From 1d15e9d8e4c52daea92e303eda9e85929e33b3dd Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:21 +0200 Subject: [PATCH 0001/1389] coding guidelines: comply with MISRA Rule 21.15 - made explicit the copied data type Signed-off-by: Hess Nathan --- kernel/msg_q.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/msg_q.c b/kernel/msg_q.c index b315cde80e1801..b3cd959d578acb 100644 --- a/kernel/msg_q.c +++ b/kernel/msg_q.c @@ -151,7 +151,7 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout /* put message in queue */ __ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start && msgq->write_ptr < msgq->buffer_end); - (void)memcpy(msgq->write_ptr, data, msgq->msg_size); + (void)memcpy(msgq->write_ptr, (char *)data, msgq->msg_size); msgq->write_ptr += msgq->msg_size; if (msgq->write_ptr == msgq->buffer_end) { msgq->write_ptr = msgq->buffer_start; @@ -227,7 +227,7 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) if (msgq->used_msgs > 0U) { /* take first available message from queue */ - (void)memcpy(data, msgq->read_ptr, msgq->msg_size); + (void)memcpy((char *)data, msgq->read_ptr, msgq->msg_size); msgq->read_ptr += msgq->msg_size; if (msgq->read_ptr == msgq->buffer_end) { msgq->read_ptr = msgq->buffer_start; @@ -242,7 +242,7 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) /* add thread's message to queue */ __ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start && msgq->write_ptr < msgq->buffer_end); - (void)memcpy(msgq->write_ptr, pending_thread->base.swap_data, + (void)memcpy(msgq->write_ptr, (char *)pending_thread->base.swap_data, msgq->msg_size); msgq->write_ptr += msgq->msg_size; if (msgq->write_ptr == msgq->buffer_end) { @@ -302,7 +302,7 @@ int z_impl_k_msgq_peek(struct k_msgq *msgq, void *data) if (msgq->used_msgs > 0U) { /* take first available message from queue */ - (void)memcpy(data, msgq->read_ptr, msgq->msg_size); + (void)memcpy((char *)data, msgq->read_ptr, msgq->msg_size); result = 0; } else { /* don't wait for a message to become available */ From 5a28b3e997bea7ba33e8b895bc160e0f84772c98 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:21 +0200 Subject: [PATCH 0002/1389] coding guidelines: comply with MISRA Rule 20.9 - avoid to use undefined macros in #if expressions Signed-off-by: Hess Nathan --- include/zephyr/linker/common-ram.ld | 2 +- include/zephyr/logging/log_msg.h | 2 +- include/zephyr/sys/__assert.h | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/zephyr/linker/common-ram.ld b/include/zephyr/linker/common-ram.ld index c0d2d444ea5e31..0f750f93cd8b5e 100644 --- a/include/zephyr/linker/common-ram.ld +++ b/include/zephyr/linker/common-ram.ld @@ -43,7 +43,7 @@ __device_states_end = .; } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) -#if CONFIG_PM_DEVICE +#ifdef CONFIG_PM_DEVICE ITERABLE_SECTION_RAM(pm_device_slots, Z_LINK_ITERABLE_SUBALIGN) #endif diff --git a/include/zephyr/logging/log_msg.h b/include/zephyr/logging/log_msg.h index 0d0094ab82a211..2f6b3a04616d85 100644 --- a/include/zephyr/logging/log_msg.h +++ b/include/zephyr/logging/log_msg.h @@ -72,7 +72,7 @@ struct log_msg_hdr { /* Attempting to keep best alignment. When address is 64 bit and timestamp 32 * swap the order to have 16 byte header instead of 24 byte. */ -#if (INTPTR_MAX > INT32_MAX) && !CONFIG_LOG_TIMESTAMP_64BIT +#if (INTPTR_MAX > INT32_MAX) && !defined(CONFIG_LOG_TIMESTAMP_64BIT) log_timestamp_t timestamp; const void *source; #else diff --git a/include/zephyr/sys/__assert.h b/include/zephyr/sys/__assert.h index fc0b9476ea65cc..9f1ab977beef13 100644 --- a/include/zephyr/sys/__assert.h +++ b/include/zephyr/sys/__assert.h @@ -12,15 +12,21 @@ #ifdef CONFIG_ASSERT #ifndef __ASSERT_ON +#ifdef CONFIG_ASSERT_LEVEL #define __ASSERT_ON CONFIG_ASSERT_LEVEL #endif #endif +#endif #ifdef CONFIG_FORCE_NO_ASSERT #undef __ASSERT_ON #define __ASSERT_ON 0 #endif +#ifndef __ASSERT_ON +#define __ASSERT_ON 0 +#endif + #ifdef __cplusplus extern "C" { #endif From 5a3cb4c89ad861254432d7dc7167765f4dea574b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:21 +0200 Subject: [PATCH 0003/1389] tests: bsim: Bluetooth: Reduce multiple id test execution iterations Reduce the iterations in multiple id multiple simultaneous connections test, and tune the buffer counts to catch any buffer leak related regressions. Signed-off-by: Vinayak Kariappa Chettimada --- tests/bsim/bluetooth/ll/multiple_id/prj.conf | 8 +++++++- tests/bsim/bluetooth/ll/multiple_id/src/main.c | 9 +++++++-- .../bluetooth/ll/multiple_id/tests_scripts/multiple.sh | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/bsim/bluetooth/ll/multiple_id/prj.conf b/tests/bsim/bluetooth/ll/multiple_id/prj.conf index 0fb600d717c2f0..173fc296c7c1f1 100644 --- a/tests/bsim/bluetooth/ll/multiple_id/prj.conf +++ b/tests/bsim/bluetooth/ll/multiple_id/prj.conf @@ -34,7 +34,13 @@ CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 # Each PHY update can pause connections for 6 interval hence to let other # parallel connection establishment to succeed increase Rx buffer count. -CONFIG_BT_CTLR_RX_BUFFERS=6 +# A minimum of 1 Rx buffer is required to receive data PDU, during control +# procedures Rx buffer could be held, preventing new connections to be +# established, a value of 3 is tuned based on this test case execution for 2 +# iterations. If there is buffer leak, simulated by using value of 2 here, the +# test is failing. +# If there is buffer leak, this test now should catch it. +CONFIG_BT_CTLR_RX_BUFFERS=3 # Provide enough spacing between connections so that multiple peripheral roles # when connected to a single peer device (peripheral_identity sample) have diff --git a/tests/bsim/bluetooth/ll/multiple_id/src/main.c b/tests/bsim/bluetooth/ll/multiple_id/src/main.c index 717bc637b1c4c9..e9aff70db86cb9 100644 --- a/tests/bsim/bluetooth/ll/multiple_id/src/main.c +++ b/tests/bsim/bluetooth/ll/multiple_id/src/main.c @@ -18,7 +18,12 @@ #include "time_machine.h" #include "bstests.h" -#define ITERATIONS 10 +/* The test case is performing 250 simultaneous connections and managing + * parallel control procedures utilizing the available/configured minimum + * buffer counts. Hence, two iterations of connect-disconnect should be + * sufficient to catch any regressions/buffer leaks. + */ +#define ITERATIONS 2 int init_central(uint8_t iterations); int init_peripheral(uint8_t iterations); @@ -81,7 +86,7 @@ static void test_peripheral_main(void) static void test_multiple_init(void) { - bst_ticker_set_next_tick_absolute(4500e6); + bst_ticker_set_next_tick_absolute(1500e6); bst_result = In_progress; } diff --git a/tests/bsim/bluetooth/ll/multiple_id/tests_scripts/multiple.sh b/tests/bsim/bluetooth/ll/multiple_id/tests_scripts/multiple.sh index 2d9eaece5efd1b..de272fdd0fe9cc 100755 --- a/tests/bsim/bluetooth/ll/multiple_id/tests_scripts/multiple.sh +++ b/tests/bsim/bluetooth/ll/multiple_id/tests_scripts/multiple.sh @@ -7,7 +7,7 @@ source ${ZEPHYR_BASE}/tests/bsim/sh_common.source # Multiple connection between two devices with multiple peripheral identity simulation_id="multiple" verbosity_level=2 -EXECUTE_TIMEOUT=2200 +EXECUTE_TIMEOUT=1600 cd ${BSIM_OUT_PATH}/bin @@ -18,6 +18,6 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_multiple_id_prj_conf\ -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ - -D=2 -sim_length=4500e6 $@ -argschannel -at=40 + -D=2 -sim_length=1800e6 $@ -argschannel -at=40 wait_for_background_jobs From b415d20447eb9bd2971fb1c8fdb8bbebcae34f62 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:21 +0200 Subject: [PATCH 0004/1389] coding guidelines: comply with MISRA C:2012 Rule 11.2 avoid convert pointers to incomplete type using the pointer to first item Signed-off-by: Hess Nathan --- kernel/include/mmu.h | 4 ++-- kernel/userspace.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index 4650b65bc8979d..590852e4e37068 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -36,8 +36,8 @@ #define Z_VIRT_RAM_END (Z_VIRT_RAM_START + Z_VIRT_RAM_SIZE) /* Boot-time virtual location of the kernel image. */ -#define Z_KERNEL_VIRT_START ((uint8_t *)(&z_mapped_start)) -#define Z_KERNEL_VIRT_END ((uint8_t *)(&z_mapped_end)) +#define Z_KERNEL_VIRT_START ((uint8_t *)&z_mapped_start[0]) +#define Z_KERNEL_VIRT_END ((uint8_t *)&z_mapped_end[0]) #define Z_KERNEL_VIRT_SIZE (Z_KERNEL_VIRT_END - Z_KERNEL_VIRT_START) #define Z_VM_OFFSET ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ diff --git a/kernel/userspace.c b/kernel/userspace.c index 0d9a437570a053..fec564188f883b 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -929,8 +929,8 @@ static int app_shmem_bss_zero(void) struct z_app_region *region, *end; - end = (struct z_app_region *)&__app_shmem_regions_end; - region = (struct z_app_region *)&__app_shmem_regions_start; + end = (struct z_app_region *)&__app_shmem_regions_end[0]; + region = (struct z_app_region *)&__app_shmem_regions_start[0]; for ( ; region < end; region++) { #if defined(CONFIG_DEMAND_PAGING) && !defined(CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT) From 93a0ca70b1143fa548d51fe1c138154751aeea1a Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Sun, 26 May 2024 22:38:21 +0200 Subject: [PATCH 0005/1389] coding guidelines: comply with MISRA C:2012 Rule 12.2 - explicit with a cast the destination bitwidth of left shift ensuring to not break DTS Signed-off-by: Abramo Bagnara --- include/zephyr/dt-bindings/pcie/pcie.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/zephyr/dt-bindings/pcie/pcie.h b/include/zephyr/dt-bindings/pcie/pcie.h index 2cf6698be53d92..2cd4fdd663edbd 100644 --- a/include/zephyr/dt-bindings/pcie/pcie.h +++ b/include/zephyr/dt-bindings/pcie/pcie.h @@ -26,9 +26,15 @@ #define PCIE_ID_DEV_SHIFT 16U #define PCIE_ID_DEV_MASK 0xFFFFU +#ifdef __DTS__ +#define CAST(type, v) (v) +#else +#define CAST(type, v) ((type)(v)) +#endif + #define PCIE_ID(vend, dev) \ ((((vend) & PCIE_ID_VEND_MASK) << PCIE_ID_VEND_SHIFT) | \ - (((dev) & PCIE_ID_DEV_MASK) << PCIE_ID_DEV_SHIFT)) + (CAST(uint32_t, (dev) & PCIE_ID_DEV_MASK) << PCIE_ID_DEV_SHIFT)) #define PCIE_ID_TO_VEND(id) (((id) >> PCIE_ID_VEND_SHIFT) & PCIE_ID_VEND_MASK) #define PCIE_ID_TO_DEV(id) (((id) >> PCIE_ID_DEV_SHIFT) & PCIE_ID_DEV_MASK) From 066ec8ffa6426ed1b91b5751357fb6e3a30a5e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0006/1389] tests: drivers: spi: spi_slave: Add nrf54h20dk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add configuration for nrf54h20dk to the test. Signed-off-by: Krzysztof Chruściński --- .../boards/nrf54h20dk_nrf54h20_common.dtsi | 79 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 14 ++++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 14 ++++ tests/drivers/spi/spi_slave/src/main.c | 1 + tests/drivers/spi/spi_slave/testcase.yaml | 4 +- 5 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_common.dtsi create mode 100644 tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 00000000000000..0a9425cc2f9d6a --- /dev/null +++ b/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi130_default_alt: spi130_default_alt { + group1 { + psels = , + , + ; + }; + }; + + spi130_sleep_alt: spi130_sleep_alt { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + spis131_default_alt: spis131_default_alt { + group1 { + psels = , + , + , + ; + }; + }; + + spis131_sleep_alt: spis131_sleep_alt { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + +}; + +&gpio0 { + status = "okay"; +}; + +&gpiote130 { + status = "okay"; + owned-channels = <7>; +}; + +dut_spi: &spi130 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi130_default_alt>; + pinctrl-1 = <&spi130_sleep_alt>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <500000>; + }; +}; + +dut_spis: &spi131 { + compatible = "nordic,nrf-spis"; + status = "okay"; + def-char = <0x00>; + pinctrl-0 = <&spis131_default_alt>; + pinctrl-1 = <&spis131_sleep_alt>; + pinctrl-names = "default", "sleep"; + /delete-property/rx-delay-supported; + /delete-property/rx-delay; +}; diff --git a/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..ff337ebdec4831 --- /dev/null +++ b/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&dut_spi { + memory-regions = <&cpuapp_dma_region>; +}; + +&dut_spis { + memory-regions = <&cpuapp_dma_region>; +}; diff --git a/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000000..936bd5b15d5419 --- /dev/null +++ b/tests/drivers/spi/spi_slave/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&dut_spi { + memory-regions = <&cpurad_dma_region>; +}; + +&dut_spis { + memory-regions = <&cpurad_dma_region>; +}; diff --git a/tests/drivers/spi/spi_slave/src/main.c b/tests/drivers/spi/spi_slave/src/main.c index 7a6ca1b7545632..5f441480c12f6f 100644 --- a/tests/drivers/spi/spi_slave/src/main.c +++ b/tests/drivers/spi/spi_slave/src/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #define SPI_MODE (SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE) diff --git a/tests/drivers/spi/spi_slave/testcase.yaml b/tests/drivers/spi/spi_slave/testcase.yaml index 1b5a46cc9e69d8..c38b3e729521f4 100644 --- a/tests/drivers/spi/spi_slave/testcase.yaml +++ b/tests/drivers/spi/spi_slave/testcase.yaml @@ -5,6 +5,8 @@ tests: harness: ztest harness_config: fixture: gpio_spi_loopback - platform_allow: nrf52840dk/nrf52840 nrf54l15pdk/nrf54l15/cpuapp + platform_allow: | + nrf52840dk/nrf52840 nrf54l15pdk/nrf54l15/cpuapp nrf54h20dk/nrf54h20/cpuapp + nrf54h20dk/nrf54h20/cpurad integration_platforms: - nrf52840dk/nrf52840 From b20ad651a44dd96bd07331f7d5f33b95ba7dbc01 Mon Sep 17 00:00:00 2001 From: Omkar Kulkarni Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0007/1389] Bluetooth: Mesh: Update models metadata API This commit updates models metadata API to simplify the usage and removes the metadata pointer in health server model context. Signed-off-by: Omkar Kulkarni --- doc/releases/migration-guide-3.7.rst | 8 +++ include/zephyr/bluetooth/mesh/access.h | 14 ++-- include/zephyr/bluetooth/mesh/health_srv.h | 23 +++---- include/zephyr/bluetooth/mesh/shell.h | 3 + subsys/bluetooth/mesh/access.c | 4 +- subsys/bluetooth/mesh/shell/shell.c | 7 +- tests/bluetooth/mesh_shell/src/main.c | 3 +- tests/bluetooth/tester/src/btp_mesh.c | 74 ++++++++++++++++++---- tests/bsim/bluetooth/mesh/src/mesh_test.c | 13 +++- tests/bsim/bluetooth/mesh/src/test_lcd.c | 2 +- 10 files changed, 112 insertions(+), 39 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 8d15411be74ef4..022a8699ee9c2b 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -210,6 +210,14 @@ Bluetooth Mesh got ``const`` qualifier too. The model's metadata structure and metadata raw value can be declared as permanent constants in the non-volatile memory. (:github:`69679`) +* The model metadata pointer declaration of :c:struct:`bt_mesh_model` has been changed + to a single ``const *`` and redundant metadata pointer from :c:struct:`bt_mesh_health_srv` + is removed. Consequently, :code:`BT_MESH_MODEL_HEALTH_SRV` definition is changed + to use variable argument notation. (:github:`71281`). Now, when your implementation + supports :kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_SRV` and when you need to + specify metadata for Health Server model, simply pass metadata as the last argument + to the :code:`BT_MESH_MODEL_HEALTH_SRV` macro, otherwise omit the last argument. + Bluetooth Audio =============== diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index 5d2d661710e919..f1fca02783e87e 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -506,7 +506,8 @@ struct bt_mesh_model_op { * @param _pub Model publish parameters. * @param _user_data User data for the model. * @param _cb Callback structure, or NULL to keep no callbacks. - * @param _metadata Metadata structure. + * @param _metadata Metadata structure. Used if @kconfig{CONFIG_BT_MESH_LARGE_COMP_DATA_SRV} + * is enabled. */ #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) #define BT_MESH_MODEL_METADATA_CB(_id, _op, _pub, _user_data, _cb, _metadata) \ @@ -560,8 +561,10 @@ struct bt_mesh_model_op { * @param _pub Model publish parameters. * @param _user_data User data for the model. * @param _cb Callback structure, or NULL to keep no callbacks. - * @param _metadata Metadata structure. + * @param _metadata Metadata structure. Used if @kconfig{CONFIG_BT_MESH_LARGE_COMP_DATA_SRV} + * is enabled. */ +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) #define BT_MESH_MODEL_VND_METADATA_CB(_company, _id, _op, _pub, _user_data, _cb, _metadata) \ { \ .vnd.company = (_company), \ @@ -577,7 +580,10 @@ struct bt_mesh_model_op { .cb = _cb, \ .metadata = _metadata, \ } - +#else +#define BT_MESH_MODEL_VND_METADATA_CB(_company, _id, _op, _pub, _user_data, _cb, _metadata) \ + BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, _cb) +#endif /** * @brief Composition data SIG model entry. * @@ -924,7 +930,7 @@ struct bt_mesh_model { #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) || defined(__DOXYGEN__) /* Pointer to the array of model metadata entries. */ - const struct bt_mesh_models_metadata_entry * const * const metadata; + const struct bt_mesh_models_metadata_entry * const metadata; #endif }; diff --git a/include/zephyr/bluetooth/mesh/health_srv.h b/include/zephyr/bluetooth/mesh/health_srv.h index 9eb4008b846c59..3833c750e2bd49 100644 --- a/include/zephyr/bluetooth/mesh/health_srv.h +++ b/include/zephyr/bluetooth/mesh/health_srv.h @@ -156,11 +156,6 @@ struct bt_mesh_health_srv { /** Attention Timer state */ struct k_work_delayable attn_timer; - -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV - /** Pointer to the array with Health Test Info Metadata */ - const struct bt_mesh_models_metadata_entry *metadata; -#endif }; /** @@ -171,18 +166,18 @@ struct bt_mesh_health_srv { * * @param srv Pointer to a unique struct bt_mesh_health_srv. * @param pub Pointer to a unique struct bt_mesh_model_pub. + * @param ... Optional Health Server metadata if application is compiled with + * Large Composition Data Server support, otherwise this parameter + * is ignored. * * @return New mesh model instance. */ -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV -#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \ - BT_MESH_MODEL_METADATA_CB(BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_op, \ - pub, srv, &bt_mesh_health_srv_cb, &(srv)->metadata) -#else -#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_op, \ - pub, srv, &bt_mesh_health_srv_cb) -#endif +#define BT_MESH_MODEL_HEALTH_SRV(srv, pub, ...) \ + BT_MESH_MODEL_METADATA_CB(BT_MESH_MODEL_ID_HEALTH_SRV, \ + bt_mesh_health_srv_op, \ + pub, \ + srv, \ + &bt_mesh_health_srv_cb, __VA_ARGS__) /** * diff --git a/include/zephyr/bluetooth/mesh/shell.h b/include/zephyr/bluetooth/mesh/shell.h index 1c3964075212bd..27879cdfad0778 100644 --- a/include/zephyr/bluetooth/mesh/shell.h +++ b/include/zephyr/bluetooth/mesh/shell.h @@ -38,6 +38,9 @@ struct bt_mesh_shell_target { /** @brief External reference to health server */ extern struct bt_mesh_health_srv bt_mesh_shell_health_srv; +/** @brief External reference to health server metadata */ +extern const struct bt_mesh_models_metadata_entry health_srv_meta[]; + /** @brief External reference to health client */ extern struct bt_mesh_health_cli bt_mesh_shell_health_cli; diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 0ad4e7164adc5d..558836504d67bd 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -220,7 +220,7 @@ static size_t metadata_model_size(const struct bt_mesh_model *mod, size += sizeof(uint8_t); - for (entry = *mod->metadata; entry && entry->len; ++entry) { + for (entry = mod->metadata; entry && entry->len; ++entry) { size += sizeof(entry->len) + sizeof(entry->id) + entry->len; } @@ -286,7 +286,7 @@ static int metadata_add_model(const struct bt_mesh_model *mod, count_ptr = data_buf_add_u8_offset(buf, 0, offset); if (mod->metadata) { - for (entry = *mod->metadata; entry && entry->data != NULL; ++entry) { + for (entry = mod->metadata; entry && entry->data != NULL; ++entry) { data_buf_add_le16_offset(buf, entry->len, offset); data_buf_add_le16_offset(buf, entry->id, offset); data_buf_add_mem_offset(buf, entry->data, entry->len, offset); diff --git a/subsys/bluetooth/mesh/shell/shell.c b/subsys/bluetooth/mesh/shell/shell.c index 78c503c29ac901..511f50a78f92b6 100644 --- a/subsys/bluetooth/mesh/shell/shell.c +++ b/subsys/bluetooth/mesh/shell/shell.c @@ -144,13 +144,13 @@ static const struct bt_mesh_health_srv_cb health_srv_cb = { }; #endif /* CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE */ -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) static const uint8_t health_tests[] = { BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_LF, 6, 0x01, 0x02, 0x03, 0x04, 0x34, 0x15), BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_NORDIC_SEMI, 3, 0x01, 0x02, 0x03), }; -static const struct bt_mesh_models_metadata_entry health_srv_meta[] = { +const struct bt_mesh_models_metadata_entry health_srv_meta[] = { BT_MESH_HEALTH_TEST_INFO_METADATA(health_tests), BT_MESH_MODELS_METADATA_END, }; @@ -160,9 +160,6 @@ struct bt_mesh_health_srv bt_mesh_shell_health_srv = { #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE) .cb = &health_srv_cb, #endif -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV - .metadata = health_srv_meta, -#endif }; #if defined(CONFIG_BT_MESH_SHELL_HEALTH_CLI) diff --git a/tests/bluetooth/mesh_shell/src/main.c b/tests/bluetooth/mesh_shell/src/main.c index f5dbdc41b40558..2428b38a19f625 100644 --- a/tests/bluetooth/mesh_shell/src/main.c +++ b/tests/bluetooth/mesh_shell/src/main.c @@ -46,7 +46,8 @@ BT_MESH_SHELL_HEALTH_PUB_DEFINE(health_pub); static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), - BT_MESH_MODEL_HEALTH_SRV(&bt_mesh_shell_health_srv, &health_pub), + BT_MESH_MODEL_HEALTH_SRV(&bt_mesh_shell_health_srv, &health_pub, + health_srv_meta), BT_MESH_MODEL_HEALTH_CLI(&bt_mesh_shell_health_cli), #if defined(CONFIG_BT_MESH_DFD_SRV) BT_MESH_MODEL_DFD_SRV(&dfd_srv), diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 65b3a81c6e2c86..3beced415da42b 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -684,7 +684,6 @@ static struct bt_mesh_health_cli health_cli = { }; -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV static uint8_t health_tests[] = { BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_LF, 6, 0x01, 0x02, 0x03, 0x04, 0x34, 0x15), @@ -718,13 +717,9 @@ static const struct bt_mesh_models_metadata_entry health_srv_meta_alt[] = { }, BT_MESH_MODELS_METADATA_END, }; -#endif static struct bt_mesh_health_srv health_srv = { .cb = &health_srv_cb, -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV - .metadata = health_srv_meta, -#endif }; BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX); @@ -1027,7 +1022,63 @@ static uint8_t proxy_solicit(const void *cmd, uint16_t cmd_len, static const struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), - BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), + BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub, health_srv_meta), + BT_MESH_MODEL_HEALTH_CLI(&health_cli), +#if defined(CONFIG_BT_MESH_SAR_CFG_SRV) + BT_MESH_MODEL_SAR_CFG_SRV, +#endif +#if defined(CONFIG_BT_MESH_SAR_CFG_CLI) + BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli), +#endif +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV) + BT_MESH_MODEL_LARGE_COMP_DATA_SRV, +#endif +#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_CLI) + BT_MESH_MODEL_LARGE_COMP_DATA_CLI(&lcd_cli), +#endif +#if defined(CONFIG_BT_MESH_OP_AGG_SRV) + BT_MESH_MODEL_OP_AGG_SRV, +#endif +#if defined(CONFIG_BT_MESH_OP_AGG_CLI) + BT_MESH_MODEL_OP_AGG_CLI, +#endif +#if defined(CONFIG_BT_MESH_RPR_CLI) + BT_MESH_MODEL_RPR_CLI(&rpr_cli), +#endif +#if defined(CONFIG_BT_MESH_RPR_SRV) + BT_MESH_MODEL_RPR_SRV, +#endif +#if defined(CONFIG_BT_MESH_DFD_SRV) + BT_MESH_MODEL_DFD_SRV(&dfd_srv), +#endif +#if defined(CONFIG_BT_MESH_DFU_SRV) + BT_MESH_MODEL_DFU_SRV(&dfu_srv), +#endif +#if defined(CONFIG_BT_MESH_BLOB_CLI) && !defined(CONFIG_BT_MESH_DFD_SRV) + BT_MESH_MODEL_BLOB_CLI(&blob_cli), +#endif +#if defined(CONFIG_BT_MESH_PRIV_BEACON_SRV) + BT_MESH_MODEL_PRIV_BEACON_SRV, +#endif +#if defined(CONFIG_BT_MESH_PRIV_BEACON_CLI) + BT_MESH_MODEL_PRIV_BEACON_CLI(&priv_beacon_cli), +#endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) + BT_MESH_MODEL_OD_PRIV_PROXY_CLI(&od_priv_proxy_cli), +#endif +#if defined(CONFIG_BT_MESH_SOL_PDU_RPL_CLI) + BT_MESH_MODEL_SOL_PDU_RPL_CLI(&srpl_cli), +#endif +#if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) + BT_MESH_MODEL_OD_PRIV_PROXY_SRV, +#endif + +}; + +static const struct bt_mesh_model root_models_alt[] = { + BT_MESH_MODEL_CFG_SRV, + BT_MESH_MODEL_CFG_CLI(&cfg_cli), + BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub, health_srv_meta_alt), BT_MESH_MODEL_HEALTH_CLI(&health_cli), #if defined(CONFIG_BT_MESH_SAR_CFG_SRV) BT_MESH_MODEL_SAR_CFG_SRV, @@ -1100,6 +1151,10 @@ static const struct bt_mesh_elem elements[] = { BT_MESH_ELEM(0, root_models, vnd_models), }; +static const struct bt_mesh_elem elements_alt[] = { + BT_MESH_ELEM(0, root_models_alt, vnd_models), +}; + static void link_open(bt_mesh_prov_bearer_t bearer) { struct btp_mesh_prov_link_open_ev ev; @@ -1247,8 +1302,8 @@ static const struct bt_mesh_comp comp = { static const struct bt_mesh_comp comp_alt = { .cid = CID_LOCAL, - .elem = elements, - .elem_count = ARRAY_SIZE(elements), + .elem = elements_alt, + .elem_count = ARRAY_SIZE(elements_alt), .vid = 2, }; @@ -1414,9 +1469,6 @@ static uint8_t init(const void *cmd, uint16_t cmd_len, err = bt_mesh_init(&prov, &comp); } else { LOG_WRN("Loading alternative comp data"); -#ifdef CONFIG_BT_MESH_LARGE_COMP_DATA_SRV - health_srv.metadata = health_srv_meta_alt; -#endif err = bt_mesh_init(&prov, &comp_alt); } diff --git a/tests/bsim/bluetooth/mesh/src/mesh_test.c b/tests/bsim/bluetooth/mesh/src/mesh_test.c index a3a562842d29a1..6865e5202ba4dc 100644 --- a/tests/bsim/bluetooth/mesh/src/mesh_test.c +++ b/tests/bsim/bluetooth/mesh/src/mesh_test.c @@ -10,6 +10,8 @@ #include #define LOG_MODULE_NAME mesh_test +#define COMPANY_ID_LF 0x05F1 +#define COMPANY_ID_NORDIC_SEMI 0x05F9 #include LOG_MODULE_REGISTER(LOG_MODULE_NAME); @@ -162,6 +164,15 @@ static struct bt_mesh_health_srv health_srv; static struct bt_mesh_model_pub health_pub = { .msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX), }; +static const uint8_t health_tests[] = { + BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_LF, 6, 0x01, 0x02, 0x03, 0x04, 0x34, 0x15), + BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_NORDIC_SEMI, 3, 0x01, 0x02, 0x03), +}; + +const struct bt_mesh_models_metadata_entry health_srv_meta[] = { + BT_MESH_HEALTH_TEST_INFO_METADATA(health_tests), + BT_MESH_MODELS_METADATA_END, +}; #if defined(CONFIG_BT_MESH_SAR_CFG) static struct bt_mesh_sar_cfg_cli sar_cfg_cli; @@ -179,7 +190,7 @@ static const struct bt_mesh_model models[] = { BT_MESH_MODEL_CFG_SRV, BT_MESH_MODEL_CFG_CLI(&cfg_cli), BT_MESH_MODEL_CB(TEST_MOD_ID, model_op, &pub, NULL, &test_model_cb), - BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), + BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub, health_srv_meta), #if defined(CONFIG_BT_MESH_SAR_CFG) BT_MESH_MODEL_SAR_CFG_SRV, BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli), diff --git a/tests/bsim/bluetooth/mesh/src/test_lcd.c b/tests/bsim/bluetooth/mesh/src/test_lcd.c index cd6a515294e924..c31c5d43f72d2e 100644 --- a/tests/bsim/bluetooth/mesh/src/test_lcd.c +++ b/tests/bsim/bluetooth/mesh/src/test_lcd.c @@ -86,7 +86,7 @@ static void test_args_parse(int argc, char *argv[]) bs_args_parse_all_cmd_line(argc, argv, args_struct); } -static const struct bt_mesh_models_metadata_entry *dummy_meta_entry[] = {}; +static const struct bt_mesh_models_metadata_entry dummy_meta_entry[1]; /* Empty elements to create large composition/meta data */ #define DUMMY_ELEM(i, _) BT_MESH_ELEM((i) + 2, \ From 37556ca394c38b2d305f123301f156c566cf0bbb Mon Sep 17 00:00:00 2001 From: Mykola Kvach Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0008/1389] drivers: sdhc: add support of Renesas MMC driver Add basic functionality of Renesas SD/MMC driver. It can be used for both gen3 and gen4 R-car boards, but tested only with H3ULCB, Salvator XS M3 and Spider boards. This driver working with SDHC subsystem. The driver supports regularal reading/writing throught SD/MMC controller buffer, DMA mode w/o interrupts and timing tuning. Add gpio5 and sd0 nodes to h3ulcb and salvator xs which are needed for working with SD cards. The GPIO node is needed for switching voltage on SD card through gpio regulator driver. Notes: * the driver doesn't support SPI mode; * SCC tuning and DMA mode based on IRQs are enabled by default; * an address of a data buffer has to be aligned to 128 bytes if it is not, driver will use non-DMA mode automatically; * Renesas MMC DMAC doesn't support 64-bit DMA addresses, so for case when we have 64-bit xref data address we use non-DMA mode; * SD/MMC controller supports block size between 512 and 1 with a lot of restrictions, more details you can find in code; * support of HS400 mode isn't implemented inside driver. Signed-off-by: Mykola Kvach --- drivers/sdhc/CMakeLists.txt | 1 + drivers/sdhc/Kconfig | 1 + drivers/sdhc/Kconfig.rcar | 42 + drivers/sdhc/rcar_mmc.c | 2223 +++++++++++++++++++++++ drivers/sdhc/rcar_mmc_registers.h | 221 +++ dts/arm64/renesas/rcar_gen3_ca57.dtsi | 47 +- dts/bindings/mmc/renesas,rcar-emmc.yaml | 63 + 7 files changed, 2596 insertions(+), 2 deletions(-) create mode 100644 drivers/sdhc/Kconfig.rcar create mode 100644 drivers/sdhc/rcar_mmc.c create mode 100644 drivers/sdhc/rcar_mmc_registers.h create mode 100644 dts/bindings/mmc/renesas,rcar-emmc.yaml diff --git a/drivers/sdhc/CMakeLists.txt b/drivers/sdhc/CMakeLists.txt index b8d7e21bfbc2f2..42985f873f1f08 100644 --- a/drivers/sdhc/CMakeLists.txt +++ b/drivers/sdhc/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_IMX_USDHC imx_usdhc.c) zephyr_library_sources_ifdef(CONFIG_SPI_SDHC sdhc_spi.c) zephyr_library_sources_ifdef(CONFIG_MCUX_SDIF mcux_sdif.c) +zephyr_library_sources_ifdef(CONFIG_RCAR_MMC rcar_mmc.c) zephyr_library_sources_ifdef(CONFIG_SAM_HSMCI sam_hsmci.c) zephyr_library_sources_ifdef(CONFIG_INTEL_EMMC_HOST intel_emmc_host.c) zephyr_library_sources_ifdef(CONFIG_SDHC_INFINEON_CAT1 ifx_cat1_sdio.c) diff --git a/drivers/sdhc/Kconfig b/drivers/sdhc/Kconfig index 2a121839cdb0c8..b6b1276207b955 100644 --- a/drivers/sdhc/Kconfig +++ b/drivers/sdhc/Kconfig @@ -12,6 +12,7 @@ source "drivers/sdhc/Kconfig.ifx_cat1" source "drivers/sdhc/Kconfig.imx" source "drivers/sdhc/Kconfig.spi" source "drivers/sdhc/Kconfig.mcux_sdif" +source "drivers/sdhc/Kconfig.rcar" source "drivers/sdhc/Kconfig.sam_hsmci" source "drivers/sdhc/Kconfig.intel" source "drivers/sdhc/Kconfig.sdhc_cdns" diff --git a/drivers/sdhc/Kconfig.rcar b/drivers/sdhc/Kconfig.rcar new file mode 100644 index 00000000000000..f5d57a4bb03c33 --- /dev/null +++ b/drivers/sdhc/Kconfig.rcar @@ -0,0 +1,42 @@ +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config RCAR_MMC + bool "Renesas Rcar MMC driver" + default y + depends on DT_HAS_RENESAS_RCAR_MMC_ENABLED + select SDHC_SUPPORTS_NATIVE_MODE + select REGULATOR + select GPIO + select SDHC_SUPPORTS_UHS if SDMMC_STACK + help + Renesas Rcar MMC driver. + +if RCAR_MMC + +config RCAR_MMC_DMA_SUPPORT + bool "Internal DMA support for Renesas Rcar MMC driver" + select CACHE_MANAGEMENT + select DCACHE + default y + help + Internal DMA support for Renesas Rcar MMC driver. + +config RCAR_MMC_SCC_SUPPORT + bool "Support of SCC" + default y + help + Enable support of Sampling Clock Controller for Renesas Rcar MMC driver. + +if RCAR_MMC_DMA_SUPPORT + +config SDHC_BUFFER_ALIGNMENT + default 128 + +config RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + bool "Internal DMA IRQ driven support for Renesas Rcar MMC driver" + default y + +endif # RCAR_MMC_DMA_SUPPORT + +endif # RCAR_MMC diff --git a/drivers/sdhc/rcar_mmc.c b/drivers/sdhc/rcar_mmc.c new file mode 100644 index 00000000000000..2e5d20ee86adfa --- /dev/null +++ b/drivers/sdhc/rcar_mmc.c @@ -0,0 +1,2223 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rcar_mmc + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rcar_mmc_registers.h" + +#define PINCTRL_STATE_UHS PINCTRL_STATE_PRIV_START + +/** + * @note we don't need any locks here, because SDHC subsystem cares about it + */ + +LOG_MODULE_REGISTER(rcar_mmc, CONFIG_LOG_DEFAULT_LEVEL); + +#define MMC_POLL_FLAGS_TIMEOUT_US 100000 +#define MMC_POLL_FLAGS_ONE_CYCLE_TIMEOUT_US 1 +#define MMC_BUS_CLOCK_FREQ 800000000 +/* + * SD/MMC clock for Gen3/Gen4 R-car boards can't be equal to 208 MHz, + * but we can run SDR104 on lower frequencies: + * "SDR104: UHS-I 1.8V signaling, Frequency up to 208 MHz" + * so according to SD card standard it is possible to use lower frequencies, + * and we need to pass check of frequency in sdmmc in order to use sdr104 mode. + * This is the reason why it is needed this correction. + */ +#define MMC_MAX_FREQ_CORRECTION 8000000 + +#ifdef CONFIG_RCAR_MMC_DMA_SUPPORT +#define ALIGN_BUF_DMA __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT) +#else +#define ALIGN_BUF_DMA +#endif + +/** + * @brief Renesas MMC host controller driver data + * + */ +struct mmc_rcar_data { + DEVICE_MMIO_RAM; /* Must be first */ + struct sdhc_io host_io; + struct sdhc_host_props props; +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + struct k_sem irq_xref_fin; +#endif + + uint8_t ver; + /* in bytes, possible values are 2, 4 or 8 */ + uint8_t width_access_sd_buf0; + uint8_t ddr_mode; + uint8_t restore_cfg_after_reset; + uint8_t is_last_cmd_app_cmd; /* ACMD55 */ + +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + uint8_t manual_retuning; + uint8_t tuning_buf[128] ALIGN_BUF_DMA; +#endif /* CONFIG_RCAR_MMC_SCC_SUPPORT */ + uint8_t can_retune; +}; + +/** + * @brief Renesas MMC host controller driver configuration + */ +struct mmc_rcar_cfg { + DEVICE_MMIO_ROM; /* Must be first */ + struct rcar_cpg_clk cpg_clk; + struct rcar_cpg_clk bus_clk; + const struct device *cpg_dev; + const struct pinctrl_dev_config *pcfg; + const struct device *regulator_vqmmc; + const struct device *regulator_vmmc; + + uint32_t max_frequency; + +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + void (*irq_config_func)(const struct device *dev); +#endif + + uint8_t non_removable; + uint8_t uhs_support; + uint8_t mmc_hs200_1_8v; + uint8_t mmc_hs400_1_8v; + uint8_t bus_width; + uint8_t mmc_sdr104_support; +}; + +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT +static int rcar_mmc_execute_tuning(const struct device *dev); +static int rcar_mmc_retune_if_needed(const struct device *dev, bool request_retune); +#endif +static int rcar_mmc_disable_scc(const struct device *dev); + +static uint32_t rcar_mmc_read_reg32(const struct device *dev, uint32_t reg) +{ + return sys_read32(DEVICE_MMIO_GET(dev) + reg); +} + +static void rcar_mmc_write_reg32(const struct device *dev, uint32_t reg, uint32_t val) +{ + sys_write32(val, DEVICE_MMIO_GET(dev) + reg); +} + +/* cleanup SD card interrupt flag register and mask their interrupts */ +static inline void rcar_mmc_reset_and_mask_irqs(const struct device *dev) +{ + struct mmc_rcar_data *data = dev->data; + + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO1, 0); + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO1_MASK, ~0); + + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_CLEAR); + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO2_MASK, ~0); + +#ifdef CONFIG_RCAR_MMC_DMA_SUPPORT + /* default value of Seq suspend should be 0 */ + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO1_MASK, 0xfffffeff); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO1, 0x0); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO2_MASK, 0xffffffff); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO2, 0x0); +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + k_sem_reset(&data->irq_xref_fin); +#endif +#endif /* CONFIG_RCAR_MMC_DMA_SUPPORT */ +} + +/** + * @brief check if MMC is busy + * + * This check should generally be implemented as checking the controller + * state. No MMC commands need to be sent. + * + * @param dev MMC device + * @retval 0 card is not busy + * @retval 1 card is busy + * @retval -EINVAL: the dev pointer is NULL + */ +static int rcar_mmc_card_busy(const struct device *dev) +{ + uint32_t reg; + + if (!dev) { + return -EINVAL; + } + + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_INFO2); + return (reg & RCAR_MMC_INFO2_DAT0) ? 0 : 1; +} + +/** + * @brief Check error flags inside INFO2 MMC register + * + * @note in/out parameters should be checked by a caller function + * + * @param dev MMC device + * + * @retval 0 INFO2 register hasn't errors + * @retval -ETIMEDOUT: timed out while tx/rx + * @retval -EIO: I/O error + * @retval -EILSEQ: communication out of sync + */ +static int rcar_mmc_check_errors(const struct device *dev) +{ + uint32_t info2 = rcar_mmc_read_reg32(dev, RCAR_MMC_INFO2); + + if (info2 & (RCAR_MMC_INFO2_ERR_TO | RCAR_MMC_INFO2_ERR_RTO)) { + LOG_DBG("timeout error 0x%08x", info2); + return -ETIMEDOUT; + } + + if (info2 & (RCAR_MMC_INFO2_ERR_END | RCAR_MMC_INFO2_ERR_CRC | RCAR_MMC_INFO2_ERR_IDX)) { + LOG_DBG("communication out of sync 0x%08x", info2); + return -EILSEQ; + } + + if (info2 & (RCAR_MMC_INFO2_ERR_ILA | RCAR_MMC_INFO2_ERR_ILR | RCAR_MMC_INFO2_ERR_ILW)) { + LOG_DBG("illegal access 0x%08x", info2); + return -EIO; + } + + return 0; +} + +/** + * @brief Poll flag(s) in MMC register and check errors + * + * @note in/out parameters should be checked by a caller function + * + * @param dev MMC device + * @param reg register offset relative to the base address + * @param flag polling flag(s) + * @param state state of flag(s) when we should stop polling + * @param check_errors call @ref rcar_mmc_check_errors function or not + * @param check_dma_errors check if there are DMA errors inside info2 + * @param timeout_us timeout in microseconds how long we should poll flag(s) + * + * @retval 0 poll of flag(s) was successful + * @retval -ETIMEDOUT: timed out while tx/rx + * @retval -EIO: I/O error + * @retval -EILSEQ: communication out of sync + */ +static int rcar_mmc_poll_reg_flags_check_err(const struct device *dev, unsigned int reg, + uint32_t flag, uint32_t state, bool check_errors, + bool check_dma_errors, int64_t timeout_us) +{ + int ret; + + while ((rcar_mmc_read_reg32(dev, reg) & flag) != state) { + if (timeout_us < 0) { + LOG_DBG("timeout error during polling flag(s) 0x%08x in reg 0x%08x", flag, + reg); + return -ETIMEDOUT; + } + + if (check_errors) { + ret = rcar_mmc_check_errors(dev); + if (ret) { + return ret; + } + } + + if (check_dma_errors && rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_INFO2)) { + LOG_DBG("%s: an error occurs on the DMAC channel #%u", dev->name, + (reg & RCAR_MMC_DMA_INFO2_ERR_RD) ? 1U : 0U); + return -EIO; + } + + k_usleep(MMC_POLL_FLAGS_ONE_CYCLE_TIMEOUT_US); + timeout_us -= MMC_POLL_FLAGS_ONE_CYCLE_TIMEOUT_US; + } + + return 0; +} + +/* reset DMA MMC controller */ +static inline void rcar_mmc_reset_dma(const struct device *dev) +{ + uint32_t reg = RCAR_MMC_DMA_RST_DTRAN0 | RCAR_MMC_DMA_RST_DTRAN1; + + rcar_mmc_write_reg32(dev, RCAR_MMC_EXTMODE, 0); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_RST, ~reg); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_RST, ~0); + rcar_mmc_write_reg32(dev, RCAR_MMC_EXTMODE, 1); +} + +/** + * @brief reset MMC controller state + * + * Used when the MMC has encountered an error. Resetting the MMC controller + * should clear all errors on the MMC, but does not necessarily reset I/O + * settings to boot (this can be done with @ref sdhc_set_io) + * + * @note during reset the clock input is disabled, also this call changes rate + * + * @param dev MMC controller device + * @retval 0 reset succeeded + * @retval -ETIMEDOUT: controller reset timed out + * @retval -EINVAL: the dev pointer is NULL + * @retval -EILSEQ: communication out of sync + * @retval -ENOTSUP: controller does not support I/O + * + * @details List of affected registers and their bits during the soft reset trigger: + * * RCAR_MMC_STOP all bits reset to default (0x0); + * * RCAR_MMC_INFO1 affected bits: + * * RCAR_MMC_INFO1_CMP default state 0; + * * RCAR_MMC_INFO1_RSP default state 0; + * * HPIRES Response Reception Completion (16), default state 0; + * * RCAR_MMC_INFO2 all bits reset 0, except the next: + * * RCAR_MMC_INFO2_DAT0 state unknown after reset; + * * RCAR_MMC_INFO2_SCLKDIVEN default state 1; + * * RCAR_MMC_CLKCTL affected bit(s): + * * RCAR_MMC_CLKCTL_SCLKEN default state 0; + * * RCAR_MMC_OPTION affected bits: + * * WIDTH (15) and WIDTH8 (13) set to 0, which equal to 4-bits bus; + * * Timeout Mode Select (EXTOP - 9) is set to 0; + * * Timeout Mask (TOUTMASK - 8) is set to 0; + * * Timeout Counter (TOP27-TOP24 bits 7-4) is equal to 0b1110; + * * Card Detect Time Counter (CTOP24-CTOP21 bits 3-0) is equal to 0b1110; + * * RCAR_MMC_ERR_STS1 all bits after reset 0, except the next: + * * E13 default state 1 (E12-E14 it is CRC status 0b010); + * * RCAR_MMC_ERR_STS2 all bits after reset 0; + * * IO_INFO1 all bits after reset 0; + * * RCAR_MMC_IF_MODE all bits after reset 0. + */ +static int rcar_mmc_reset(const struct device *dev) +{ + int ret = 0; + uint32_t reg; + struct mmc_rcar_data *data; + uint8_t can_retune; + + if (!dev) { + return -EINVAL; + } + + data = dev->data; + + /* + * soft reset of the host + */ + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_SOFT_RST); + reg &= ~RCAR_MMC_SOFT_RST_RSTX; + rcar_mmc_write_reg32(dev, RCAR_MMC_SOFT_RST, reg); + reg |= RCAR_MMC_SOFT_RST_RSTX; + rcar_mmc_write_reg32(dev, RCAR_MMC_SOFT_RST, reg); + + rcar_mmc_reset_and_mask_irqs(dev); + + /* + * note: DMA reset can be triggered only in case of error in + * DMA Info2 otherwise the SDIP will not accurately operate + */ +#ifdef CONFIG_RCAR_MMC_DMA_SUPPORT + rcar_mmc_reset_dma(dev); +#endif + + can_retune = data->can_retune; + if (can_retune) { + rcar_mmc_disable_scc(dev); + } + + /* note: be careful soft reset stops SDCLK */ + if (data->restore_cfg_after_reset) { + struct sdhc_io ios; + + memcpy(&ios, &data->host_io, sizeof(ios)); + memset(&data->host_io, 0, sizeof(ios)); + + data->host_io.power_mode = ios.power_mode; + + ret = sdhc_set_io(dev, &ios); + + rcar_mmc_write_reg32(dev, RCAR_MMC_STOP, RCAR_MMC_STOP_SEC); + +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + /* tune if this reset isn't invoked during tuning */ + if (can_retune && (ios.timing == SDHC_TIMING_SDR50 || + ios.timing == SDHC_TIMING_SDR104 || + ios.timing == SDHC_TIMING_HS200)) { + ret = rcar_mmc_execute_tuning(dev); + } +#endif + + return ret; + } + + data->ddr_mode = 0; + data->host_io.bus_width = SDHC_BUS_WIDTH4BIT; + data->host_io.timing = SDHC_TIMING_LEGACY; + data->is_last_cmd_app_cmd = 0; + + return 0; +} + +/** + * @brief SD Clock (SD_CLK) Output Control Enable + * + * @note in/out parameters should be checked by a caller function. + * + * @param dev MMC device + * @param enable + * false: SD_CLK output is disabled. The SD_CLK signal is fixed 0. + * true: SD_CLK output is enabled. + * + * @retval 0 I/O was configured correctly + * @retval -ETIMEDOUT: card busy flag is set during long time + */ +static int rcar_mmc_enable_clock(const struct device *dev, bool enable) +{ + int ret; + uint32_t mmc_clk_ctl = rcar_mmc_read_reg32(dev, RCAR_MMC_CLKCTL); + + if (enable == true) { + mmc_clk_ctl &= ~RCAR_MMC_CLKCTL_OFFEN; + mmc_clk_ctl |= RCAR_MMC_CLKCTL_SCLKEN; + } else { + mmc_clk_ctl |= RCAR_MMC_CLKCTL_OFFEN; + mmc_clk_ctl &= ~RCAR_MMC_CLKCTL_SCLKEN; + } + + /* + * Do not change the values of these bits + * when the CBSY bit in SD_INFO2 is 1 + */ + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_CBSY, 0, false, + false, MMC_POLL_FLAGS_TIMEOUT_US); + if (ret) { + return -ETIMEDOUT; + } + rcar_mmc_write_reg32(dev, RCAR_MMC_CLKCTL, mmc_clk_ctl); + + /* SD spec recommends at least 1 ms of delay */ + k_msleep(1); + + return 0; +} + +/** + * @brief Convert SDHC response to Renesas MMC response + * + * Function performs a conversion from SDHC response to Renesas MMC + * CMD register response. + * + * @note in/out parameters should be checked by a caller function. + * + * @param response_type SDHC response type without SPI flags + * + * @retval positiv number (partial configuration of CMD register) on + * success, negative errno code otherwise + */ +static int32_t rcar_mmc_convert_sd_to_mmc_resp(uint32_t response_type) +{ + uint32_t mmc_resp = 0U; + + switch (response_type) { + case SD_RSP_TYPE_NONE: + mmc_resp = RCAR_MMC_CMD_RSP_NONE; + break; + case SD_RSP_TYPE_R1: + case SD_RSP_TYPE_R5: + case SD_RSP_TYPE_R6: + case SD_RSP_TYPE_R7: + mmc_resp = RCAR_MMC_CMD_RSP_R1; + break; + case SD_RSP_TYPE_R1b: + case SD_RSP_TYPE_R5b: + mmc_resp = RCAR_MMC_CMD_RSP_R1B; + break; + case SD_RSP_TYPE_R2: + mmc_resp = RCAR_MMC_CMD_RSP_R2; + break; + case SD_RSP_TYPE_R3: + case SD_RSP_TYPE_R4: + mmc_resp = RCAR_MMC_CMD_RSP_R3; + break; + default: + LOG_ERR("unknown response type 0x%08x", response_type); + return -EINVAL; + } + + __ASSERT((int32_t)mmc_resp >= 0, "%s: converted response shouldn't be negative", __func__); + + return mmc_resp; +} + +/** + * @brief Convert response from Renesas MMC to SDHC + * + * Function writes a response to response array of @ref sdhc_command structure + * + * @note in/out parameters should be checked by a caller function. + * + * @param dev MMC device + * @param cmd MMC command + * @param response_type SDHC response type without SPI flags + * + * @retval none + */ +static void rcar_mmc_extract_resp(const struct device *dev, struct sdhc_command *cmd, + uint32_t response_type) +{ + if (response_type == SD_RSP_TYPE_R2) { + uint32_t rsp_127_104 = rcar_mmc_read_reg32(dev, RCAR_MMC_RSP76); + uint32_t rsp_103_72 = rcar_mmc_read_reg32(dev, RCAR_MMC_RSP54); + uint32_t rsp_71_40 = rcar_mmc_read_reg32(dev, RCAR_MMC_RSP32); + uint32_t rsp_39_8 = rcar_mmc_read_reg32(dev, RCAR_MMC_RSP10); + + cmd->response[0] = (rsp_39_8 & 0xffffff) << 8; + cmd->response[1] = + ((rsp_71_40 & 0x00ffffff) << 8) | ((rsp_39_8 & 0xff000000) >> 24); + cmd->response[2] = + ((rsp_103_72 & 0x00ffffff) << 8) | ((rsp_71_40 & 0xff000000) >> 24); + cmd->response[3] = + ((rsp_127_104 & 0x00ffffff) << 8) | ((rsp_103_72 & 0xff000000) >> 24); + + LOG_DBG("Response 2\n\t[0]: 0x%08x\n\t[1]: 0x%08x" + "\n\t[2]: 0x%08x\n\t[3]: 0x%08x", + cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3]); + } else { + cmd->response[0] = rcar_mmc_read_reg32(dev, RCAR_MMC_RSP10); + LOG_DBG("Response %u\n\t[0]: 0x%08x", response_type, cmd->response[0]); + } +} + +/* configure CMD register for tx/rx data */ +static uint32_t rcar_mmc_gen_data_cmd(struct sdhc_command *cmd, struct sdhc_data *data) +{ + uint32_t cmd_reg = RCAR_MMC_CMD_DATA; + + switch (cmd->opcode) { + case MMC_SEND_EXT_CSD: + case SD_READ_SINGLE_BLOCK: + case MMC_SEND_TUNING_BLOCK: + case SD_SEND_TUNING_BLOCK: + case SD_SWITCH: + case SD_APP_SEND_NUM_WRITTEN_BLK: + case SD_APP_SEND_SCR: + cmd_reg |= RCAR_MMC_CMD_RD; + break; + case SD_READ_MULTIPLE_BLOCK: + cmd_reg |= RCAR_MMC_CMD_RD; + cmd_reg |= RCAR_MMC_CMD_MULTI; + break; + case SD_WRITE_MULTIPLE_BLOCK: + cmd_reg |= RCAR_MMC_CMD_MULTI; + break; + case SD_WRITE_SINGLE_BLOCK: + /* fall through */ + default: + break; + } + + if (data->blocks > 1) { + cmd_reg |= RCAR_MMC_CMD_MULTI; + } + + return cmd_reg; +} + +/** + * @brief Transmit/Receive data to/from MMC using DMA + * + * Sends/Receives data to/from the MMC controller. + * + * @note in/out parameters should be checked by a caller function. + * + * @param dev MMC device + * @param data MMC data buffer for tx/rx + * @param is_read it is read or write operation + * + * @retval 0 tx/rx was successful + * @retval -ENOTSUP: cache flush/invalidate aren't supported + * @retval -ETIMEDOUT: timed out while tx/rx + * @retval -EIO: I/O error + * @retval -EILSEQ: communication out of sync + */ +static int rcar_mmc_dma_rx_tx_data(const struct device *dev, struct sdhc_data *data, bool is_read) +{ + uintptr_t dma_addr; + uint32_t reg; + int ret = 0; + uint32_t dma_info1_poll_flag; +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + struct mmc_rcar_data *dev_data = dev->data; +#endif + + ret = sys_cache_data_flush_range(data->data, data->blocks * data->block_size); + if (ret < 0) { + LOG_ERR("%s: can't invalidate data cache before write", dev->name); + return ret; + } + + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_MODE); + if (is_read) { + dma_info1_poll_flag = RCAR_MMC_DMA_INFO1_END_RD2; + reg |= RCAR_MMC_DMA_MODE_DIR_RD; + } else { + dma_info1_poll_flag = RCAR_MMC_DMA_INFO1_END_WR; + reg &= ~RCAR_MMC_DMA_MODE_DIR_RD; + } + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_MODE, reg); + + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_EXTMODE); + reg |= RCAR_MMC_EXTMODE_DMA_EN; + rcar_mmc_write_reg32(dev, RCAR_MMC_EXTMODE, reg); + + dma_addr = z_mem_phys_addr(data->data); + + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_ADDR_L, dma_addr); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_ADDR_H, 0); + +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + rcar_mmc_write_reg32( + dev, RCAR_MMC_DMA_INFO2_MASK, + (uint32_t)(is_read ? (~RCAR_MMC_DMA_INFO2_ERR_RD) : (~RCAR_MMC_DMA_INFO2_ERR_WR))); + + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_INFO1_MASK); + reg &= ~dma_info1_poll_flag; + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO1_MASK, reg); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_CTL, RCAR_MMC_DMA_CTL_START); + + ret = k_sem_take(&dev_data->irq_xref_fin, K_MSEC(data->timeout_ms)); + if (ret < 0) { + LOG_ERR("%s: interrupt signal timeout error %d", dev->name, ret); + } + + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_INFO2); + if (reg) { + LOG_ERR("%s: an error occurs on the DMAC channel #%u", dev->name, + (reg & RCAR_MMC_DMA_INFO2_ERR_RD) ? 1U : 0U); + ret = -EIO; + } +#else + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_CTL, RCAR_MMC_DMA_CTL_START); + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_DMA_INFO1, dma_info1_poll_flag, + dma_info1_poll_flag, false, true, + data->timeout_ms * 1000LL); +#endif + + if (is_read) { + if (sys_cache_data_invd_range(data->data, data->blocks * data->block_size) < 0) { + LOG_ERR("%s: can't invalidate data cache after read", dev->name); + } + } + + /* in case when we get to here and there wasn't IRQ trigger */ + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO1_MASK, 0xfffffeff); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO2_MASK, ~0); + + if (ret == -EIO) { + rcar_mmc_reset_dma(dev); + } + + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_EXTMODE); + reg &= ~RCAR_MMC_EXTMODE_DMA_EN; + rcar_mmc_write_reg32(dev, RCAR_MMC_EXTMODE, reg); + + return ret; +} + +/* read from SD/MMC controller buf0 register */ +static inline uint64_t rcar_mmc_read_buf0(const struct device *dev) +{ + uint64_t buf0 = 0ULL; + struct mmc_rcar_data *dev_data = dev->data; + uint8_t sd_buf0_size = dev_data->width_access_sd_buf0; + mm_reg_t buf0_addr = DEVICE_MMIO_GET(dev) + RCAR_MMC_BUF0; + + switch (sd_buf0_size) { + case 8: + buf0 = sys_read64(buf0_addr); + break; + case 4: + buf0 = sys_read32(buf0_addr); + break; + case 2: + buf0 = sys_read16(buf0_addr); + break; + default: + k_panic(); + break; + } + + return buf0; +} + +/* write to SD/MMC controller buf0 register */ +static inline void rcar_mmc_write_buf0(const struct device *dev, uint64_t val) +{ + struct mmc_rcar_data *dev_data = dev->data; + uint8_t sd_buf0_size = dev_data->width_access_sd_buf0; + mm_reg_t buf0_addr = DEVICE_MMIO_GET(dev) + RCAR_MMC_BUF0; + + switch (sd_buf0_size) { + case 8: + sys_write64(val, buf0_addr); + break; + case 4: + sys_write32(val, buf0_addr); + break; + case 2: + sys_write16(val, buf0_addr); + break; + default: + k_panic(); + break; + } +} + +/** + * @brief Transmit/Receive data to/from MMC without DMA + * + * Sends/Receives data to/from the MMC controller. + * + * @note in/out parameters should be checked by a caller function. + * + * @param dev MMC device + * @param data MMC data buffer for tx/rx + * @param is_read it is read or write operation + * + * @retval 0 tx/rx was successful + * @retval -EINVAL: invalid block size + * @retval -ETIMEDOUT: timed out while tx/rx + * @retval -EIO: I/O error + * @retval -EILSEQ: communication out of sync + */ +static int rcar_mmc_sd_buf_rx_tx_data(const struct device *dev, struct sdhc_data *data, + bool is_read) +{ + struct mmc_rcar_data *dev_data = dev->data; + uint32_t block; + int ret = 0; + uint32_t info2_poll_flag = is_read ? RCAR_MMC_INFO2_BRE : RCAR_MMC_INFO2_BWE; + uint8_t sd_buf0_size = dev_data->width_access_sd_buf0; + uint16_t aligned_block_size = ROUND_UP(data->block_size, sd_buf0_size); + uint32_t cmd_reg = 0; + int64_t remaining_timeout_us = data->timeout_ms * 1000LL; + + /* + * note: below code should work for all possible block sizes, but + * we need below check, because code isn't tested with smaller + * block sizes. + */ + if ((data->block_size % dev_data->width_access_sd_buf0) || + (data->block_size < dev_data->width_access_sd_buf0)) { + LOG_ERR("%s: block size (%u) less or not align on SD BUF0 access width (%hhu)", + dev->name, data->block_size, dev_data->width_access_sd_buf0); + return -EINVAL; + } + + /* + * JEDEC Standard No. 84-B51 + * 6.6.24 Dual Data Rate mode operation: + * Therefore, all single or multiple block data transfer read or write will operate on + * a fixed block size of 512 bytes while the Device remains in dual data rate. + * + * Physical Layer Specification Version 3.01 + * 4.12.6 Timing Changes in DDR50 Mode + * 4.12.6.2 Protocol Principles + * * Read and Write data block length size is always 512 bytes (same as SDHC). + */ + if (dev_data->ddr_mode && data->block_size != 512) { + LOG_ERR("%s: block size (%u) isn't equal to 512 in DDR mode", dev->name, + data->block_size); + return -EINVAL; + } + + /* + * note: the next restrictions we have according to description of + * transfer data length register from R-Car S4 series User's Manual + */ + if (data->block_size > 512 || data->block_size == 0) { + LOG_ERR("%s: block size (%u) must not be bigger than 512 bytes and equal to zero", + dev->name, data->block_size); + return -EINVAL; + } + + cmd_reg = rcar_mmc_read_reg32(dev, RCAR_MMC_CMD); + if (cmd_reg & RCAR_MMC_CMD_MULTI) { + /* CMD12 is automatically issued at multiple block transfer */ + if (!(cmd_reg & RCAR_MMC_CMD_NOSTOP) && data->block_size != 512) { + LOG_ERR("%s: illegal block size (%u) for multi-block xref with CMD12", + dev->name, data->block_size); + return -EINVAL; + } + + switch (data->block_size) { + case 32: + case 64: + case 128: + case 256: + case 512: + break; + default: + LOG_ERR("%s: illegal block size (%u) for multi-block xref without CMD12", + dev->name, data->block_size); + return -EINVAL; + } + } + + if (data->block_size == 1 && dev_data->host_io.bus_width == SDHC_BUS_WIDTH8BIT) { + LOG_ERR("%s: block size can't be equal to 1 with 8-bits bus width", dev->name); + return -EINVAL; + } + + for (block = 0; block < data->blocks; block++) { + uint8_t *buf = (uint8_t *)data->data + (block * data->block_size); + uint32_t info2_reg; + uint16_t w_off; /* word offset in a block */ + uint64_t start_block_xref_us = k_ticks_to_us_ceil64(k_uptime_ticks()); + + /* wait until the buffer is filled with data */ + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO2, info2_poll_flag, + info2_poll_flag, true, false, + remaining_timeout_us); + if (ret) { + return ret; + } + + /* clear write/read buffer ready flag */ + info2_reg = rcar_mmc_read_reg32(dev, RCAR_MMC_INFO2); + info2_reg &= ~info2_poll_flag; + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO2, info2_reg); + + for (w_off = 0; w_off < aligned_block_size; w_off += sd_buf0_size) { + uint64_t buf0 = 0ULL; + uint8_t copy_size = MIN(sd_buf0_size, data->block_size - w_off); + + if (is_read) { + buf0 = rcar_mmc_read_buf0(dev); + memcpy(buf + w_off, &buf0, copy_size); + } else { + memcpy(&buf0, buf + w_off, copy_size); + rcar_mmc_write_buf0(dev, buf0); + } + } + + remaining_timeout_us -= + k_ticks_to_us_ceil64(k_uptime_ticks()) - start_block_xref_us; + if (remaining_timeout_us < 0) { + return -ETIMEDOUT; + } + } + + return ret; +} + +/** + * @brief Transmit/Receive data to/from MMC + * + * Sends/Receives data to/from the MMC controller. + * + * @note in/out parameters should be checked by a caller function. + * + * @param dev MMC device + * @param data MMC data buffer for tx/rx + * @param is_read it is read or write operation + * + * @retval 0 tx/rx was successful + * @retval -EINVAL: invalid block size + * @retval -ETIMEDOUT: timed out while tx/rx + * @retval -EIO: I/O error + * @retval -EILSEQ: communication out of sync + */ +static int rcar_mmc_rx_tx_data(const struct device *dev, struct sdhc_data *data, bool is_read) +{ + uint32_t info1_reg; + int ret = 0; + +#ifdef CONFIG_RCAR_MMC_DMA_SUPPORT + if (!(z_mem_phys_addr(data->data) >> 32)) { + ret = rcar_mmc_dma_rx_tx_data(dev, data, is_read); + } else +#endif + { + ret = rcar_mmc_sd_buf_rx_tx_data(dev, data, is_read); + } + + if (ret < 0) { + return ret; + } + + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO1, RCAR_MMC_INFO1_CMP, + RCAR_MMC_INFO1_CMP, true, false, + MMC_POLL_FLAGS_TIMEOUT_US); + if (ret) { + return ret; + } + + /* clear access end flag */ + info1_reg = rcar_mmc_read_reg32(dev, RCAR_MMC_INFO1); + info1_reg &= ~RCAR_MMC_INFO1_CMP; + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO1, info1_reg); + + return ret; +} + +/** + * @brief Send command to MMC + * + * Sends a command to the MMC controller. + * + * @param dev MMC device + * @param cmd MMC command + * @param data MMC data. Leave NULL to send SD command without data. + * + * @retval 0 command was sent successfully + * @retval -ETIMEDOUT: command timed out while sending + * @retval -ENOTSUP: host controller does not support command + * @retval -EIO: I/O error + * @retval -EILSEQ: communication out of sync + */ +static int rcar_mmc_request(const struct device *dev, struct sdhc_command *cmd, + struct sdhc_data *data) +{ + int ret = -ENOTSUP; + uint32_t reg; + uint32_t response_type; + bool is_read = true; + int attempts; + struct mmc_rcar_data *dev_data; + + if (!dev || !cmd) { + return -EINVAL; + } + + dev_data = dev->data; + response_type = cmd->response_type & SDHC_NATIVE_RESPONSE_MASK; + attempts = cmd->retries + 1; + + while (ret && attempts-- > 0) { + if (ret != -ENOTSUP) { + rcar_mmc_reset(dev); +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + rcar_mmc_retune_if_needed(dev, true); +#endif + } + + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_CBSY, 0, + false, false, MMC_POLL_FLAGS_TIMEOUT_US); + if (ret) { + ret = -EBUSY; + continue; + } + + rcar_mmc_reset_and_mask_irqs(dev); + + rcar_mmc_write_reg32(dev, RCAR_MMC_ARG, cmd->arg); + + reg = cmd->opcode; + + if (data) { + rcar_mmc_write_reg32(dev, RCAR_MMC_SIZE, data->block_size); + rcar_mmc_write_reg32(dev, RCAR_MMC_SECCNT, data->blocks); + reg |= rcar_mmc_gen_data_cmd(cmd, data); + is_read = (reg & RCAR_MMC_CMD_RD) ? true : false; + } + + /* CMD55 is always sended before ACMD */ + if (dev_data->is_last_cmd_app_cmd) { + reg |= RCAR_MMC_CMD_APP; + } + + ret = rcar_mmc_convert_sd_to_mmc_resp(response_type); + if (ret < 0) { + /* don't need to retry we will always have the same result */ + return -EINVAL; + } + + reg |= ret; + + LOG_DBG("(SD_CMD=%08x, SD_ARG=%08x)", cmd->opcode, cmd->arg); + rcar_mmc_write_reg32(dev, RCAR_MMC_CMD, reg); + + /* wait until response end flag is set or errors occur */ + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO1, RCAR_MMC_INFO1_RSP, + RCAR_MMC_INFO1_RSP, true, false, + cmd->timeout_ms * 1000LL); + if (ret) { + continue; + } + + /* clear response end flag */ + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_INFO1); + reg &= ~RCAR_MMC_INFO1_RSP; + rcar_mmc_write_reg32(dev, RCAR_MMC_INFO1, reg); + + rcar_mmc_extract_resp(dev, cmd, response_type); + + if (data) { + ret = rcar_mmc_rx_tx_data(dev, data, is_read); + if (ret) { + continue; + } + } + + /* wait until the SD bus (CMD, DAT) is free or errors occur */ + ret = rcar_mmc_poll_reg_flags_check_err( + dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_SCLKDIVEN, RCAR_MMC_INFO2_SCLKDIVEN, + true, false, MMC_POLL_FLAGS_TIMEOUT_US); + } + + if (ret) { + rcar_mmc_reset(dev); +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + rcar_mmc_retune_if_needed(dev, true); +#endif + } + + dev_data->is_last_cmd_app_cmd = (cmd->opcode == SD_APP_CMD); + + return ret; +} + +/* convert sd_voltage to string */ +static inline const char *const rcar_mmc_get_signal_voltage_str(enum sd_voltage voltage) +{ + static const char *const sig_vol_str[] = { + [0] = "Unset", [SD_VOL_3_3_V] = "3.3V", [SD_VOL_3_0_V] = "3.0V", + [SD_VOL_1_8_V] = "1.8V", [SD_VOL_1_2_V] = "1.2V", + }; + + if (voltage >= 0 && voltage < ARRAY_SIZE(sig_vol_str)) { + return sig_vol_str[voltage]; + } else { + return "Unknown"; + } +} + +/* convert sdhc_timing_mode to string */ +static inline const char *const rcar_mmc_get_timing_str(enum sdhc_timing_mode timing) +{ + static const char *const timing_str[] = { + [0] = "Unset", + [SDHC_TIMING_LEGACY] = "LEGACY", + [SDHC_TIMING_HS] = "HS", + [SDHC_TIMING_SDR12] = "SDR12", + [SDHC_TIMING_SDR25] = "SDR25", + [SDHC_TIMING_SDR50] = "SDR50", + [SDHC_TIMING_SDR104] = "SDR104", + [SDHC_TIMING_DDR50] = "DDR50", + [SDHC_TIMING_DDR52] = "DDR52", + [SDHC_TIMING_HS200] = "HS200", + [SDHC_TIMING_HS400] = "HS400", + }; + + if (timing >= 0 && timing < ARRAY_SIZE(timing_str)) { + return timing_str[timing]; + } else { + return "Unknown"; + } +} + +/* change voltage of MMC */ +static int rcar_mmc_change_voltage(const struct mmc_rcar_cfg *cfg, struct sdhc_io *host_io, + struct sdhc_io *ios) +{ + int ret = 0; + + /* Set host signal voltage */ + if (!ios->signal_voltage || ios->signal_voltage == host_io->signal_voltage) { + return 0; + } + + switch (ios->signal_voltage) { + case SD_VOL_3_3_V: + ret = regulator_set_voltage(cfg->regulator_vqmmc, 3300000, 3300000); + if (ret && ret != -ENOSYS) { + break; + } + + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + break; + case SD_VOL_1_8_V: + ret = regulator_set_voltage(cfg->regulator_vqmmc, 1800000, 1800000); + if (ret && ret != -ENOSYS) { + break; + } + + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_UHS); + break; + case SD_VOL_3_0_V: + case SD_VOL_1_2_V: + /* fall through */ + default: + ret = -ENOTSUP; + return ret; + } + + if (!ret) { + host_io->signal_voltage = ios->signal_voltage; + } + + return ret; +} + +/* note: for zero val function returns zero */ +static inline uint32_t round_up_next_pwr_of_2(uint32_t val) +{ + __ASSERT(val, "Zero val passed to %s", __func__); + + val--; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + return ++val; +} + +/** + * @brief configure clock divider on MMC controller + * + * @note In/out parameters should be checked by a caller function. + * @note In the case of data transfer in HS400 mode (HS400 bit in + * SDIF_MODE = 1), do not set this width equal to 1. + * @note In the case of writing of one-byte block, 8-bit width cannot + * be specified for the bus width. Change the bus width to 4 bits + * or 1 bit before writing one-byte block. + * + * @param dev MMC device + * @param io I/O properties + * + * @retval 0 I/O was configured correctly + * @retval -ENOTSUP: controller does not support these I/O settings + * @retval -ETIMEDOUT: card busy flag is set during long time + */ +static int rcar_mmc_set_clk_rate(const struct device *dev, struct sdhc_io *ios) +{ + int ret = 0; + uint32_t divisor; + uint32_t mmc_clk_ctl; + struct mmc_rcar_data *data = dev->data; + const struct mmc_rcar_cfg *cfg = dev->config; + struct sdhc_io *host_io = &data->host_io; + + if (host_io->clock == ios->clock) { + return 0; + } + + if (ios->clock == 0) { + host_io->clock = 0; + return rcar_mmc_enable_clock(dev, false); + } + + if (ios->clock > data->props.f_max || ios->clock < data->props.f_min) { + LOG_ERR("SDHC I/O: clock (%d) isn't in range %d - %d Hz", ios->clock, + data->props.f_min, data->props.f_max); + return -EINVAL; + } + + divisor = DIV_ROUND_UP(cfg->max_frequency, ios->clock); + + /* Do not set divider to 0xff in DDR mode */ + if (data->ddr_mode && (divisor == 1)) { + divisor = 2; + } + + divisor = round_up_next_pwr_of_2(divisor); + if (divisor == 1) { + divisor = RCAR_MMC_CLKCTL_RCAR_DIV1; + } else { + divisor >>= 2; + } + + /* + * Stop the clock before changing its rate + * to avoid a glitch signal + */ + ret = rcar_mmc_enable_clock(dev, false); + if (ret) { + return ret; + } + + mmc_clk_ctl = rcar_mmc_read_reg32(dev, RCAR_MMC_CLKCTL); + if ((mmc_clk_ctl & RCAR_MMC_CLKCTL_SCLKEN) && + (mmc_clk_ctl & RCAR_MMC_CLKCTL_DIV_MASK) == divisor) { + host_io->clock = ios->clock; + return rcar_mmc_enable_clock(dev, false); + } + + /* + * Do not change the values of these bits + * when the CBSY bit in SD_INFO2 is 1 + */ + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_CBSY, 0, false, + false, MMC_POLL_FLAGS_TIMEOUT_US); + if (ret) { + return -ETIMEDOUT; + } + + mmc_clk_ctl &= ~RCAR_MMC_CLKCTL_DIV_MASK; + mmc_clk_ctl |= divisor; + + rcar_mmc_write_reg32(dev, RCAR_MMC_CLKCTL, mmc_clk_ctl); + ret = rcar_mmc_enable_clock(dev, true); + if (ret) { + return ret; + } + + host_io->clock = ios->clock; + + LOG_DBG("%s: set clock rate to %d", dev->name, ios->clock); + + return 0; +} + +/** + * @brief set bus width of MMC + * + * @note In/out parameters should be checked by a caller function. + * @note In the case of data transfer in HS400 mode (HS400 bit in + * SDIF_MODE = 1), do not set this width equal to 1. + * @note In the case of writing of one-byte block, 8-bit width cannot + * be specified for the bus width. Change the bus width to 4 bits + * or 1 bit before writing one-byte block. + * + * @param dev MMC device + * @param io I/O properties + * + * @retval 0 I/O was configured correctly + * @retval -ENOTSUP: controller does not support these I/O settings + * @retval -ETIMEDOUT: card busy flag is set during long time + */ +static int rcar_mmc_set_bus_width(const struct device *dev, struct sdhc_io *ios) +{ + int ret = 0; + uint32_t mmc_option_reg; + uint32_t reg_width; + struct mmc_rcar_data *data = dev->data; + struct sdhc_io *host_io = &data->host_io; + + /* Set bus width */ + if (host_io->bus_width == ios->bus_width) { + return 0; + } + + if (!ios->bus_width) { + return 0; + } + + switch (ios->bus_width) { + case SDHC_BUS_WIDTH1BIT: + reg_width = RCAR_MMC_OPTION_WIDTH_1; + break; + case SDHC_BUS_WIDTH4BIT: + if (data->props.host_caps.bus_4_bit_support) { + reg_width = RCAR_MMC_OPTION_WIDTH_4; + } else { + LOG_ERR("SDHC I/O: 4-bits bus width isn't supported"); + return -ENOTSUP; + } + break; + case SDHC_BUS_WIDTH8BIT: + if (data->props.host_caps.bus_8_bit_support) { + reg_width = RCAR_MMC_OPTION_WIDTH_8; + } else { + LOG_ERR("SDHC I/O: 8-bits bus width isn't supported"); + return -ENOTSUP; + } + break; + default: + return -ENOTSUP; + } + + /* + * Do not change the values of these bits + * when the CBSY bit in SD_INFO2 is 1 + */ + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_CBSY, 0, false, + false, MMC_POLL_FLAGS_TIMEOUT_US); + if (ret) { + return -ETIMEDOUT; + } + + mmc_option_reg = rcar_mmc_read_reg32(dev, RCAR_MMC_OPTION); + mmc_option_reg &= ~RCAR_MMC_OPTION_WIDTH_MASK; + mmc_option_reg |= reg_width; + rcar_mmc_write_reg32(dev, RCAR_MMC_OPTION, mmc_option_reg); + + host_io->bus_width = ios->bus_width; + + LOG_DBG("%s: set bus-width to %d", dev->name, host_io->bus_width); + return 0; +} + +/** + * set DDR mode on MMC controller according to value inside + * ddr_mode field from @ref mmc_rcar_data structure. + */ +static int rcar_mmc_set_ddr_mode(const struct device *dev) +{ + int ret = 0; + uint32_t if_mode_reg; + struct mmc_rcar_data *data = dev->data; + + /* + * Do not change the values of these bits + * when the CBSY bit in SD_INFO2 is 1 + */ + ret = rcar_mmc_poll_reg_flags_check_err(dev, RCAR_MMC_INFO2, RCAR_MMC_INFO2_CBSY, 0, false, + false, MMC_POLL_FLAGS_TIMEOUT_US); + if (ret) { + return -ETIMEDOUT; + } + + if_mode_reg = rcar_mmc_read_reg32(dev, RCAR_MMC_IF_MODE); + if (data->ddr_mode) { + /* HS400 mode (DDR mode) */ + if_mode_reg |= RCAR_MMC_IF_MODE_DDR; + } else { + /* Normal mode (default, high speed, or SDR) */ + if_mode_reg &= ~RCAR_MMC_IF_MODE_DDR; + } + rcar_mmc_write_reg32(dev, RCAR_MMC_IF_MODE, if_mode_reg); + + return 0; +} + +/** + * @brief set timing property of MMC + * + * For now function only can enable DDR mode and call the function for + * changing voltage. It is expectable that we change clock using another + * I/O option. + * @note In/out parameters should be checked by a caller function. + * + * @param dev MMC device + * @param io I/O properties + * + * @retval 0 I/O was configured correctly + * @retval -ENOTSUP: controller does not support these I/O settings + * @retval -ETIMEDOUT: card busy flag is set during long time + */ +static int rcar_mmc_set_timings(const struct device *dev, struct sdhc_io *ios) +{ + int ret; + struct mmc_rcar_data *data = dev->data; + struct sdhc_io *host_io = &data->host_io; + enum sd_voltage new_voltage = host_io->signal_voltage; + + if (host_io->timing == ios->timing) { + return 0; + } + + if (!host_io->timing) { + return 0; + } + + data->ddr_mode = 0; + + switch (ios->timing) { + case SDHC_TIMING_LEGACY: + break; + case SDHC_TIMING_HS: + if (!data->props.host_caps.high_spd_support) { + LOG_ERR("SDHC I/O: HS timing isn't supported"); + return -ENOTSUP; + } + break; + case SDHC_TIMING_SDR12: + case SDHC_TIMING_SDR25: + case SDHC_TIMING_SDR50: + break; + case SDHC_TIMING_SDR104: + if (!data->props.host_caps.sdr104_support) { + LOG_ERR("SDHC I/O: SDR104 timing isn't supported"); + return -ENOTSUP; + } + break; + case SDHC_TIMING_HS400: + if (!data->props.host_caps.hs400_support) { + LOG_ERR("SDHC I/O: HS400 timing isn't supported"); + return -ENOTSUP; + } + new_voltage = SD_VOL_1_8_V; + data->ddr_mode = 1; + break; + case SDHC_TIMING_DDR50: + case SDHC_TIMING_DDR52: + if (!data->props.host_caps.ddr50_support) { + LOG_ERR("SDHC I/O: DDR50/DDR52 timing isn't supported"); + return -ENOTSUP; + } + data->ddr_mode = 1; + break; + case SDHC_TIMING_HS200: + if (!data->props.host_caps.hs200_support) { + LOG_ERR("SDHC I/O: HS200 timing isn't supported"); + return -ENOTSUP; + } + new_voltage = SD_VOL_1_8_V; + break; + default: + return -ENOTSUP; + } + + ios->signal_voltage = new_voltage; + if (rcar_mmc_change_voltage(dev->config, host_io, ios)) { + return -ENOTSUP; + } + + ret = rcar_mmc_set_ddr_mode(dev); + if (ret) { + return ret; + } + + host_io->timing = ios->timing; + return 0; +} + +/** + * @brief set I/O properties of MMC + * + * I/O properties should be reconfigured when the card has been sent a command + * to change its own MMC settings. This function can also be used to toggle + * power to the SD card. + * + * @param dev MMC device + * @param io I/O properties + * + * @retval 0 I/O was configured correctly + * @retval -ENOTSUP: controller does not support these I/O settings + * @retval -EINVAL: some of pointers provided to the function are NULL + * @retval -ETIMEDOUT: card busy flag is set during long time + */ +static int rcar_mmc_set_io(const struct device *dev, struct sdhc_io *ios) +{ + int ret = 0; + struct mmc_rcar_data *data; + struct sdhc_io *host_io; + + if (!dev || !ios || !dev->data || !dev->config) { + return -EINVAL; + } + + data = dev->data; + host_io = &data->host_io; + + LOG_DBG("SDHC I/O: bus width %d, clock %dHz, card power %s, " + "timing %s, voltage %s", + ios->bus_width, ios->clock, ios->power_mode == SDHC_POWER_ON ? "ON" : "OFF", + rcar_mmc_get_timing_str(ios->timing), + rcar_mmc_get_signal_voltage_str(ios->signal_voltage)); + + /* Set host clock */ + ret = rcar_mmc_set_clk_rate(dev, ios); + if (ret) { + LOG_ERR("SDHC I/O: can't change clock rate error %d old %d new %d", ret, + host_io->clock, ios->clock); + return ret; + } + + /* + * Set card bus mode + * + * SD Specifications Part 1 Physical Layer Simplified Specification Version 9.00 + * 4.7.1 Command Types: "... there is no Open Drain mode in SD Memory Card" + * + * The use of open-drain mode is not possible in SD memory cards because the SD bus uses + * push-pull signaling, where both the host and the card can actively drive the data lines + * high or low. + * In an SD card, the command and response signaling needs to be bidirectional, and each + * signal line needs to be actively driven high or low. The use of open-drain mode in this + * scenario would not allow for the necessary bidirectional signaling and could result in + * communication errors. + * + * JEDEC Standard No. 84-B51, 10 The eMMC bus: + * "The e•MMC bus has eleven communication lines: + * - CMD: Command is a bidirectional signal. The host and Device drivers are operating in + * two modes, open drain and push/pull. + * - DAT0-7: Data lines are bidirectional signals. Host and Device drivers are operating + * in push-pull mode. + * - CLK: Clock is a host to Device signal. CLK operates in push-pull mode. + * - Data Strobe: Data Strobe is a Device to host signal. Data Strobe operates in + * push-pull mode." + * + * So, open-drain mode signaling is supported in eMMC as one of the signaling modes for + * the CMD line. But Gen3 and Gen4 boards has MMC/SD controller which is a specialized + * component designed specifically for managing communication with MMC/SD devices. It + * handles low-level operations such as protocol handling, data transfer, and error + * checking and should take care of the low-level details of communicating with the + * MMC/SD card, including setting the bus mode. Moreover, we can use only MMIO mode, the + * processor communicates with the MMC/SD controller through memory read and write + * operations, rather than through dedicated I/O instructions or specialized data transfer + * protocols like SPI or SDIO. Finally, R-Car Gen3 and Gen4 "User’s manuals: Hardware" + * don't have direct configurations for open-drain mode for both PFC and GPIO and Zephyr + * SDHC subsystem doesn't support any bus mode except push-pull. + */ + if (ios->bus_mode != SDHC_BUSMODE_PUSHPULL) { + LOG_ERR("SDHC I/O: not supported bus mode %d", ios->bus_mode); + return -ENOTSUP; + } + host_io->bus_mode = ios->bus_mode; + + /* Set card power */ + if (ios->power_mode && host_io->power_mode != ios->power_mode) { + const struct mmc_rcar_cfg *cfg = dev->config; + + switch (ios->power_mode) { + case SDHC_POWER_ON: + ret = regulator_enable(cfg->regulator_vmmc); + if (ret) { + break; + } + + k_msleep(data->props.power_delay); + + ret = regulator_enable(cfg->regulator_vqmmc); + if (ret) { + break; + } + + k_msleep(data->props.power_delay); + ret = rcar_mmc_enable_clock(dev, true); + break; + case SDHC_POWER_OFF: + if (regulator_is_enabled(cfg->regulator_vqmmc)) { + ret = regulator_disable(cfg->regulator_vqmmc); + if (ret) { + break; + } + } + + if (regulator_is_enabled(cfg->regulator_vmmc)) { + ret = regulator_disable(cfg->regulator_vmmc); + if (ret) { + break; + } + } + + ret = rcar_mmc_enable_clock(dev, false); + break; + default: + LOG_ERR("SDHC I/O: not supported power mode %d", ios->power_mode); + return -ENOTSUP; + } + + if (ret) { + return ret; + } + host_io->power_mode = ios->power_mode; + } + + ret = rcar_mmc_set_bus_width(dev, ios); + if (ret) { + LOG_ERR("SDHC I/O: can't change bus width error %d old %d new %d", ret, + host_io->bus_width, ios->bus_width); + return ret; + } + + ret = rcar_mmc_set_timings(dev, ios); + if (ret) { + LOG_ERR("SDHC I/O: can't change timing error %d old %d new %d", ret, + host_io->timing, ios->timing); + return ret; + } + + ret = rcar_mmc_change_voltage(dev->config, host_io, ios); + if (ret) { + LOG_ERR("SDHC I/O: can't change voltage! error %d old %d new %d", ret, + host_io->signal_voltage, ios->signal_voltage); + return ret; + } + + return 0; +} + +/** + * @brief check for MMC card presence + * + * Checks if card is present on the bus. + * + * @param dev MMC device + * + * @retval 1 card is present + * @retval 0 card is not present + * @retval -EINVAL: some of pointers provided to the function are NULL + */ +static int rcar_mmc_get_card_present(const struct device *dev) +{ + const struct mmc_rcar_cfg *cfg; + + if (!dev || !dev->config) { + return -EINVAL; + } + + cfg = dev->config; + if (cfg->non_removable) { + return 1; + } + + return !!(rcar_mmc_read_reg32(dev, RCAR_MMC_INFO1) & RCAR_MMC_INFO1_CD); +} + +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + +/* JESD84-B51, 6.6.5.1 Sampling Tuning Sequence for HS200 */ +static const uint8_t tun_block_8_bits_bus[] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, +}; + +/* + * In 4 bit mode the same pattern is used as shown above, + * but only first 4 bits least significant from every byte is used, examle: + * 8-bits pattern: 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00 ... + * f f 0 f f f 0 0 ... + * 4-bits pattern: 0xff 0x0f 0xff 0x00 ... + */ +static const uint8_t tun_block_4_bits_bus[] = { + 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, + 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, + 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, + 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, + 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, + 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, + 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, + 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, +}; + +#define RENESAS_TAPNUM 8 + +/** + * @brief run MMC tuning + * + * MMC cards require signal tuning for UHS modes SDR104, HS200 or HS400. + * This function allows an application to request the SD host controller + * to tune the card. + * + * @param dev MMC device + * + * @retval 0 tuning succeeded (card is ready for commands), otherwise negative number is returned + */ +static int rcar_mmc_execute_tuning(const struct device *dev) +{ + int ret = -ENOTSUP; + const uint8_t *tun_block_ptr; + uint8_t tap_idx; + uint8_t is_mmc_cmd = false; + struct sdhc_command cmd = {0}; + struct sdhc_data data = {0}; + struct mmc_rcar_data *dev_data; + uint16_t valid_taps = 0; + uint16_t smpcmp_bitmask = 0; + + BUILD_ASSERT(sizeof(valid_taps) * 8 >= 2 * RENESAS_TAPNUM); + BUILD_ASSERT(sizeof(smpcmp_bitmask) * 8 >= 2 * RENESAS_TAPNUM); + + if (!dev) { + return -EINVAL; + } + + dev_data = dev->data; + dev_data->can_retune = 0; + + if (dev_data->host_io.timing == SDHC_TIMING_HS200) { + cmd.opcode = MMC_SEND_TUNING_BLOCK; + is_mmc_cmd = true; + } else if (dev_data->host_io.timing != SDHC_TIMING_HS400) { + cmd.opcode = SD_SEND_TUNING_BLOCK; + } else { + LOG_ERR("%s: tuning isn't possible in HS400 mode, it should be done in HS200", + dev->name); + return -EINVAL; + } + + cmd.response_type = SD_RSP_TYPE_R1; + cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; + + data.blocks = 1; + data.data = dev_data->tuning_buf; + data.timeout_ms = CONFIG_SD_DATA_TIMEOUT; + if (dev_data->host_io.bus_width == SDHC_BUS_WIDTH4BIT) { + data.block_size = sizeof(tun_block_4_bits_bus); + tun_block_ptr = tun_block_4_bits_bus; + } else if (dev_data->host_io.bus_width == SDHC_BUS_WIDTH8BIT) { + data.block_size = sizeof(tun_block_8_bits_bus); + tun_block_ptr = tun_block_8_bits_bus; + } else { + LOG_ERR("%s: don't support tuning for 1-bit bus width", dev->name); + return -EINVAL; + } + + ret = rcar_mmc_enable_clock(dev, false); + if (ret) { + return ret; + } + + /* enable modes SDR104/HS200/HS400 */ + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_DT2FF, 0x300); + /* SCC sampling clock operation is enabled */ + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_DTCNTL, + RENESAS_SDHI_SCC_DTCNTL_TAPEN | RENESAS_TAPNUM << 16); + /* SCC sampling clock is used */ + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_CKSEL, RENESAS_SDHI_SCC_CKSEL_DTSEL); + /* SCC sampling clock position correction is disabled */ + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSCNTL, 0); + /* cleanup errors */ + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSREQ, 0); + + ret = rcar_mmc_enable_clock(dev, true); + if (ret) { + return ret; + } + + /* + * two runs is better for detecting TAP ok cases like next: + * - one burn: 0b10000011 + * - two burns: 0b1000001110000011 + * it is more easly to detect 3 OK taps in a row + */ + for (tap_idx = 0; tap_idx < 2 * RENESAS_TAPNUM; tap_idx++) { + /* clear flags */ + rcar_mmc_reset_and_mask_irqs(dev); + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_TAPSET, tap_idx % RENESAS_TAPNUM); + memset(dev_data->tuning_buf, 0, data.block_size); + ret = rcar_mmc_request(dev, &cmd, &data); + if (ret) { + LOG_DBG("%s: received an error (%d) during tuning request", dev->name, ret); + + if (is_mmc_cmd) { + struct sdhc_command stop_cmd = { + .opcode = SD_STOP_TRANSMISSION, + .response_type = SD_RSP_TYPE_R1b, + .timeout_ms = CONFIG_SD_CMD_TIMEOUT, + }; + + rcar_mmc_request(dev, &stop_cmd, NULL); + } + continue; + } + + smpcmp_bitmask |= !rcar_mmc_read_reg32(dev, RENESAS_SDHI_SCC_SMPCMP) << tap_idx; + + if (memcmp(tun_block_ptr, dev_data->tuning_buf, data.block_size)) { + LOG_DBG("%s: received tuning block doesn't equal to pattert TAP index %u", + dev->name, tap_idx); + continue; + } + + valid_taps |= BIT(tap_idx); + + LOG_DBG("%s: smpcmp_bitmask[%u] 0x%08x", dev->name, tap_idx, smpcmp_bitmask); + } + + /* both parts of bitmasks have to be the same */ + valid_taps &= (valid_taps >> RENESAS_TAPNUM); + valid_taps |= (valid_taps << RENESAS_TAPNUM); + + smpcmp_bitmask &= (smpcmp_bitmask >> RENESAS_TAPNUM); + smpcmp_bitmask |= (smpcmp_bitmask << RENESAS_TAPNUM); + + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSREQ, 0); + + if (!valid_taps) { + LOG_ERR("%s: there isn't any valid tap during tuning", dev->name); + goto reset_scc; + } + + /* + * If all of the taps[i] is OK, the sampling clock position is selected by identifying + * the change point of data. Change point of the data can be found in the value of + * SCC_SMPCMP register + */ + if ((valid_taps >> RENESAS_TAPNUM) == (1 << RENESAS_TAPNUM) - 1) { + valid_taps = smpcmp_bitmask; + } + + /* do we have 3 set bits in a row at least */ + if (valid_taps & (valid_taps >> 1) & (valid_taps >> 2)) { + uint32_t max_len_range_pos = 0; + uint32_t max_bits_in_range = 0; + uint32_t pos_of_lsb_set = 0; + + /* all bits are set */ + if ((valid_taps >> RENESAS_TAPNUM) == (1 << RENESAS_TAPNUM) - 1) { + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_TAPSET, 0); + + if (!dev_data->manual_retuning) { + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSCNTL, 1); + } + dev_data->can_retune = 1; + return 0; + } + + /* searching the longest range of set bits */ + while (valid_taps) { + uint32_t num_bits_in_range; + uint32_t rsh = 0; + + rsh = find_lsb_set(valid_taps) - 1; + pos_of_lsb_set += rsh; + + /* shift all leading zeros */ + valid_taps >>= rsh; + + num_bits_in_range = find_lsb_set(~valid_taps) - 1; + + /* shift all leading ones */ + valid_taps >>= num_bits_in_range; + + if (max_bits_in_range < num_bits_in_range) { + max_bits_in_range = num_bits_in_range; + max_len_range_pos = pos_of_lsb_set; + } + pos_of_lsb_set += num_bits_in_range; + } + + tap_idx = (max_len_range_pos + max_bits_in_range / 2) % RENESAS_TAPNUM; + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_TAPSET, tap_idx); + + LOG_DBG("%s: valid_taps %08x smpcmp_bitmask %08x tap_idx %u", dev->name, valid_taps, + smpcmp_bitmask, tap_idx); + + if (!dev_data->manual_retuning) { + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSCNTL, 1); + } + dev_data->can_retune = 1; + return 0; + } + +reset_scc: + rcar_mmc_disable_scc(dev); + return ret; +} + +/* retune SCC in case of error during xref */ +static int rcar_mmc_retune_if_needed(const struct device *dev, bool request_retune) +{ + struct mmc_rcar_data *dev_data = dev->data; + int ret = 0; + uint32_t reg; + bool scc_pos_err = false; + uint8_t scc_tapset; + + if (!dev_data->can_retune) { + return 0; + } + + reg = rcar_mmc_read_reg32(dev, RENESAS_SDHI_SCC_RVSREQ); + if (reg & RENESAS_SDHI_SCC_RVSREQ_ERR) { + scc_pos_err = true; + } + + scc_tapset = rcar_mmc_read_reg32(dev, RENESAS_SDHI_SCC_TAPSET); + + LOG_DBG("%s: scc_tapset %08x scc_rvsreq %08x request %d is manual tuning %d", dev->name, + scc_tapset, reg, request_retune, dev_data->manual_retuning); + + if (request_retune || (scc_pos_err && !dev_data->manual_retuning)) { + return rcar_mmc_execute_tuning(dev); + } + + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSREQ, 0); + + switch (reg & RENESAS_SDHI_SCC_RVSREQ_REQTAP_MASK) { + case RENESAS_SDHI_SCC_RVSREQ_REQTAPDOWN: + scc_tapset = (scc_tapset - 1) % RENESAS_TAPNUM; + break; + case RENESAS_SDHI_SCC_RVSREQ_REQTAPUP: + scc_tapset = (scc_tapset + 1) % RENESAS_TAPNUM; + break; + default: + ret = -EINVAL; + LOG_ERR("%s: can't perform manual tuning SCC_RVSREQ %08x", dev->name, reg); + break; + } + + if (!ret) { + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_TAPSET, scc_tapset); + } + + return ret; +} + +#endif /* CONFIG_RCAR_MMC_SCC_SUPPORT */ + +/** + * @brief Get MMC controller properties + * + * Gets host properties from the host controller. Host controller should + * initialize all values in the @ref sdhc_host_props structure provided. + * + * @param dev Renesas MMC device + * @param props property structure to be filled by MMC driver + * + * @retval 0 function succeeded. + * @retval -EINVAL: some of pointers provided to the function are NULL + */ +static int rcar_mmc_get_host_props(const struct device *dev, struct sdhc_host_props *props) +{ + struct mmc_rcar_data *data; + + if (!props || !dev || !dev->data) { + return -EINVAL; + } + + data = dev->data; + memcpy(props, &data->props, sizeof(*props)); + return 0; +} + +static const struct sdhc_driver_api rcar_sdhc_api = { + .card_busy = rcar_mmc_card_busy, +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + .execute_tuning = rcar_mmc_execute_tuning, +#endif + .get_card_present = rcar_mmc_get_card_present, + .get_host_props = rcar_mmc_get_host_props, + .request = rcar_mmc_request, + .reset = rcar_mmc_reset, + .set_io = rcar_mmc_set_io, +}; + +/* start SD-IF clock at max frequency configured in dts */ +static int rcar_mmc_init_start_clk(const struct mmc_rcar_cfg *cfg) +{ + int ret = 0; + const struct device *cpg_dev = cfg->cpg_dev; + uintptr_t rate = cfg->max_frequency; + + ret = clock_control_on(cpg_dev, (clock_control_subsys_t *)&cfg->bus_clk); + if (ret < 0) { + return ret; + } + + ret = clock_control_on(cpg_dev, (clock_control_subsys_t *)&cfg->cpg_clk); + if (ret < 0) { + return ret; + } + + ret = clock_control_set_rate(cpg_dev, (clock_control_subsys_t *)&cfg->cpg_clk, + (clock_control_subsys_rate_t)rate); + if (ret < 0) { + clock_control_off(cpg_dev, (clock_control_subsys_t *)&cfg->cpg_clk); + } + + rate = MMC_BUS_CLOCK_FREQ; + ret = clock_control_set_rate(cpg_dev, (clock_control_subsys_t *)&cfg->bus_clk, + (clock_control_subsys_rate_t)rate); + /* SD spec recommends at least 1 ms of delay after start of clock */ + k_msleep(1); + + return ret; +} + +static void rcar_mmc_init_host_props(const struct device *dev) +{ + struct mmc_rcar_data *data = dev->data; + const struct mmc_rcar_cfg *cfg = dev->config; + struct sdhc_host_props *props = &data->props; + struct sdhc_host_caps *host_caps = &props->host_caps; + + memset(props, 0, sizeof(*props)); + + /* Note: init only properties that are used for mmc/sdhc */ + + props->f_max = cfg->max_frequency + MMC_MAX_FREQ_CORRECTION; + /* + * note: actually, it's possible to get lower frequency + * if we use divider from cpg too + */ + props->f_min = (cfg->max_frequency >> 9); + + props->power_delay = 100; /* ms */ + + props->is_spi = 0; + + switch (cfg->bus_width) { + case SDHC_BUS_WIDTH8BIT: + host_caps->bus_8_bit_support = 1; + case SDHC_BUS_WIDTH4BIT: + host_caps->bus_4_bit_support = 1; + default: + break; + } + + host_caps->high_spd_support = 1; +#ifdef CONFIG_RCAR_MMC_SCC_SUPPORT + host_caps->sdr104_support = cfg->mmc_sdr104_support; + host_caps->sdr50_support = cfg->uhs_support; + /* neither Linux nor U-boot support DDR50 mode, that's why we don't support it too */ + host_caps->ddr50_support = 0; + host_caps->hs200_support = cfg->mmc_hs200_1_8v; + /* TODO: add support */ + host_caps->hs400_support = 0; +#endif + + host_caps->vol_330_support = + regulator_is_supported_voltage(cfg->regulator_vqmmc, 3300000, 3300000); + host_caps->vol_300_support = + regulator_is_supported_voltage(cfg->regulator_vqmmc, 3000000, 3000000); + host_caps->vol_180_support = + regulator_is_supported_voltage(cfg->regulator_vqmmc, 1800000, 1800000); +} + +/* reset sampling clock controller registers */ +static int rcar_mmc_disable_scc(const struct device *dev) +{ + int ret; + uint32_t reg; + struct mmc_rcar_data *data = dev->data; + uint32_t mmc_clk_ctl = rcar_mmc_read_reg32(dev, RCAR_MMC_CLKCTL); + + /* just to be to be sure that the SD clock is disabled */ + ret = rcar_mmc_enable_clock(dev, false); + if (ret) { + return ret; + } + + /* + * Reset SCC registers, need to disable and enable clock + * before and after reset + */ + + /* Disable SCC sampling clock */ + reg = rcar_mmc_read_reg32(dev, RENESAS_SDHI_SCC_CKSEL); + reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL; + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_CKSEL, reg); + + /* disable hs400 mode & data output timing */ + reg = rcar_mmc_read_reg32(dev, RENESAS_SDHI_SCC_TMPPORT2); + reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN | RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL); + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_TMPPORT2, reg); + + ret = rcar_mmc_enable_clock(dev, (mmc_clk_ctl & RCAR_MMC_CLKCTL_OFFEN) ? false : true); + if (ret) { + return ret; + } + + /* disable SCC sampling clock position correction */ + reg = rcar_mmc_read_reg32(dev, RENESAS_SDHI_SCC_RVSCNTL); + reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN; + rcar_mmc_write_reg32(dev, RENESAS_SDHI_SCC_RVSCNTL, reg); + + data->can_retune = 0; + + return 0; +} + +/* initialize and configure the Renesas MMC controller registers */ +static int rcar_mmc_init_controller_regs(const struct device *dev) +{ + int ret = 0; + uint32_t reg; + struct mmc_rcar_data *data = dev->data; + struct sdhc_io ios = {0}; + + rcar_mmc_reset(dev); + + /* Disable SD clock (SD_CLK) output */ + ret = rcar_mmc_enable_clock(dev, false); + if (ret) { + return ret; + } + + /* set transfer data length to 0 */ + rcar_mmc_write_reg32(dev, RCAR_MMC_SIZE, 0); + + /* disable the SD_BUF read/write DMA transfer */ + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_EXTMODE); + reg &= ~RCAR_MMC_EXTMODE_DMA_EN; + rcar_mmc_write_reg32(dev, RCAR_MMC_EXTMODE, reg); + /* mask DMA irqs and clear dma irq flags */ + rcar_mmc_reset_and_mask_irqs(dev); + /* set system address increment mode selector & 64-bit bus width */ + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_MODE); + reg |= RCAR_MMC_DMA_MODE_ADDR_INC | RCAR_MMC_DMA_MODE_WIDTH; + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_MODE, reg); + + /* store version of of introductory IP */ + data->ver = rcar_mmc_read_reg32(dev, RCAR_MMC_VERSION); + data->ver &= RCAR_MMC_VERSION_IP; + + /* + * set bus width to 1 + * timeout counter: SDCLK * 2^27 + * card detect time counter: SDϕ * 2^24 + */ + reg = rcar_mmc_read_reg32(dev, RCAR_MMC_OPTION); + reg |= RCAR_MMC_OPTION_WIDTH_MASK | 0xEE; + rcar_mmc_write_reg32(dev, RCAR_MMC_OPTION, reg); + + /* block count enable */ + rcar_mmc_write_reg32(dev, RCAR_MMC_STOP, RCAR_MMC_STOP_SEC); + /* number of transfer blocks */ + rcar_mmc_write_reg32(dev, RCAR_MMC_SECCNT, 0); + + /* + * SD_BUF0 data swap disabled. + * Read/write access to SD_BUF0 can be performed with the 64-bit access. + * + * Note: when using the DMA, the bus width should be fixed at 64 bits. + */ + rcar_mmc_write_reg32(dev, RCAR_MMC_HOST_MODE, 0); + data->width_access_sd_buf0 = 8; + + /* disable sampling clock controller, it is used for uhs/sdr104, hs200 and hs400 */ + ret = rcar_mmc_disable_scc(dev); + if (ret) { + return ret; + } + + /* + * configure divider inside MMC controller + * set maximum possible divider + */ + ios.clock = data->props.f_min; + rcar_mmc_set_clk_rate(dev, &ios); + + data->restore_cfg_after_reset = 1; + + return 0; +} + +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT +static void rcar_mmc_irq_handler(const void *arg) +{ + const struct device *dev = arg; + + uint32_t dma_info1 = rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_INFO1); + uint32_t dma_info2 = rcar_mmc_read_reg32(dev, RCAR_MMC_DMA_INFO2); + + if (dma_info1 || dma_info2) { + struct mmc_rcar_data *data = dev->data; + + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO1_MASK, 0xfffffeff); + rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_INFO2_MASK, ~0); + k_sem_give(&data->irq_xref_fin); + } else { + LOG_WRN("%s: warning: non-dma event triggers irq", dev->name); + } +} +#endif /* CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT */ + +/* initialize and configure the Renesas MMC driver */ +static int rcar_mmc_init(const struct device *dev) +{ + int ret = 0; + struct mmc_rcar_data *data = dev->data; + const struct mmc_rcar_cfg *cfg = dev->config; + +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + ret = k_sem_init(&data->irq_xref_fin, 0, 1); + if (ret) { + LOG_ERR("%s: can't init semaphore", dev->name); + return ret; + } +#endif + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("%s: error can't apply pinctrl state", dev->name); + goto exit_unmap; + } + + if (!device_is_ready(cfg->cpg_dev)) { + LOG_ERR("%s: error cpg_dev isn't ready", dev->name); + ret = -ENODEV; + goto exit_unmap; + } + + ret = rcar_mmc_init_start_clk(cfg); + if (ret < 0) { + LOG_ERR("%s: error can't turn on the cpg", dev->name); + goto exit_unmap; + } + + /* it's needed for SDHC */ + rcar_mmc_init_host_props(dev); + + ret = rcar_mmc_init_controller_regs(dev); + if (ret) { + goto exit_disable_clk; + } + +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT + cfg->irq_config_func(dev); +#endif /* CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT */ + + LOG_INF("%s: initialize driver, MMC version 0x%hhx", dev->name, data->ver); + + return 0; + +exit_disable_clk: + clock_control_off(cfg->cpg_dev, (clock_control_subsys_t *)&cfg->cpg_clk); + +exit_unmap: +#if defined(DEVICE_MMIO_IS_IN_RAM) && defined(CONFIG_MMU) + z_phys_unmap((uint8_t *)DEVICE_MMIO_GET(dev), DEVICE_MMIO_ROM_PTR(dev)->size); +#endif + return ret; +} + +#ifdef CONFIG_RCAR_MMC_DMA_IRQ_DRIVEN_SUPPORT +#define RCAR_MMC_CONFIG_FUNC(n) \ + static void irq_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), rcar_mmc_irq_handler, \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ(n, flags)); \ + irq_enable(DT_INST_IRQN(n)); \ + } +#define RCAR_MMC_IRQ_CFG_FUNC_INIT(n) .irq_config_func = irq_config_func_##n, +#else +#define RCAR_MMC_IRQ_CFG_FUNC_INIT(n) +#define RCAR_MMC_CONFIG_FUNC(n) +#endif + +#define RCAR_MMC_INIT(n) \ + static struct mmc_rcar_data mmc_rcar_data_##n; \ + PINCTRL_DT_INST_DEFINE(n); \ + RCAR_MMC_CONFIG_FUNC(n); \ + static const struct mmc_rcar_cfg mmc_rcar_cfg_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .cpg_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .cpg_clk.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ + .cpg_clk.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ + .bus_clk.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 1, module), \ + .bus_clk.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 1, domain), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .regulator_vqmmc = DEVICE_DT_GET(DT_PHANDLE(DT_DRV_INST(n), vqmmc_supply)), \ + .regulator_vmmc = DEVICE_DT_GET(DT_PHANDLE(DT_DRV_INST(n), vmmc_supply)), \ + .max_frequency = DT_INST_PROP(n, max_bus_freq), \ + .non_removable = DT_INST_PROP(n, non_removable), \ + .mmc_hs200_1_8v = DT_INST_PROP(n, mmc_hs200_1_8v), \ + .mmc_hs400_1_8v = DT_INST_PROP(n, mmc_hs400_1_8v), \ + .mmc_sdr104_support = DT_INST_PROP(n, mmc_sdr104_support), \ + .uhs_support = 1, \ + .bus_width = DT_INST_PROP(n, bus_width), \ + RCAR_MMC_IRQ_CFG_FUNC_INIT(n)}; \ + DEVICE_DT_INST_DEFINE(n, rcar_mmc_init, NULL, &mmc_rcar_data_##n, &mmc_rcar_cfg_##n, \ + POST_KERNEL, CONFIG_SDHC_INIT_PRIORITY, &rcar_sdhc_api); + +DT_INST_FOREACH_STATUS_OKAY(RCAR_MMC_INIT) diff --git a/drivers/sdhc/rcar_mmc_registers.h b/drivers/sdhc/rcar_mmc_registers.h new file mode 100644 index 00000000000000..067ca4f112ebcf --- /dev/null +++ b/drivers/sdhc/rcar_mmc_registers.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __RCAR_MMC_REGISTERS_H__ +#define __RCAR_MMC_REGISTERS_H__ + +#include /* for BIT macro */ + +/* + * The command type register is used to select the command type + * and response type + */ +#define RCAR_MMC_CMD 0x000 /* command */ +#define RCAR_MMC_CMD_NOSTOP BIT(14) /* No automatic CMD12 issue */ +#define RCAR_MMC_CMD_MULTI BIT(13) /* multiple block transfer */ +#define RCAR_MMC_CMD_RD BIT(12) /* 1: read, 0: write */ +#define RCAR_MMC_CMD_DATA BIT(11) /* data transfer */ +#define RCAR_MMC_CMD_APP BIT(6) /* ACMD preceded by CMD55 */ +#define RCAR_MMC_CMD_NORMAL (0 << 8) /* auto-detect of resp-type */ +#define RCAR_MMC_CMD_RSP_NONE (3 << 8) /* response: none */ +#define RCAR_MMC_CMD_RSP_R1 (4 << 8) /* response: R1, R5, R6, R7 */ +#define RCAR_MMC_CMD_RSP_R1B (5 << 8) /* response: R1b, R5b */ +#define RCAR_MMC_CMD_RSP_R2 (6 << 8) /* response: R2 */ +#define RCAR_MMC_CMD_RSP_R3 (7 << 8) /* response: R3, R4 */ + +/* Command arguments register for SD card */ +#define RCAR_MMC_ARG 0x010 /* command argument */ + +/* + * The data stop register is used to enable or disable block counting at + * multiple block transfer, and to control the issuing of CMD12 within + * command sequences. + */ +#define RCAR_MMC_STOP 0x020 /* stop action control */ +#define RCAR_MMC_STOP_SEC BIT(8) /* use sector count */ +#define RCAR_MMC_STOP_STP BIT(0) /* issue CMD12 */ + +/* + * The block count register is used to specify the number of + * transfer blocks at multiple block transfer. + */ +#define RCAR_MMC_SECCNT 0x028 /* sector counter */ + +/* The SD card response registers hold the response from the SD card */ +#define RCAR_MMC_RSP10 0x030 /* response[39:8] */ +#define RCAR_MMC_RSP32 0x040 /* response[71:40] */ +#define RCAR_MMC_RSP54 0x050 /* response[103:72] */ +#define RCAR_MMC_RSP76 0x060 /* response[127:104] */ + +/* + * The SD card interrupt flag register 1 indicates the response end and access + * end in the command sequence. This register also indicates the card + * detect/write protect state. + */ +#define RCAR_MMC_INFO1 0x070 /* IRQ status 1 */ +#define RCAR_MMC_INFO1_CD BIT(5) /* state of card detect */ +#define RCAR_MMC_INFO1_INSERT BIT(4) /* card inserted */ +#define RCAR_MMC_INFO1_REMOVE BIT(3) /* card removed */ +#define RCAR_MMC_INFO1_CMP BIT(2) /* data complete */ +#define RCAR_MMC_INFO1_RSP BIT(0) /* response complete */ + +/* + * The SD card interrupt flag register 2 indicates the access status of the + * SD buffer and SD card. + */ +#define RCAR_MMC_INFO2 0x078 /* IRQ status 2 */ +#define RCAR_MMC_INFO2_ERR_ILA BIT(15) /* illegal access err */ +#define RCAR_MMC_INFO2_CBSY BIT(14) /* command busy */ +#define RCAR_MMC_INFO2_SCLKDIVEN BIT(13) /* command setting reg ena */ +#define RCAR_MMC_INFO2_CLEAR BIT(11) /* the write value should always be 1 */ +#define RCAR_MMC_INFO2_BWE BIT(9) /* write buffer ready */ +#define RCAR_MMC_INFO2_BRE BIT(8) /* read buffer ready */ +#define RCAR_MMC_INFO2_DAT0 BIT(7) /* SDDAT0 */ +#define RCAR_MMC_INFO2_ERR_RTO BIT(6) /* response time out */ +#define RCAR_MMC_INFO2_ERR_ILR BIT(5) /* illegal read err */ +#define RCAR_MMC_INFO2_ERR_ILW BIT(4) /* illegal write err */ +#define RCAR_MMC_INFO2_ERR_TO BIT(3) /* time out error */ +#define RCAR_MMC_INFO2_ERR_END BIT(2) /* END bit error */ +#define RCAR_MMC_INFO2_ERR_CRC BIT(1) /* CRC error */ +#define RCAR_MMC_INFO2_ERR_IDX BIT(0) /* cmd index error */ + +#define RCAR_MMC_INFO2_ERRORS \ + (RCAR_MMC_INFO2_ERR_RTO | RCAR_MMC_INFO2_ERR_ILR | \ + RCAR_MMC_INFO2_ERR_ILW | RCAR_MMC_INFO2_ERR_TO | \ + RCAR_MMC_INFO2_ERR_END | RCAR_MMC_INFO2_ERR_CRC | \ + RCAR_MMC_INFO2_ERR_IDX | RCAR_MMC_INFO2_ERR_ILA) + +/* + * The interrupt mask 1 register is used to enable or disable + * the RCAR_MMC_INFO1 interrupt. + */ +#define RCAR_MMC_INFO1_MASK 0x080 + +/* + * The interrupt mask 2 register is used to enable or disable + * the RCAR_MMC_INFO2 interrupt. + */ +#define RCAR_MMC_INFO2_MASK 0x088 + +/* + * The SD clock control register is used to control + * the SD clock output and to set the frequency. + */ +#define RCAR_MMC_CLKCTL 0x090 +#define RCAR_MMC_CLKCTL_DIV_MASK 0x104ff +#define RCAR_MMC_CLKCTL_DIV512 BIT(7) /* SDCLK = CLK / 512 */ +#define RCAR_MMC_CLKCTL_DIV256 BIT(6) /* SDCLK = CLK / 256 */ +#define RCAR_MMC_CLKCTL_DIV128 BIT(5) /* SDCLK = CLK / 128 */ +#define RCAR_MMC_CLKCTL_DIV64 BIT(4) /* SDCLK = CLK / 64 */ +#define RCAR_MMC_CLKCTL_DIV32 BIT(3) /* SDCLK = CLK / 32 */ +#define RCAR_MMC_CLKCTL_DIV16 BIT(2) /* SDCLK = CLK / 16 */ +#define RCAR_MMC_CLKCTL_DIV8 BIT(1) /* SDCLK = CLK / 8 */ +#define RCAR_MMC_CLKCTL_DIV4 BIT(0) /* SDCLK = CLK / 4 */ +#define RCAR_MMC_CLKCTL_DIV2 0 /* SDCLK = CLK / 2 */ +#define RCAR_MMC_CLKCTL_RCAR_DIV1 0xff /* SDCLK = CLK (RCar ver.) */ +#define RCAR_MMC_CLKCTL_OFFEN BIT(9) /* stop SDCLK when unused */ +#define RCAR_MMC_CLKCTL_SCLKEN BIT(8) /* SDCLK output enable */ + +/* + * The transfer data length register is used to specify + * the transfer data size. + */ +#define RCAR_MMC_SIZE 0x098 + +/* + * The SD card access control option register is used to set + * the bus width and timeout counter. + */ +#define RCAR_MMC_OPTION 0x0A0 +#define RCAR_MMC_OPTION_WIDTH_MASK (5 << 13) +#define RCAR_MMC_OPTION_WIDTH_1 (4 << 13) +#define RCAR_MMC_OPTION_WIDTH_4 (0 << 13) +#define RCAR_MMC_OPTION_WIDTH_8 (1 << 13) + +/* + * The SD error status register 1 indicates the CRC status, CRC error, + * End error, and CMD error. + */ +#define RCAR_MMC_ERR_STS1 0x0B0 + +/* The SD error status register 2 indicates the timeout state. */ +#define RCAR_MMC_ERR_STS2 0x0B8 + +/* SD Buffer Read/Write Register */ +#define RCAR_MMC_BUF0 0x0C0 + +/* The DMA mode enable register enables the DMA transfer. */ +#define RCAR_MMC_EXTMODE 0x360 +#define RCAR_MMC_EXTMODE_DMA_EN BIT(1) /* transfer 1: DMA, 0: pio */ + +/* The software reset register sets a software reset. */ +#define RCAR_MMC_SOFT_RST 0x380 +#define RCAR_MMC_SOFT_RST_RSTX BIT(0) /* reset deassert */ + +/* The version register indicates the version of the SD host interface. */ +#define RCAR_MMC_VERSION 0x388 +#define RCAR_MMC_VERSION_IP 0xff /* IP version */ + +/* + * The host interface mode setting register selects the width for access to + * the data bus. + */ +#define RCAR_MMC_HOST_MODE 0x390 + +/* The SD interface mode setting register specifies HS400 mode. */ +#define RCAR_MMC_IF_MODE 0x398 +#define RCAR_MMC_IF_MODE_DDR BIT(0) /* DDR mode */ + +/* Set of DMAC registers */ +#define RCAR_MMC_DMA_MODE 0x820 +#define RCAR_MMC_DMA_MODE_DIR_RD BIT(16) /* 1: from device, 0: to dev */ +#define RCAR_MMC_DMA_MODE_WIDTH (BIT(4) | BIT(5)) +#define RCAR_MMC_DMA_MODE_ADDR_INC BIT(0) /* 1: address inc, 0: fixed */ +#define RCAR_MMC_DMA_CTL 0x828 +#define RCAR_MMC_DMA_CTL_START BIT(0) /* start DMA (auto cleared) */ +#define RCAR_MMC_DMA_RST 0x830 +#define RCAR_MMC_DMA_RST_DTRAN0 BIT(8) +#define RCAR_MMC_DMA_RST_DTRAN1 BIT(9) +#define RCAR_MMC_DMA_INFO1 0x840 +#define RCAR_MMC_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete (uniphier) */ +#define RCAR_MMC_DMA_INFO1_END_RD BIT(17) /* DMA from device is complete (renesas) */ +#define RCAR_MMC_DMA_INFO1_END_WR BIT(16) /* DMA to device is complete */ +#define RCAR_MMC_DMA_INFO1_MASK 0x848 +#define RCAR_MMC_DMA_INFO2 0x850 +#define RCAR_MMC_DMA_INFO2_ERR_RD BIT(17) +#define RCAR_MMC_DMA_INFO2_ERR_WR BIT(16) +#define RCAR_MMC_DMA_INFO2_MASK 0x858 +#define RCAR_MMC_DMA_ADDR_L 0x880 +#define RCAR_MMC_DMA_ADDR_H 0x888 + +/* set of SCC registers */ + +/* Initial setting register */ +#define RENESAS_SDHI_SCC_DTCNTL 0x1000 +#define RENESAS_SDHI_SCC_DTCNTL_TAPEN BIT(0) +/* Sampling clock position setting register */ +#define RENESAS_SDHI_SCC_TAPSET 0x1008 +#define RENESAS_SDHI_SCC_DT2FF 0x1010 +/* Sampling Clock Selection Register */ +#define RENESAS_SDHI_SCC_CKSEL 0x1018 +#define RENESAS_SDHI_SCC_CKSEL_DTSEL BIT(0) +/* Sampling Clock Position Correction Register */ +#define RENESAS_SDHI_SCC_RVSCNTL 0x1020 +#define RENESAS_SDHI_SCC_RVSCNTL_RVSEN BIT(0) +/* Sampling Clock Position Correction Request Register */ +#define RENESAS_SDHI_SCC_RVSREQ 0x1028 +#define RENESAS_SDHI_SCC_RVSREQ_REQTAPDOWN BIT(0) +#define RENESAS_SDHI_SCC_RVSREQ_REQTAPUP BIT(1) +#define RENESAS_SDHI_SCC_RVSREQ_REQTAP_MASK \ + (RENESAS_SDHI_SCC_RVSREQ_REQTAPDOWN | RENESAS_SDHI_SCC_RVSREQ_REQTAPUP) +#define RENESAS_SDHI_SCC_RVSREQ_ERR BIT(2) +/* Sampling data comparison register */ +#define RENESAS_SDHI_SCC_SMPCMP 0x1030 +/* Hardware Adjustment Register 2, used for configuration HS400 mode */ +#define RENESAS_SDHI_SCC_TMPPORT2 0x1038 +#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN BIT(31) +#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL BIT(4) + +#endif /* __RCAR_MMC_REGISTERS_H__ */ diff --git a/dts/arm64/renesas/rcar_gen3_ca57.dtsi b/dts/arm64/renesas/rcar_gen3_ca57.dtsi index 5c87c8accd3b4a..d79a557a9cdd04 100644 --- a/dts/arm64/renesas/rcar_gen3_ca57.dtsi +++ b/dts/arm64/renesas/rcar_gen3_ca57.dtsi @@ -28,6 +28,26 @@ ; }; + reg_3p3v: regulator_3p3v { + compatible = "regulator-fixed"; + regulator-name = "reg_3p3v"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + status = "okay"; + }; + + reg_1p8v: regulator_1p8v { + compatible = "regulator-fixed"; + regulator-name = "reg_1p8v"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + status = "okay"; + }; + gic: interrupt-controller@f1010000 { compatible = "arm,gic-400", "arm,gic-v2", "arm,gic" ; #interrupt-cells = <4>; @@ -53,13 +73,36 @@ #reset-cells = <1>; }; + gpio5: gpio@e6055000 { + compatible = "renesas,rcar-gpio"; + reg = <0 0xe6055000 0 0x50>; + #gpio-cells = <2>; + gpio-controller; + interrupt-parent = <&gic>; + interrupts = ; + clocks = <&cpg CPG_MOD 907>; + status = "disabled"; + }; + + sd0: mmc@ee100000 { + compatible = "renesas,rcar-mmc"; + reg = <0 0xee100000 0 0x2000>; + interrupts = ; + clocks = <&cpg CPG_MOD 314>, <&cpg CPG_CORE R8A7795_CLK_SD0H>; + max-bus-freq = <200000000>; + status = "disabled"; + }; + emmc2: mmc@ee140000 { compatible = "renesas,rcar-mmc"; reg = <0 0xee140000 0 0x2000>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; interrupts = ; - clocks = <&cpg CPG_MOD 312>; - max-frequency = <200000000>; + clocks = <&cpg CPG_MOD 312>, <&cpg CPG_CORE R8A7795_CLK_SD2H>; + max-bus-freq = <200000000>; status = "disabled"; }; diff --git a/dts/bindings/mmc/renesas,rcar-emmc.yaml b/dts/bindings/mmc/renesas,rcar-emmc.yaml new file mode 100644 index 00000000000000..fe786d2e197f76 --- /dev/null +++ b/dts/bindings/mmc/renesas,rcar-emmc.yaml @@ -0,0 +1,63 @@ +description: Renesas R-Car eMMC + +compatible: "renesas,rcar-mmc" + +include: [sdhc.yaml, mmc.yaml, pinctrl-device.yaml, reset-device.yaml] + +properties: + clocks: + required: true + + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + max-bus-freq: + required: true + + non-removable: + type: boolean + description: | + Non-removable slots (like eMMC), which are assumed to always be present, + will affect the `sdhc_card_present` call. This call will always return + true if this property exists for the node. + + mmc-sdr104-support: + type: boolean + + cd-gpios: + type: phandle-array + description: Card Detect pin + + pwr-gpios: + type: phandle-array + description: Power pin + + vmmc-supply: + type: phandle + description: | + Supply for the card power + + vqmmc-supply: + type: phandle + description: | + Supply for the bus IO line power, such as a level shifter. + If the level shifter is controlled by a GPIO line, this shall + be modeled as a "regulator-fixed" with a GPIO line for + switching the level shifter on/off. + + bus-width: + type: int + default: 1 + description: | + Bus width for SDMMC access, defaults to the minimum necessary + number of bus lines + enum: + - 1 + - 4 + - 8 From 0e47c18bea02e48120e22d88f63c66235bade5cc Mon Sep 17 00:00:00 2001 From: Mykola Kvach Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0009/1389] boards: arm64: rcar: add board-specific configuration for MMC node Add pin control group for UHS modes for H3ULCB, Salvator XS M3 boards to appropriate dts files. Both 'uhs' and 'default' pins states have the same properties for eMMC, e.g. 1.8V. Signed-off-by: Mykola Kvach --- .../rcar_h3ulcb/doc/rcar_h3ulcb_a57.rst | 2 + .../rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi | 44 +++++++++++++++++++ .../rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts | 23 ++++++++++ boards/renesas/rcar_salvator_xs/doc/index.rst | 2 + .../rcar_salvator_xs-pinctrl.dtsi | 44 +++++++++++++++++++ .../rcar_salvator_xs/rcar_salvator_xs.dts | 23 ++++++++++ 6 files changed, 138 insertions(+) diff --git a/boards/renesas/rcar_h3ulcb/doc/rcar_h3ulcb_a57.rst b/boards/renesas/rcar_h3ulcb/doc/rcar_h3ulcb_a57.rst index d7a261dbb5c12b..aefe429f5c88d0 100644 --- a/boards/renesas/rcar_h3ulcb/doc/rcar_h3ulcb_a57.rst +++ b/boards/renesas/rcar_h3ulcb/doc/rcar_h3ulcb_a57.rst @@ -58,6 +58,8 @@ hardware features: +-----------+------------------------------+--------------------------------+ | UART | uart | serial port-polling | +-----------+------------------------------+--------------------------------+ +| MMC | renesas_rcar_mmc | DMA and SCC | ++-----------+------------------------------+--------------------------------+ Other hardware features have not been enabled yet for this board. diff --git a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi index 088f930051dbb5..6dc65b033137e1 100644 --- a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi +++ b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi @@ -14,4 +14,48 @@ scif2_data_a_rx_default: scif2_data_a_rx_default { pin = ; }; + + emmc2_clk: emmc2_clk { + pin = ; + }; + + emmc2_cmd: emmc2_cmd { + pin = ; + }; + + emmc2_data0: emmc2_data0 { + pin = ; + }; + + emmc2_data1: emmc2_data1 { + pin = ; + }; + + emmc2_data2: emmc2_data2 { + pin = ; + }; + + emmc2_data3: emmc2_data3 { + pin = ; + }; + + emmc2_data4: emmc2_data4 { + pin = ; + }; + + emmc2_data5: emmc2_data5 { + pin = ; + }; + + emmc2_data6: emmc2_data6 { + pin = ; + }; + + emmc2_data7: emmc2_data7 { + pin = ; + }; + + emmc2_ds: emmc2_ds { + pin = ; + }; }; diff --git a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts index 5a2bef11c82bd0..599a0f25314beb 100644 --- a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts +++ b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts @@ -23,6 +23,11 @@ device_type = "mmio-sram"; reg = <0x0 0x48000000 0x0 DT_SIZE_M(512)>; }; + + /* These aliases are provided for compatibility with samples */ + aliases { + sdhc0 = &emmc2; + }; }; &scif2 { @@ -30,3 +35,21 @@ pinctrl-names = "default"; status = "okay"; }; + +&emmc2 { + pinctrl-0 = <&emmc2_clk &emmc2_cmd &emmc2_ds + &emmc2_data0 &emmc2_data1 &emmc2_data2 &emmc2_data3 + &emmc2_data4 &emmc2_data5 &emmc2_data6 &emmc2_data7>; + pinctrl-1 = <&emmc2_clk &emmc2_cmd &emmc2_ds + &emmc2_data0 &emmc2_data1 &emmc2_data2 &emmc2_data3 + &emmc2_data4 &emmc2_data5 &emmc2_data6 &emmc2_data7>; + pinctrl-names = "default", "uhs"; + disk { + compatible = "zephyr,mmc-disk"; + status = "disabled"; + }; + bus-width = <8>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + non-removable; +}; diff --git a/boards/renesas/rcar_salvator_xs/doc/index.rst b/boards/renesas/rcar_salvator_xs/doc/index.rst index a9900158169fc2..464b4e659d7144 100644 --- a/boards/renesas/rcar_salvator_xs/doc/index.rst +++ b/boards/renesas/rcar_salvator_xs/doc/index.rst @@ -43,6 +43,8 @@ hardware features: +-----------+------------------------------+--------------------------------+ | UART | uart | serial port-polling | +-----------+------------------------------+--------------------------------+ +| MMC | renesas_rcar_mmc | DMA and SCC | ++-----------+------------------------------+--------------------------------+ Other hardware features have not been enabled yet for this board. diff --git a/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi b/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi index 69529f233ace64..b563a720079f84 100644 --- a/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi +++ b/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi @@ -14,4 +14,48 @@ scif2_data_a_rx_default: scif2_data_a_rx_default { pin = ; }; + + emmc2_clk: emmc2_clk { + pin = ; + }; + + emmc2_cmd: emmc2_cmd { + pin = ; + }; + + emmc2_data0: emmc2_data0 { + pin = ; + }; + + emmc2_data1: emmc2_data1 { + pin = ; + }; + + emmc2_data2: emmc2_data2 { + pin = ; + }; + + emmc2_data3: emmc2_data3 { + pin = ; + }; + + emmc2_data4: emmc2_data4 { + pin = ; + }; + + emmc2_data5: emmc2_data5 { + pin = ; + }; + + emmc2_data6: emmc2_data6 { + pin = ; + }; + + emmc2_data7: emmc2_data7 { + pin = ; + }; + + emmc2_ds: emmc2_ds { + pin = ; + }; }; diff --git a/boards/renesas/rcar_salvator_xs/rcar_salvator_xs.dts b/boards/renesas/rcar_salvator_xs/rcar_salvator_xs.dts index 9c6bfc9a6ebf91..bc926dfddd4fc0 100644 --- a/boards/renesas/rcar_salvator_xs/rcar_salvator_xs.dts +++ b/boards/renesas/rcar_salvator_xs/rcar_salvator_xs.dts @@ -19,6 +19,11 @@ zephyr,shell-uart = &scif2; }; + /* These aliases are provided for compatibility with samples */ + aliases { + sdhc0 = &emmc2; + }; + ram: memory@48000000 { device_type = "mmio-sram"; reg = <0x0 0x48000000 0x0 DT_SIZE_M(512)>; @@ -30,3 +35,21 @@ pinctrl-names = "default"; status = "okay"; }; + +&emmc2 { + pinctrl-0 = <&emmc2_clk &emmc2_cmd &emmc2_ds + &emmc2_data0 &emmc2_data1 &emmc2_data2 &emmc2_data3 + &emmc2_data4 &emmc2_data5 &emmc2_data6 &emmc2_data7>; + pinctrl-1 = <&emmc2_clk &emmc2_cmd &emmc2_ds + &emmc2_data0 &emmc2_data1 &emmc2_data2 &emmc2_data3 + &emmc2_data4 &emmc2_data5 &emmc2_data6 &emmc2_data7>; + pinctrl-names = "default", "uhs"; + disk { + compatible = "zephyr,mmc-disk"; + status = "disabled"; + }; + bus-width = <8>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + non-removable; +}; From b21a2414b2657b6f98cc86e9ceb57ec590918b6e Mon Sep 17 00:00:00 2001 From: Mykola Kvach Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0010/1389] tests: add h3ulcb and salvator xs m3configs to perf disk tests Add MMC related cfgs/overlays of arm64 gen3 rcar boards to perf and susys/sd/mmc tests. Signed-off-by: Mykola Kvach --- .../boards/rcar_h3ulcb_r8a77951_a57.overlay | 8 ++++++++ .../disk/disk_performance/boards/rcar_salvator_xs.overlay | 8 ++++++++ .../subsys/sd/mmc/boards/rcar_h3ulcb_r8a77951_a57.overlay | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/drivers/disk/disk_performance/boards/rcar_h3ulcb_r8a77951_a57.overlay create mode 100644 tests/drivers/disk/disk_performance/boards/rcar_salvator_xs.overlay create mode 100644 tests/subsys/sd/mmc/boards/rcar_h3ulcb_r8a77951_a57.overlay diff --git a/tests/drivers/disk/disk_performance/boards/rcar_h3ulcb_r8a77951_a57.overlay b/tests/drivers/disk/disk_performance/boards/rcar_h3ulcb_r8a77951_a57.overlay new file mode 100644 index 00000000000000..9442e02b45f51d --- /dev/null +++ b/tests/drivers/disk/disk_performance/boards/rcar_h3ulcb_r8a77951_a57.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&emmc2 { + disk { + status = "okay"; + }; + status = "okay"; +}; diff --git a/tests/drivers/disk/disk_performance/boards/rcar_salvator_xs.overlay b/tests/drivers/disk/disk_performance/boards/rcar_salvator_xs.overlay new file mode 100644 index 00000000000000..9442e02b45f51d --- /dev/null +++ b/tests/drivers/disk/disk_performance/boards/rcar_salvator_xs.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&emmc2 { + disk { + status = "okay"; + }; + status = "okay"; +}; diff --git a/tests/subsys/sd/mmc/boards/rcar_h3ulcb_r8a77951_a57.overlay b/tests/subsys/sd/mmc/boards/rcar_h3ulcb_r8a77951_a57.overlay new file mode 100644 index 00000000000000..9442e02b45f51d --- /dev/null +++ b/tests/subsys/sd/mmc/boards/rcar_h3ulcb_r8a77951_a57.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&emmc2 { + disk { + status = "okay"; + }; + status = "okay"; +}; From 48153cb7c386442aff5195a15c59cd9355155dfa Mon Sep 17 00:00:00 2001 From: Mykola Kvach Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0011/1389] samples: littlefs: add support for H3ULCB and Salvator XS M3 Add support of R-Car H3ULCB and Salvator XS M3 boards to littlefs sample. Signed-off-by: Mykola Kvach --- .../boards/rcar_h3ulcb_r8a77951_a57.conf | 17 +++++++++++++++++ .../boards/rcar_h3ulcb_r8a77951_a57.overlay | 8 ++++++++ .../fs/littlefs/boards/rcar_salvator_xs.conf | 17 +++++++++++++++++ .../fs/littlefs/boards/rcar_salvator_xs.overlay | 8 ++++++++ samples/subsys/fs/littlefs/sample.yaml | 2 ++ 5 files changed, 52 insertions(+) create mode 100644 samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf create mode 100644 samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.overlay create mode 100644 samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf create mode 100644 samples/subsys/fs/littlefs/boards/rcar_salvator_xs.overlay diff --git a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf new file mode 100644 index 00000000000000..f2dffe4fe097a7 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf @@ -0,0 +1,17 @@ +# +# Copyright (c) 2023 EPAM Systems +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_DISK_ACCESS=y +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_MMC=y + +CONFIG_FS_LITTLEFS_BLK_DEV=y +CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y + +CONFIG_FS_LITTLEFS_FMP_DEV=n diff --git a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.overlay b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.overlay new file mode 100644 index 00000000000000..9442e02b45f51d --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&emmc2 { + disk { + status = "okay"; + }; + status = "okay"; +}; diff --git a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf new file mode 100644 index 00000000000000..f2dffe4fe097a7 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf @@ -0,0 +1,17 @@ +# +# Copyright (c) 2023 EPAM Systems +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_DISK_ACCESS=y +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_MMC=y + +CONFIG_FS_LITTLEFS_BLK_DEV=y +CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y + +CONFIG_FS_LITTLEFS_FMP_DEV=n diff --git a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.overlay b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.overlay new file mode 100644 index 00000000000000..9442e02b45f51d --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&emmc2 { + disk { + status = "okay"; + }; + status = "okay"; +}; diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index b78a070f1c9d59..89ffe9f16ae8d6 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -20,6 +20,8 @@ tests: - mimxrt1160_evk/mimxrt1166/cm7 - lpcxpresso55s69/lpc55s69/cpu0 - mr_canhubk3 + - rcar_h3ulcb/r8a77951/a57 + - rcar_salvator_xs - stm32f429i_disc1 - stm32f746g_disco - stm32h747i_disco/stm32h747xx/m7 From 23513236d1976add740937a06d851acad5915f83 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0012/1389] coding guidelines: comply with MISRA Rule 20.9 - avoid to use undefined macros in #if expressions Signed-off-by: Hess Nathan --- kernel/include/kernel_internal.h | 2 +- kernel/include/kthread.h | 2 +- kernel/init.c | 2 +- kernel/thread.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index c598720999a477..b2e1ccf7068234 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -140,7 +140,7 @@ extern void smp_timer_init(void); extern void z_early_rand_get(uint8_t *buf, size_t length); -#if CONFIG_STACK_POINTER_RANDOM +#if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0) extern int z_stack_adjust_initialized; #endif /* CONFIG_STACK_POINTER_RANDOM */ diff --git a/kernel/include/kthread.h b/kernel/include/kthread.h index 9311552e0f09fb..bf5fb1da08f5fb 100644 --- a/kernel/include/kthread.h +++ b/kernel/include/kthread.h @@ -75,7 +75,7 @@ static inline int thread_is_metairq(struct k_thread *thread) #endif /* CONFIG_NUM_METAIRQ_PRIORITIES */ } -#if CONFIG_ASSERT +#ifdef CONFIG_ASSERT static inline bool is_thread_dummy(struct k_thread *thread) { return (thread->base.thread_state & _THREAD_DUMMY) != 0U; diff --git a/kernel/init.c b/kernel/init.c index 76a4bbe238a6ac..54b34dce5e9288 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -424,7 +424,7 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) z_sys_post_kernel = true; z_sys_init_run_level(INIT_LEVEL_POST_KERNEL); -#if CONFIG_STACK_POINTER_RANDOM +#if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0) z_stack_adjust_initialized = 1; #endif /* CONFIG_STACK_POINTER_RANDOM */ boot_banner(); diff --git a/kernel/thread.c b/kernel/thread.c index 981a048bb0dc71..e11e53087d0dce 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -356,7 +356,7 @@ static inline void z_vrfy_k_thread_start(struct k_thread *thread) #include #endif /* CONFIG_USERSPACE */ -#if CONFIG_STACK_POINTER_RANDOM +#if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0) int z_stack_adjust_initialized; static size_t random_offset(size_t stack_size) @@ -487,7 +487,7 @@ static char *setup_thread_stack(struct k_thread *new_thread, new_thread->userspace_local_data = (struct _thread_userspace_local_data *)(stack_ptr - delta); #endif /* CONFIG_THREAD_USERSPACE_LOCAL_DATA */ -#if CONFIG_STACK_POINTER_RANDOM +#if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0) delta += random_offset(stack_buf_size); #endif /* CONFIG_STACK_POINTER_RANDOM */ delta = ROUND_UP(delta, ARCH_STACK_PTR_ALIGN); From de40ab128cfb8ea85647be7b3058aa71a9ba1ab1 Mon Sep 17 00:00:00 2001 From: Bram Vlerick Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0013/1389] samples: drivers: add i2c eeprom target sample Add simple sample for the i2c target driver interface using the i2c-target-eeprom as a target device. Signed-off-by: Bram Vlerick --- .../drivers/i2c/target_eeprom/CMakeLists.txt | 8 ++++ samples/drivers/i2c/target_eeprom/README.rst | 31 ++++++++++++++ .../lpcxpresso55s69_lpc55s69_cpu0.overlay | 16 ++++++++ samples/drivers/i2c/target_eeprom/prj.conf | 3 ++ samples/drivers/i2c/target_eeprom/sample.yaml | 9 +++++ samples/drivers/i2c/target_eeprom/src/main.c | 40 +++++++++++++++++++ 6 files changed, 107 insertions(+) create mode 100644 samples/drivers/i2c/target_eeprom/CMakeLists.txt create mode 100644 samples/drivers/i2c/target_eeprom/README.rst create mode 100644 samples/drivers/i2c/target_eeprom/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay create mode 100644 samples/drivers/i2c/target_eeprom/prj.conf create mode 100644 samples/drivers/i2c/target_eeprom/sample.yaml create mode 100644 samples/drivers/i2c/target_eeprom/src/main.c diff --git a/samples/drivers/i2c/target_eeprom/CMakeLists.txt b/samples/drivers/i2c/target_eeprom/CMakeLists.txt new file mode 100644 index 00000000000000..ecac4629ac0485 --- /dev/null +++ b/samples/drivers/i2c/target_eeprom/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(i2c_target) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/i2c/target_eeprom/README.rst b/samples/drivers/i2c/target_eeprom/README.rst new file mode 100644 index 00000000000000..6b91aa0c1f5757 --- /dev/null +++ b/samples/drivers/i2c/target_eeprom/README.rst @@ -0,0 +1,31 @@ +.. zephyr:code-sample:: i2c-eeprom-target + :name: I2C Target + :relevant-api: i2c_interface + + Setup an I2C target on the I2C interface. + +Overview +******** + +This sample demonstrates how to setup and use the :ref:`i2c-target-api` using the +:dtcompatible:`zephyr,i2c-target-eeprom` device. + +Requirements +************ + +This sample requires an I2C peripheral which is capable of acting as a target. + +This sample has been tested on :ref:`lpcxpresso55s69`. + +Building and Running +******************** + +The code for this sample can be found in :zephyr_file:`samples/drivers/i2c_target`. + +To build and flash the application: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/i2c_target + :board: lpcxpresso55s69/lpc55s69/cpu0 + :goals: flash + :compact: diff --git a/samples/drivers/i2c/target_eeprom/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay b/samples/drivers/i2c/target_eeprom/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay new file mode 100644 index 00000000000000..ab2cc09bcaf68a --- /dev/null +++ b/samples/drivers/i2c/target_eeprom/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Open Pixel Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flexcomm4 { + status = "okay"; + + eeprom0: eeprom@50 { + reg = <0x50>; + size = <256>; + compatible = "zephyr,i2c-target-eeprom"; + status = "okay"; + }; +}; diff --git a/samples/drivers/i2c/target_eeprom/prj.conf b/samples/drivers/i2c/target_eeprom/prj.conf new file mode 100644 index 00000000000000..03350edd9236db --- /dev/null +++ b/samples/drivers/i2c/target_eeprom/prj.conf @@ -0,0 +1,3 @@ +CONFIG_I2C=y +CONFIG_I2C_TARGET=y +CONFIG_I2C_EEPROM_TARGET=y diff --git a/samples/drivers/i2c/target_eeprom/sample.yaml b/samples/drivers/i2c/target_eeprom/sample.yaml new file mode 100644 index 00000000000000..ed61e564b51cdc --- /dev/null +++ b/samples/drivers/i2c/target_eeprom/sample.yaml @@ -0,0 +1,9 @@ +sample: + name: I2C target sample +tests: + sample.drivers.i2c.target: + tags: i2c_target + filter: dt_nodelabel_enabled("target_eeprom") + platform_allow: + - lpcxpresso55s69/lpc55s69/cpu0 + harness: TBD diff --git a/samples/drivers/i2c/target_eeprom/src/main.c b/samples/drivers/i2c/target_eeprom/src/main.c new file mode 100644 index 00000000000000..d1c42f9a401644 --- /dev/null +++ b/samples/drivers/i2c/target_eeprom/src/main.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Open Pixel Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +static const struct device *eeprom = DEVICE_DT_GET(DT_NODELABEL(eeprom0)); + +int main(void) +{ + printk("i2c target sample\n"); + + if (!device_is_ready(eeprom)) { + printk("eeprom device not ready\n"); + return 0; + } + + if (i2c_target_driver_register(eeprom) < 0) { + printk("Failed to register i2c target driver\n"); + return 0; + } + + printk("i2c target driver registered\n"); + + k_msleep(1000); + + if (i2c_target_driver_unregister(eeprom) < 0) { + printk("Failed to unregister i2c target driver\n"); + return 0; + } + + printk("i2c target driver unregistered\n"); + + return 0; +} From 01ac9175b023d85b03afbb52fa637efc844318d2 Mon Sep 17 00:00:00 2001 From: Bram Vlerick Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0014/1389] samples: drivers: i2c: add i2c target api sample Add simple sample which demonstrates how to setup a custom i2c target. Signed-off-by: Bram Vlerick --- .../drivers/i2c/custom_target/CMakeLists.txt | 8 ++ samples/drivers/i2c/custom_target/README.rst | 31 ++++++ .../lpcxpresso55s69_lpc55s69_cpu0.overlay | 9 ++ samples/drivers/i2c/custom_target/prj.conf | 2 + samples/drivers/i2c/custom_target/sample.yaml | 8 ++ samples/drivers/i2c/custom_target/src/main.c | 100 ++++++++++++++++++ 6 files changed, 158 insertions(+) create mode 100644 samples/drivers/i2c/custom_target/CMakeLists.txt create mode 100644 samples/drivers/i2c/custom_target/README.rst create mode 100644 samples/drivers/i2c/custom_target/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay create mode 100644 samples/drivers/i2c/custom_target/prj.conf create mode 100644 samples/drivers/i2c/custom_target/sample.yaml create mode 100644 samples/drivers/i2c/custom_target/src/main.c diff --git a/samples/drivers/i2c/custom_target/CMakeLists.txt b/samples/drivers/i2c/custom_target/CMakeLists.txt new file mode 100644 index 00000000000000..1a1702c4216f9f --- /dev/null +++ b/samples/drivers/i2c/custom_target/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(i2c_custom_target) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/i2c/custom_target/README.rst b/samples/drivers/i2c/custom_target/README.rst new file mode 100644 index 00000000000000..a3d86482888792 --- /dev/null +++ b/samples/drivers/i2c/custom_target/README.rst @@ -0,0 +1,31 @@ +.. zephyr:code-sample:: i2c-custom-target + :name: I2C Custom Target + :relevant-api: i2c_interface + + Setup a custom I2C target on the I2C interface. + +Overview +******** + +This sample demonstrates how to setup an I2C custom target on the I2C interface +using the :ref:`i2c-target-api`. + +Requirements +************ + +This sample requires an I2C peripheral which is capable of acting as a target. + +This sample has been tested on :ref:`lpcxpresso55s69`. + +Building and Running +******************** + +The code for this sample can be found in :zephyr_file:`samples/drivers/i2c_target`. + +To build and flash the application: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/i2c_target + :board: lpcxpresso55s69/lpc55s69/cpu0 + :goals: flash + :compact: diff --git a/samples/drivers/i2c/custom_target/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay b/samples/drivers/i2c/custom_target/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay new file mode 100644 index 00000000000000..8826b80c5525c5 --- /dev/null +++ b/samples/drivers/i2c/custom_target/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Open Pixel Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flexcomm4 { + status = "okay"; +}; diff --git a/samples/drivers/i2c/custom_target/prj.conf b/samples/drivers/i2c/custom_target/prj.conf new file mode 100644 index 00000000000000..f3d64527b85f30 --- /dev/null +++ b/samples/drivers/i2c/custom_target/prj.conf @@ -0,0 +1,2 @@ +CONFIG_I2C=y +CONFIG_I2C_TARGET=y diff --git a/samples/drivers/i2c/custom_target/sample.yaml b/samples/drivers/i2c/custom_target/sample.yaml new file mode 100644 index 00000000000000..dd8cc903dbb5cb --- /dev/null +++ b/samples/drivers/i2c/custom_target/sample.yaml @@ -0,0 +1,8 @@ +sample: + name: I2C custom target sample +tests: + sample.drivers.i2c.custom_target: + tags: i2c_target + platform_allow: + - lpcxpresso55s69/lpc55s69/cpu0 + harness: TBD diff --git a/samples/drivers/i2c/custom_target/src/main.c b/samples/drivers/i2c/custom_target/src/main.c new file mode 100644 index 00000000000000..83a0003cb34f0b --- /dev/null +++ b/samples/drivers/i2c/custom_target/src/main.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 Open Pixel Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static const struct device *bus = DEVICE_DT_GET(DT_NODELABEL(flexcomm4)); +static char last_byte; + +/* + * @brief Callback which is called when a write request is received from the master. + * @param config Pointer to the target configuration. + */ +int sample_target_write_requested_cb(struct i2c_target_config *config) +{ + printk("sample target write requested\n"); + return 0; +} + +/* + * @brief Callback which is called when a write is received from the master. + * @param config Pointer to the target configuration. + * @param val The byte received from the master. + */ +int sample_target_write_received_cb(struct i2c_target_config *config, uint8_t val) +{ + printk("sample target write received: 0x%02x\n", val); + last_byte = val; + return 0; +} + +/* + * @brief Callback which is called when a read request is received from the master. + * @param config Pointer to the target configuration. + * @param val Pointer to the byte to be sent to the master. + */ +int sample_target_read_requested_cb(struct i2c_target_config *config, uint8_t *val) +{ + printk("sample target read request: 0x%02x\n", *val); + *val = 0x42; + return 0; +} + +/* + * @brief Callback which is called when a read is processed from the master. + * @param config Pointer to the target configuration. + * @param val Pointer to the next byte to be sent to the master. + */ +int sample_target_read_processed_cb(struct i2c_target_config *config, uint8_t *val) +{ + printk("sample target read processed: 0x%02x\n", *val); + *val = 0x43; + return 0; +} + +/* + * @brief Callback which is called when the master sends a stop condition. + * @param config Pointer to the target configuration. + */ +int sample_target_stop_cb(struct i2c_target_config *config) +{ + printk("sample target stop callback\n"); + return 0; +} + +static struct i2c_target_callbacks sample_target_callbacks = { + .write_requested = sample_target_write_requested_cb, + .write_received = sample_target_write_received_cb, + .read_requested = sample_target_read_requested_cb, + .read_processed = sample_target_read_processed_cb, + .stop = sample_target_stop_cb, +}; + +int main(void) +{ + struct i2c_target_config target_cfg = { + .address = 0x60, + .callbacks = &sample_target_callbacks, + }; + + printk("i2c custom target sample\n"); + + if (i2c_target_register(bus, &target_cfg) < 0) { + printk("Failed to register target\n"); + return -1; + } + + k_msleep(5000); + + if (i2c_target_unregister(bus, &target_cfg) < 0) { + printk("Failed to unregister target\n"); + return -1; + } + + return 0; +} From 428affb5257cfdc4c9a6e0c76e0a2d2a06432617 Mon Sep 17 00:00:00 2001 From: Bram Vlerick Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0015/1389] MAINTAINERS.yml: add new samples/drivers/i2c Add samples/drivers/i2c to the maintainers file so the correct code owners get added in PRs Signed-off-by: Bram Vlerick --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 2b0d010cce7c2e..53de3ee3da2bb3 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1375,6 +1375,7 @@ Release Notes: - include/zephyr/dt-bindings/i2c/ - tests/boards/*/i2c/ - tests/drivers/*/i2c/ + - samples/drivers/i2c/ labels: - "area: I2C" tests: From 82d8ca602a87f2665b903a224c921f371baa2b2e Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Sun, 26 May 2024 22:38:22 +0200 Subject: [PATCH 0016/1389] kernel: Drop non-negative from timeout descriptions Drops "non-negative" from a few stray kernel API timeout descriptions as a negative timeout is actually valid and represents an absolute timeout. Signed-off-by: Peter Mitsis --- include/zephyr/kernel.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 6a3bd04c0a7dfd..943d7dc89b759b 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -2017,9 +2017,8 @@ int k_queue_merge_slist(struct k_queue *queue, sys_slist_t *list); * @funcprops \isr_ok * * @param queue Address of the queue. - * @param timeout Non-negative waiting period to obtain a data item - * or one of the special values K_NO_WAIT and - * K_FOREVER. + * @param timeout Waiting period to obtain a data item, or one of the special + * values K_NO_WAIT and K_FOREVER. * * @return Address of the data item if successful; NULL if returned * without waiting, or waiting period timed out. @@ -2163,8 +2162,8 @@ struct z_futex_data { * @param futex Address of the futex. * @param expected Expected value of the futex, if it is different the caller * will not wait on it. - * @param timeout Non-negative waiting period on the futex, or - * one of the special values K_NO_WAIT or K_FOREVER. + * @param timeout Waiting period on the futex, or one of the special values + * K_NO_WAIT or K_FOREVER. * @retval -EACCES Caller does not have read access to futex address. * @retval -EAGAIN If the futex value did not match the expected parameter. * @retval -EINVAL Futex parameter address not recognized by the kernel. @@ -4564,9 +4563,8 @@ int k_msgq_cleanup(struct k_msgq *msgq); * * @param msgq Address of the message queue. * @param data Pointer to the message. - * @param timeout Non-negative waiting period to add the message, - * or one of the special values K_NO_WAIT and - * K_FOREVER. + * @param timeout Waiting period to add the message, or one of the special + * values K_NO_WAIT and K_FOREVER. * * @retval 0 Message sent. * @retval -ENOMSG Returned without waiting or queue purged. @@ -5191,7 +5189,7 @@ int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, * * @param slab Address of the memory slab. * @param mem Pointer to block address area. - * @param timeout Non-negative waiting period to wait for operation to complete. + * @param timeout Waiting period to wait for operation to complete. * Use K_NO_WAIT to return without waiting, * or K_FOREVER to wait as long as necessary. * From 7bc6fc797fa4a3314b5a92ef0cccc5a5270c4af3 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0017/1389] ci: check_compliance: use inclusive language UNDEF_KCONFIG_WHITELIST -> UNDEF_KCONFIG_ALLOWLIS Fixes #72044 Signed-off-by: Anas Nashif --- scripts/ci/check_compliance.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index ea86465235d03a..1bd39950ddefea 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -801,7 +801,7 @@ def check_no_undef_outside_kconfig(self, kconf): for sym_name in re.findall(regex, line): sym_name = sym_name[7:] # Strip CONFIG_ if sym_name not in defined_syms and \ - sym_name not in self.UNDEF_KCONFIG_WHITELIST: + sym_name not in self.UNDEF_KCONFIG_ALLOWLIST: undef_to_locs[sym_name].append(f"{path}:{lineno}") @@ -819,7 +819,7 @@ def check_no_undef_outside_kconfig(self, kconf): self.failure(f""" Found references to undefined Kconfig symbols. If any of these are false -positives, then add them to UNDEF_KCONFIG_WHITELIST in {__file__}. +positives, then add them to UNDEF_KCONFIG_ALLOWLIST in {__file__}. If the reference is for a comment like /* CONFIG_FOO_* */ (or /* CONFIG_FOO_*_... */), then please use exactly that form (with the '*'). The @@ -832,7 +832,7 @@ def check_no_undef_outside_kconfig(self, kconf): # Many of these are symbols used as examples. Note that the list is sorted # alphabetically, and skips the CONFIG_ prefix. - UNDEF_KCONFIG_WHITELIST = { + UNDEF_KCONFIG_ALLOWLIST = { "ALSO_MISSING", "APP_LINK_WITH_", "APP_LOG_LEVEL", # Application log level is not detected correctly as From a5ab3c8393a3097e57c28598c31dad2b5d863d0e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0018/1389] sys: sflist: replace unative_t with uintptr_t We already have uintptr_t which purpose is exactly what we need here. Signed-off-by: Nicolas Pitre --- include/zephyr/sys/sflist.h | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/include/zephyr/sys/sflist.h b/include/zephyr/sys/sflist.h index 97580800831b8a..c43ad5a208811a 100644 --- a/include/zephyr/sys/sflist.h +++ b/include/zephyr/sys/sflist.h @@ -25,7 +25,7 @@ #ifndef ZEPHYR_INCLUDE_SYS_SFLIST_H_ #define ZEPHYR_INCLUDE_SYS_SFLIST_H_ -#include +#include #include #include #include "list_gen.h" @@ -34,15 +34,9 @@ extern "C" { #endif -#ifdef __LP64__ -typedef uint64_t unative_t; -#else -typedef uint32_t unative_t; -#endif - /** @cond INTERNAL_HIDDEN */ struct _sfnode { - unative_t next_and_flags; + uintptr_t next_and_flags; }; /** @endcond */ @@ -218,7 +212,8 @@ static inline void sys_sflist_init(sys_sflist_t *list) * @param ptr_to_list A pointer on the list to initialize */ #define SYS_SFLIST_STATIC_INIT(ptr_to_list) {NULL, NULL} -#define SYS_SFLIST_FLAGS_MASK 0x3UL + +#define SYS_SFLIST_FLAGS_MASK ((uintptr_t)0x3) static inline sys_sfnode_t *z_sfnode_next_peek(sys_sfnode_t *node) { @@ -232,7 +227,7 @@ static inline void z_sfnode_next_set(sys_sfnode_t *parent, { uint8_t cur_flags = sys_sfnode_flags_get(parent); - parent->next_and_flags = cur_flags | (unative_t)child; + parent->next_and_flags = cur_flags | (uintptr_t)child; } static inline void z_sflist_head_set(sys_sflist_t *list, sys_sfnode_t *node) @@ -316,7 +311,7 @@ static inline void sys_sfnode_init(sys_sfnode_t *node, uint8_t flags) static inline void sys_sfnode_flags_set(sys_sfnode_t *node, uint8_t flags) { __ASSERT((flags & ~SYS_SFLIST_FLAGS_MASK) == 0UL, "flags too large"); - node->next_and_flags = (unative_t)(z_sfnode_next_peek(node)) | flags; + node->next_and_flags = (uintptr_t)(z_sfnode_next_peek(node)) | flags; } /* From a092ae2d626dfbae5328e31ee741916bdf4feb81 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0019/1389] sys: sflist: allow usage of all available flag bits Room for flag bits is function of the struct sfnode alignment. Define the flag mask accordingly. This gives 2 available bits on 32-bit architectures and 3 bits on 64-bit architectures. Signed-off-by: Nicolas Pitre --- include/zephyr/sys/sflist.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/include/zephyr/sys/sflist.h b/include/zephyr/sys/sflist.h index c43ad5a208811a..f26c69270a466d 100644 --- a/include/zephyr/sys/sflist.h +++ b/include/zephyr/sys/sflist.h @@ -12,7 +12,7 @@ * @brief Flagged single-linked list implementation. * * Similar to @ref single-linked-list_apis with the added ability to define - * two bits of user "flags" for each node. They can be accessed and modified + * user "flags" bits for each node. They can be accessed and modified * using the sys_sfnode_flags_get() and sys_sfnode_flags_set() APIs. * * Flagged single-linked list implementation using inline macros/functions. @@ -213,7 +213,10 @@ static inline void sys_sflist_init(sys_sflist_t *list) */ #define SYS_SFLIST_STATIC_INIT(ptr_to_list) {NULL, NULL} -#define SYS_SFLIST_FLAGS_MASK ((uintptr_t)0x3) +/* Flag bits are stored in unused LSB of the sys_sfnode_t pointer */ +#define SYS_SFLIST_FLAGS_MASK ((uintptr_t)(__alignof__(sys_sfnode_t) - 1)) +/* At least 2 available flag bits are expected */ +BUILD_ASSERT(SYS_SFLIST_FLAGS_MASK >= 0x3); static inline sys_sfnode_t *z_sfnode_next_peek(sys_sfnode_t *node) { @@ -272,7 +275,8 @@ static inline sys_sfnode_t *sys_sflist_peek_tail(sys_sflist_t *list) * @brief Fetch flags value for a particular sfnode * * @param node A pointer to the node to fetch flags from - * @return The value of flags, which will be between 0 and 3 + * @return The value of flags, which will be between 0 and 3 on 32-bit + * architectures, or between 0 and 7 on 64-bit architectures */ static inline uint8_t sys_sfnode_flags_get(sys_sfnode_t *node) { @@ -283,14 +287,15 @@ static inline uint8_t sys_sfnode_flags_get(sys_sfnode_t *node) * @brief Initialize an sflist node * * Set an initial flags value for this slist node, which can be a value between - * 0 and 3. These flags will persist even if the node is moved around - * within a list, removed, or transplanted to a different slist. + * 0 and 3 on 32-bit architectures, or between 0 and 7 on 64-bit architectures. + * These flags will persist even if the node is moved around within a list, + * removed, or transplanted to a different slist. * * This is ever so slightly faster than sys_sfnode_flags_set() and should * only be used on a node that hasn't been added to any list. * * @param node A pointer to the node to set the flags on - * @param flags A value between 0 and 3 to set the flags value + * @param flags The flags value to set */ static inline void sys_sfnode_init(sys_sfnode_t *node, uint8_t flags) { @@ -302,11 +307,12 @@ static inline void sys_sfnode_init(sys_sfnode_t *node, uint8_t flags) * @brief Set flags value for an sflist node * * Set a flags value for this slist node, which can be a value between - * 0 and 3. These flags will persist even if the node is moved around - * within a list, removed, or transplanted to a different slist. + * 0 and 3 on 32-bit architectures, or between 0 and 7 on 64-bit architectures. + * These flags will persist even if the node is moved around within a list, + * removed, or transplanted to a different slist. * * @param node A pointer to the node to set the flags on - * @param flags A value between 0 and 3 to set the flags value + * @param flags The flags value to set */ static inline void sys_sfnode_flags_set(sys_sfnode_t *node, uint8_t flags) { From 285230f83111b8a3504e43fce8d4e8d3086ddfb0 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0020/1389] kernel: timeslicing: add time slice reset in slice per thread api This will reset time slice in k_thread_time_slice_set() when slice per thread api is used. Currently it will reset it only in standard slice_set Signed-off-by: Adrian Bonislawski --- kernel/timeslicing.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/timeslicing.c b/kernel/timeslicing.c index 401bcea0c7c4b8..07ae497c7f91e6 100644 --- a/kernel/timeslicing.c +++ b/kernel/timeslicing.c @@ -95,6 +95,7 @@ void k_thread_time_slice_set(struct k_thread *thread, int32_t thread_slice_ticks thread->base.slice_ticks = thread_slice_ticks; thread->base.slice_expired = expired; thread->base.slice_data = data; + z_reset_time_slice(thread); } } #endif From 47cb2c2beb33a5e793d949995c7e14b0f92fd008 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0021/1389] include: sys: util: implement `NUM_VA_ARGS` This macro count the number of arguments in the variable arguments list. Added test for it in `tests/lib/sys_util`. Signed-off-by: Yong Cong Sin --- include/zephyr/sys/util_macro.h | 11 +++++++++++ tests/lib/sys_util/src/main.c | 15 +++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/zephyr/sys/util_macro.h b/include/zephyr/sys/util_macro.h index 81df23f9150bf6..24784f91e638fd 100644 --- a/include/zephyr/sys/util_macro.h +++ b/include/zephyr/sys/util_macro.h @@ -635,6 +635,17 @@ extern "C" { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) +/** + * @brief Number of arguments in the variable arguments list. + * + * @note Supports up to 63 arguments. + * + * @param ... List of arguments + * @return Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS(...) \ + COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (UTIL_INC(NUM_VA_ARGS_LESS_1(__VA_ARGS__)))) + /** * @brief Mapping macro that pastes results together * diff --git a/tests/lib/sys_util/src/main.c b/tests/lib/sys_util/src/main.c index 9e1f7b5fa8c280..05f75ccc050069 100644 --- a/tests/lib/sys_util/src/main.c +++ b/tests/lib/sys_util/src/main.c @@ -37,6 +37,21 @@ ZTEST(sys_util, test_wait_for) end = k_cycle_get_32(); zassert_true(end-start >= expected, "wait for 1ms"); } + +/** + * @brief Test NUM_VA_ARGS works as expected with typical use cases + * + * @see NUM_VA_ARGS() + */ + +ZTEST(sys_util, test_NUM_VA_ARGS) +{ + zassert_equal(0, NUM_VA_ARGS()); + zassert_equal(1, NUM_VA_ARGS(_1)); + zassert_equal(2, NUM_VA_ARGS(_1, _2)); + /* support up to 63 args */ + zassert_equal(63, NUM_VA_ARGS(LISTIFY(63, ~, (,)))); +} /** * @} */ From f7e30c1ee9a70cb085c1cfb6d8d949e4c0c25389 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0022/1389] include: sys: util: add note and test for NUM_VA_ARGS_LESS_1 Notes that `NUM_VA_ARGS_LESS_1` support up to 64 arguments, and added test for it in `tests/lib/sys_util`. Signed-off-by: Yong Cong Sin --- include/zephyr/sys/util_macro.h | 2 ++ tests/lib/sys_util/src/main.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/zephyr/sys/util_macro.h b/include/zephyr/sys/util_macro.h index 24784f91e638fd..5b3864d2e3c63d 100644 --- a/include/zephyr/sys/util_macro.h +++ b/include/zephyr/sys/util_macro.h @@ -623,6 +623,8 @@ extern "C" { /** * @brief Number of arguments in the variable arguments list minus one. * + * @note Supports up to 64 arguments. + * * @param ... List of arguments * @return Number of variadic arguments in the argument list, minus one */ diff --git a/tests/lib/sys_util/src/main.c b/tests/lib/sys_util/src/main.c index 05f75ccc050069..02e6465e447860 100644 --- a/tests/lib/sys_util/src/main.c +++ b/tests/lib/sys_util/src/main.c @@ -52,6 +52,21 @@ ZTEST(sys_util, test_NUM_VA_ARGS) /* support up to 63 args */ zassert_equal(63, NUM_VA_ARGS(LISTIFY(63, ~, (,)))); } + +/** + * @brief Test NUM_VA_ARGS_LESS_1 works as expected with typical use cases + * + * @see NUM_VA_ARGS_LESS_1() + */ + +ZTEST(sys_util, test_NUM_VA_ARGS_LESS_1) +{ + zassert_equal(0, NUM_VA_ARGS_LESS_1()); + zassert_equal(0, NUM_VA_ARGS_LESS_1(_1)); + zassert_equal(1, NUM_VA_ARGS_LESS_1(_1, _2)); + /* support up to 64 args */ + zassert_equal(63, NUM_VA_ARGS_LESS_1(LISTIFY(64, ~, (,)))); +} /** * @} */ From bb3a8020c963ca3610d51a6fdf1ba7f23e487d83 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0023/1389] input: analog_axis: use k_sem for locking Swap the mutex with a semaphore for locking the calibration data. Lighter data structure, no need to use a mutex here. Signed-off-by: Fabio Baltieri --- drivers/input/input_analog_axis.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/input/input_analog_axis.c b/drivers/input/input_analog_axis.c index 832bd970fbafec..4217fdc765014f 100644 --- a/drivers/input/input_analog_axis.c +++ b/drivers/input/input_analog_axis.c @@ -38,7 +38,7 @@ struct analog_axis_config { }; struct analog_axis_data { - struct k_mutex cal_lock; + struct k_sem cal_lock; analog_axis_raw_data_t raw_data_cb; struct k_timer timer; struct k_thread thread; @@ -66,9 +66,9 @@ int analog_axis_calibration_get(const struct device *dev, return -EINVAL; } - k_mutex_lock(&data->cal_lock, K_FOREVER); + k_sem_take(&data->cal_lock, K_FOREVER); memcpy(out_cal, cal, sizeof(struct analog_axis_calibration)); - k_mutex_unlock(&data->cal_lock); + k_sem_give(&data->cal_lock); return 0; } @@ -77,9 +77,9 @@ void analog_axis_set_raw_data_cb(const struct device *dev, analog_axis_raw_data_ { struct analog_axis_data *data = dev->data; - k_mutex_lock(&data->cal_lock, K_FOREVER); + k_sem_take(&data->cal_lock, K_FOREVER); data->raw_data_cb = cb; - k_mutex_unlock(&data->cal_lock); + k_sem_give(&data->cal_lock); } int analog_axis_calibration_set(const struct device *dev, @@ -94,9 +94,9 @@ int analog_axis_calibration_set(const struct device *dev, return -EINVAL; } - k_mutex_lock(&data->cal_lock, K_FOREVER); + k_sem_take(&data->cal_lock, K_FOREVER); memcpy(cal, new_cal, sizeof(struct analog_axis_calibration)); - k_mutex_unlock(&data->cal_lock); + k_sem_give(&data->cal_lock); return 0; } @@ -171,7 +171,7 @@ static void analog_axis_loop(const struct device *dev) return; } - k_mutex_lock(&data->cal_lock, K_FOREVER); + k_sem_take(&data->cal_lock, K_FOREVER); for (i = 0; i < cfg->num_channels; i++) { const struct analog_axis_channel_config *axis_cfg = &cfg->channel_cfg[i]; @@ -203,7 +203,7 @@ static void analog_axis_loop(const struct device *dev) axis_data->last_out = out; } - k_mutex_unlock(&data->cal_lock); + k_sem_give(&data->cal_lock); } static void analog_axis_thread(void *arg1, void *arg2, void *arg3) @@ -244,7 +244,7 @@ static int analog_axis_init(const struct device *dev) struct analog_axis_data *data = dev->data; k_tid_t tid; - k_mutex_init(&data->cal_lock); + k_sem_init(&data->cal_lock, 1, 1); tid = k_thread_create(&data->thread, data->thread_stack, K_KERNEL_STACK_SIZEOF(data->thread_stack), From 676f67d9a2fb47e36fddfded8eb2e5182a85b5b0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0024/1389] subsys/settings: add a function to save subtree When running multiple subsystems or applications on a MCU, the usual strategy is to use different settings subtrees. The API provides a way to load or commit a subtree, to avoid adding dependencies between subsystems or applications, but lacks the way to save a subtree only. Fix that by adding a settings_save_subtree() function. Signed-off-by: Aurelien Jarno --- include/zephyr/settings/settings.h | 10 ++++++++++ subsys/settings/src/settings_store.c | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/zephyr/settings/settings.h b/include/zephyr/settings/settings.h index 0bae0658d43c83..99b9fc21077d83 100644 --- a/include/zephyr/settings/settings.h +++ b/include/zephyr/settings/settings.h @@ -303,6 +303,16 @@ int settings_load_subtree_direct( */ int settings_save(void); +/** + * Save limited set of currently running serialized items. All serialized items + * that belong to subtree and which are different from currently persisted + * values will be saved. + * + * @param[in] subtree name of the subtree to be loaded. + * @return 0 on success, non-zero on failure. + */ +int settings_save_subtree(const char *subtree); + /** * Write a single serialized value to persisted storage (if it has * changed value). diff --git a/subsys/settings/src/settings_store.c b/subsys/settings/src/settings_store.c index d47b24f064be00..b697f993d94161 100644 --- a/subsys/settings/src/settings_store.c +++ b/subsys/settings/src/settings_store.c @@ -116,6 +116,11 @@ int settings_delete(const char *name) } int settings_save(void) +{ + return settings_save_subtree(NULL); +} + +int settings_save_subtree(const char *subtree) { struct settings_store *cs; int rc; @@ -132,6 +137,9 @@ int settings_save(void) rc = 0; STRUCT_SECTION_FOREACH(settings_handler_static, ch) { + if (subtree && !settings_name_steq(ch->name, subtree, NULL)) { + continue; + } if (ch->h_export) { rc2 = ch->h_export(settings_save_one); if (!rc) { @@ -143,6 +151,9 @@ int settings_save(void) #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS) struct settings_handler *ch; SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) { + if (subtree && !settings_name_steq(ch->name, subtree, NULL)) { + continue; + } if (ch->h_export) { rc2 = ch->h_export(settings_save_one); if (!rc) { From 5c0a1f782fdb0f09c4f642a2254a1c61e461ab76 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0025/1389] lorawan/nvm: do not call settings_save() after writing individual settings The lorawan subsystem do not use settings handler, and instead uses individual calls to settings_save_one(). With this strategy there is no need to call settings_save() at the end. Signed-off-by: Aurelien Jarno --- subsys/lorawan/nvm/lorawan_nvm_settings.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/subsys/lorawan/nvm/lorawan_nvm_settings.c b/subsys/lorawan/nvm/lorawan_nvm_settings.c index 3b062299c5139f..b56784ad6272e6 100644 --- a/subsys/lorawan/nvm/lorawan_nvm_settings.c +++ b/subsys/lorawan/nvm/lorawan_nvm_settings.c @@ -77,8 +77,6 @@ static void lorawan_nvm_save_settings(uint16_t nvm_notify_flag) } } } - - settings_save(); } void lorawan_nvm_data_mgmt_event(uint16_t flags) From 61b912d9a7e1bee9397c29361a1f77a6d09140d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0026/1389] mgmt: hawkbit: reset action id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be able to reset the hawkBit action id. Signed-off-by: Fin Maaß --- include/zephyr/mgmt/hawkbit.h | 20 ++++++++++++++++++++ subsys/mgmt/hawkbit/hawkbit.c | 17 +++++++++++++++++ subsys/mgmt/hawkbit/shell.c | 14 ++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/include/zephyr/mgmt/hawkbit.h b/include/zephyr/mgmt/hawkbit.h index 5111cf8087fee9..3516650a920746 100644 --- a/include/zephyr/mgmt/hawkbit.h +++ b/include/zephyr/mgmt/hawkbit.h @@ -219,6 +219,26 @@ static inline char *hawkbit_get_ddi_security_token(void) return hawkbit_get_config().auth_token; } +/** + * @brief Get the hawkBit action id. + * + * @return Action id. + +*/ +int32_t hawkbit_get_action_id(void); + +/** + * @brief Resets the hawkBit action id, that is saved in settings. + * + * @details This should be done after changing the hawkBit server. + * + * @retval 0 on success. + * @retval -EAGAIN if probe is currently running. + * @retval -EIO if the action id could not be reset. + * + */ +int hawkbit_reset_action_id(void); + /** * @} */ diff --git a/subsys/mgmt/hawkbit/hawkbit.c b/subsys/mgmt/hawkbit/hawkbit.c index 5ecb0454fd41a5..f9da2ddd31a195 100644 --- a/subsys/mgmt/hawkbit/hawkbit.c +++ b/subsys/mgmt/hawkbit/hawkbit.c @@ -477,6 +477,23 @@ static int hawkbit_device_acid_update(int32_t new_value) return 0; } +int hawkbit_reset_action_id(void) +{ + int ret; + + if (k_sem_take(&probe_sem, K_NO_WAIT) == 0) { + ret = hawkbit_device_acid_update(0); + k_sem_give(&probe_sem); + return ret; + } + return -EAGAIN; +} + +int32_t hawkbit_get_action_id(void) +{ + return hb_cfg.action_id; +} + /* * Update sleep interval, based on results from hawkBit base polling * resource diff --git a/subsys/mgmt/hawkbit/shell.c b/subsys/mgmt/hawkbit/shell.c index d05c98e357ba02..7f1efbd36aff59 100644 --- a/subsys/mgmt/hawkbit/shell.c +++ b/subsys/mgmt/hawkbit/shell.c @@ -80,6 +80,7 @@ static int cmd_info(const struct shell *sh, size_t argc, char *argv) hawkbit_get_firmware_version(firmware_version, BOOT_IMG_VER_STRLEN_MAX); hawkbit_get_device_identity(device_id, DEVICE_ID_HEX_MAX_SIZE); + shell_print(sh, "Action id: %d", hawkbit_get_action_id()); shell_fprintf(sh, SHELL_NORMAL, "Unique device id: %s\n", device_id); shell_fprintf(sh, SHELL_NORMAL, "Firmware Version: %s\n", firmware_version); @@ -105,6 +106,18 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv) return 0; } +static int cmd_reset(const struct shell *sh, size_t argc, char *argv) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + int ret = hawkbit_reset_action_id(); + + shell_print(sh, "Reset action id %s", (ret == 0) ? "success" : "failed"); + + return 0; +} + #ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME static int cmd_set_addr(const struct shell *sh, size_t argc, char **argv) @@ -160,6 +173,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( SHELL_CMD(info, NULL, "Dump hawkBit information", cmd_info), SHELL_CMD(init, NULL, "Initialize hawkBit", cmd_init), SHELL_CMD(run, NULL, "Trigger an hawkBit update run", cmd_run), + SHELL_CMD(reset, NULL, "Reset the hawkBit action id", cmd_reset), #ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME SHELL_CMD(set, &sub_hawkbit_set, "Set hawkBit settings", NULL), #endif From 1596d4e5fcf4d712c4fb5180dc37a8729e23a689 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0027/1389] coding guidelines: comply with MISRA Rule 2.2 - avoided dead stores Signed-off-by: Hess Nathan --- kernel/mem_slab.c | 2 +- kernel/sched.c | 2 +- kernel/sem.c | 2 +- kernel/work.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/mem_slab.c b/kernel/mem_slab.c index 609063ef630d48..7b62c96facc369 100644 --- a/kernel/mem_slab.c +++ b/kernel/mem_slab.c @@ -172,7 +172,7 @@ SYS_INIT(init_mem_slab_obj_core_list, PRE_KERNEL_1, int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, size_t block_size, uint32_t num_blocks) { - int rc = 0; + int rc; slab->info.num_blocks = num_blocks; slab->info.block_size = block_size; diff --git a/kernel/sched.c b/kernel/sched.c index 866a51775582f8..390a7efe8c5f3d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1370,7 +1370,7 @@ void z_impl_k_thread_abort(struct k_thread *thread) int z_impl_k_thread_join(struct k_thread *thread, k_timeout_t timeout) { k_spinlock_key_t key = k_spin_lock(&_sched_spinlock); - int ret = 0; + int ret; SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, join, thread, timeout); diff --git a/kernel/sem.c b/kernel/sem.c index 819abd3879c010..c3c8055d0de9d3 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -131,7 +131,7 @@ static inline void z_vrfy_k_sem_give(struct k_sem *sem) int z_impl_k_sem_take(struct k_sem *sem, k_timeout_t timeout) { - int ret = 0; + int ret; __ASSERT(((arch_is_in_isr() == false) || K_TIMEOUT_EQ(timeout, K_NO_WAIT)), ""); diff --git a/kernel/work.c b/kernel/work.c index 1615c321f72264..994d6d74e8041b 100644 --- a/kernel/work.c +++ b/kernel/work.c @@ -271,7 +271,7 @@ static inline int queue_submit_locked(struct k_work_q *queue, return -EINVAL; } - int ret = -EBUSY; + int ret; bool chained = (_current == &queue->thread) && !k_is_in_isr(); bool draining = flag_test(&queue->flags, K_WORK_QUEUE_DRAIN_BIT); bool plugged = flag_test(&queue->flags, K_WORK_QUEUE_PLUGGED_BIT); @@ -1018,7 +1018,7 @@ int k_work_reschedule_for_queue(struct k_work_q *queue, SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, reschedule_for_queue, queue, dwork, delay); - int ret = 0; + int ret; k_spinlock_key_t key = k_spin_lock(&lock); /* Remove any active scheduling. */ From ad6fb2db96c6c5fb3ed9b454033ac199611b3eab Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0028/1389] mgmt: updatehub: Fix json arrays After the changes introduced by #50816 the UpdateHub could not decode anymore the JSON object. This introduce missing parsing definitions to allow JSON parser undertood the correct UpdateHub probe object. Fixes #69297 Signed-off-by: Gerson Fernando Budke --- subsys/mgmt/updatehub/updatehub.c | 44 ++++++++++++++++++++------ subsys/mgmt/updatehub/updatehub_priv.h | 24 ++++++++++---- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/subsys/mgmt/updatehub/updatehub.c b/subsys/mgmt/updatehub/updatehub.c index 886f10634bca68..1886b634a765e2 100644 --- a/subsys/mgmt/updatehub/updatehub.c +++ b/subsys/mgmt/updatehub/updatehub.c @@ -847,19 +847,31 @@ enum updatehub_response z_impl_updatehub_probe(void) recv_probe_sh_string_descr, ARRAY_SIZE(recv_probe_sh_string_descr), &metadata_any_boards) < 0) { - LOG_ERR("Could not parse json"); + LOG_ERR("Could not parse the json"); ctx.code_status = UPDATEHUB_METADATA_ERROR; goto cleanup; } + LOG_DBG("elements: %d", metadata_any_boards.objects_len); + for (size_t i = 0; i < metadata_any_boards.objects_len; ++i) { + LOG_DBG("obj[%d].elements: %d", + i, metadata_any_boards.objects[i].objects_len); + for (size_t j = 0; j < metadata_any_boards.objects[i].objects_len; ++j) { + struct resp_probe_objects *obj = + &metadata_any_boards.objects[i].objects[j].objects; + LOG_DBG("\tMode: %s\n\tSHA: %s\n\tSize: %d", + obj->mode, obj->sha256sum, obj->size); + } + } + if (metadata_any_boards.objects_len != 2) { - LOG_ERR("Could not parse json"); + LOG_ERR("Object length of type 'any metadata' is incorrect"); ctx.code_status = UPDATEHUB_METADATA_ERROR; goto cleanup; } sha256size = strlen( - metadata_any_boards.objects[1].objects.sha256sum) + 1; + metadata_any_boards.objects[1].objects[0].objects.sha256sum) + 1; if (sha256size != SHA256_HEX_DIGEST_SIZE) { LOG_ERR("SHA256 size is invalid"); @@ -868,14 +880,26 @@ enum updatehub_response z_impl_updatehub_probe(void) } memcpy(update_info.sha256sum_image, - metadata_any_boards.objects[1].objects.sha256sum, + metadata_any_boards.objects[1].objects[0].objects.sha256sum, SHA256_HEX_DIGEST_SIZE); - update_info.image_size = metadata_any_boards.objects[1].objects.size; + update_info.image_size = metadata_any_boards.objects[1].objects[0].objects.size; LOG_DBG("metadata_any: %s", update_info.sha256sum_image); } else { + LOG_DBG("elements: %d\n", metadata_some_boards.objects_len); + for (size_t i = 0; i < metadata_some_boards.objects_len; ++i) { + LOG_DBG("obj[%d].elements: %d\n", + i, metadata_some_boards.objects[i].objects_len); + for (size_t j = 0; j < metadata_some_boards.objects[i].objects_len; ++j) { + struct resp_probe_objects *obj = + &metadata_some_boards.objects[i].objects[j].objects; + LOG_DBG("\tMode: %s\n\tSHA: %s\n\tSize: %d\n", + obj->mode, obj->sha256sum, obj->size); + } + } + if (metadata_some_boards.objects_len != 2) { - LOG_ERR("Could not parse json"); + LOG_ERR("Object length of type 'some metadata' is incorrect"); ctx.code_status = UPDATEHUB_METADATA_ERROR; goto cleanup; } @@ -888,7 +912,7 @@ enum updatehub_response z_impl_updatehub_probe(void) } sha256size = strlen( - metadata_some_boards.objects[1].objects.sha256sum) + 1; + metadata_some_boards.objects[1].objects[0].objects.sha256sum) + 1; if (sha256size != SHA256_HEX_DIGEST_SIZE) { LOG_ERR("SHA256 size is invalid"); @@ -897,10 +921,10 @@ enum updatehub_response z_impl_updatehub_probe(void) } memcpy(update_info.sha256sum_image, - metadata_some_boards.objects[1].objects.sha256sum, + metadata_some_boards.objects[1].objects[0].objects.sha256sum, SHA256_HEX_DIGEST_SIZE); update_info.image_size = - metadata_some_boards.objects[1].objects.size; + metadata_some_boards.objects[1].objects[0].objects.size; LOG_DBG("metadata_some: %s", update_info.sha256sum_image); } @@ -942,7 +966,7 @@ enum updatehub_response z_impl_updatehub_update(void) if (updatehub_storage_mark_partition_to_upgrade(&ctx.storage_ctx, UPDATEHUB_SLOT_PARTITION_1)) { - LOG_ERR("Could not reporting downloaded state"); + LOG_ERR("Could not mark partition to upgrade"); ctx.code_status = UPDATEHUB_INSTALL_ERROR; goto error; } diff --git a/subsys/mgmt/updatehub/updatehub_priv.h b/subsys/mgmt/updatehub/updatehub_priv.h index ebfedcbb02a8d7..707e2db6c6dfb2 100644 --- a/subsys/mgmt/updatehub/updatehub_priv.h +++ b/subsys/mgmt/updatehub/updatehub_priv.h @@ -97,15 +97,20 @@ struct resp_probe_objects_array { struct resp_probe_objects objects; }; +struct resp_probe_objects_array_array { + struct resp_probe_objects_array objects[4]; + size_t objects_len; +}; + struct resp_probe_any_boards { - struct resp_probe_objects_array objects[2]; + struct resp_probe_objects_array_array objects[2]; size_t objects_len; const char *product; const char *supported_hardware; }; struct resp_probe_some_boards { - struct resp_probe_objects_array objects[2]; + struct resp_probe_objects_array_array objects[2]; size_t objects_len; const char *product; const char *supported_hardware[CONFIG_UPDATEHUB_SUPPORTED_HARDWARE_MAX]; @@ -148,6 +153,13 @@ static const struct json_obj_descr recv_probe_objects_descr_array[] = { objects, recv_probe_objects_descr), }; +static const struct json_obj_descr recv_probe_objects_descr_array_array[] = { + JSON_OBJ_DESCR_ARRAY_ARRAY(struct resp_probe_objects_array_array, + objects, 4, objects_len, + recv_probe_objects_descr_array, + ARRAY_SIZE(recv_probe_objects_descr_array)), +}; + static const struct json_obj_descr recv_probe_sh_string_descr[] = { JSON_OBJ_DESCR_PRIM(struct resp_probe_any_boards, product, JSON_TOK_STRING), @@ -156,8 +168,8 @@ static const struct json_obj_descr recv_probe_sh_string_descr[] = { JSON_TOK_STRING), JSON_OBJ_DESCR_ARRAY_ARRAY(struct resp_probe_any_boards, objects, 2, objects_len, - recv_probe_objects_descr_array, - ARRAY_SIZE(recv_probe_objects_descr_array)), + recv_probe_objects_descr_array_array, + ARRAY_SIZE(recv_probe_objects_descr_array_array)), }; static const struct json_obj_descr recv_probe_sh_array_descr[] = { @@ -169,8 +181,8 @@ static const struct json_obj_descr recv_probe_sh_array_descr[] = { supported_hardware_len, JSON_TOK_STRING), JSON_OBJ_DESCR_ARRAY_ARRAY(struct resp_probe_some_boards, objects, 2, objects_len, - recv_probe_objects_descr_array, - ARRAY_SIZE(recv_probe_objects_descr_array)), + recv_probe_objects_descr_array_array, + ARRAY_SIZE(recv_probe_objects_descr_array_array)), }; static const struct json_obj_descr device_identity_descr[] = { From 92d565d720c3d69cf21309505a4c5efdef6f5d56 Mon Sep 17 00:00:00 2001 From: Grant Ramsay Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0029/1389] doc: kernel: code-relocation: Remove kernel example and add tips The Kernel code relocation example does not work, as the kernel contains early initialization code that executes before code relocation takes place Signed-off-by: Grant Ramsay --- doc/kernel/code-relocation.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/kernel/code-relocation.rst b/doc/kernel/code-relocation.rst index 599cdedccbd745..73633c2f40eb2a 100644 --- a/doc/kernel/code-relocation.rst +++ b/doc/kernel/code-relocation.rst @@ -135,13 +135,21 @@ Relocating libraries Libraries can be relocated using the LIBRARY argument to ``zephyr_code_relocation()`` with the library name. For example, the following -snippet will relocate kernel code to ITCM and serial drivers to SRAM2: +snippet will relocate serial drivers to SRAM2: .. code-block:: none - zephyr_code_relocate(LIBRARY kernel LOCATION ITCM_TEXT) zephyr_code_relocate(LIBRARY drivers__serial LOCATION SRAM2) +Tips +==== + +Take care if relocating kernel/arch files, some contain early initialization +code that executes before code relocation takes place. + +Additional MPU/MMU configuration may be required to ensure that the +destination memory region is configured to allow code execution. + Samples/ Tests ============== From 9b61e177a4931bf35a3d79b0d2e0f04f004e2366 Mon Sep 17 00:00:00 2001 From: Yves Vandervennet Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0030/1389] west: linkserver: change to flash command line as required by v1.5.xx There is no need to specify the core with the flash command line. This is actually rejected with linkserver v1.5.xx and after. Signed-off-by: Yves Vandervennet --- scripts/west_commands/runners/linkserver.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scripts/west_commands/runners/linkserver.py b/scripts/west_commands/runners/linkserver.py index b87c594c4ae7e0..51241add14d5fd 100644 --- a/scripts/west_commands/runners/linkserver.py +++ b/scripts/west_commands/runners/linkserver.py @@ -186,12 +186,7 @@ def _build_override_cli(self): def flash(self, **kwargs): - if self.core is not None: - _cmd_core = ":"+self.core - else: - _cmd_core = "" - - linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", str(self.probe)] + self.override_cli + [self.device+_cmd_core]) + linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", str(self.probe)] + self.override_cli + [self.device]) self.logger.debug(f'LinkServer cmd: + {linkserver_cmd}') if self.erase: From 2847e50088db0717663b37aa960bf3973c2502a2 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Sun, 26 May 2024 22:38:23 +0200 Subject: [PATCH 0031/1389] scripts: runner: linkserver: Add flash support for Intel Hex files Enables flash support for Intel Hex files, added with LinkServer v1.5.30. Signed-off-by: Andrej Butok --- scripts/west_commands/runners/linkserver.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/scripts/west_commands/runners/linkserver.py b/scripts/west_commands/runners/linkserver.py index 51241add14d5fd..1d62840c2e207d 100644 --- a/scripts/west_commands/runners/linkserver.py +++ b/scripts/west_commands/runners/linkserver.py @@ -1,4 +1,4 @@ -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # Copyright (c) 2017 Linaro Limited. # # SPDX-License-Identifier: Apache-2.0 @@ -192,7 +192,10 @@ def flash(self, **kwargs): if self.erase: self.do_erase() - if self.bin_name is not None and os.path.isfile(self.bin_name): + # Use .hex or .bin, preferring .hex over .bin + if self.supports_hex and self.hex_name is not None and os.path.isfile(self.hex_name): + flash_cmd = (["load", self.hex_name]) + elif self.bin_name is not None and os.path.isfile(self.bin_name): if self.dt_flash: load_addr = self.flash_address_from_build_conf(self.build_conf) else: @@ -201,10 +204,10 @@ def flash(self, **kwargs): flash_cmd = (["load", "--addr", str(load_addr), self.bin_name]) else: - err = 'Cannot flash; no bin ({}) file found.' - raise ValueError(err.format(self.bin_name)) + err = 'Cannot flash; no hex ({}) or bin ({}) file found.' + raise ValueError(err.format(self.hex_name, self.bin_name)) - # Flash the selected elf file + # Flash the selected file linkserver_cmd = linkserver_cmd + flash_cmd self.logger.debug("flash command = " + str(linkserver_cmd)) kwargs = {} @@ -215,3 +218,7 @@ def flash(self, **kwargs): kwargs['stdout'] = subprocess.DEVNULL self.check_call(linkserver_cmd, **kwargs) + + def supports_hex(self): + # v1.5.30 has added flash support for Intel Hex files. + return self.linkserver_version_str >= "v1.5.30" From 1652eeda09fc69d9eea2ee480a047b4011d25ca3 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0032/1389] drivers: adc: support Nuvoton numaker m2l31x Update m2l31x.dtsi for adc support and update adc_numaker.c to support acquisition time in 0~255 ADC ticks. Signed-off-by: cyliang tw --- drivers/adc/adc_numaker.c | 40 +++++++++++++++++++++++-------------- dts/arm/nuvoton/m2l31x.dtsi | 14 +++++++++++++ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/drivers/adc/adc_numaker.c b/drivers/adc/adc_numaker.c index 4fae17f422d479..42d3b7ad5ddbf6 100644 --- a/drivers/adc/adc_numaker.c +++ b/drivers/adc/adc_numaker.c @@ -17,6 +17,7 @@ #include #define ADC_CONTEXT_USES_KERNEL_TIMER +#define ADC_CONTEXT_ENABLE_ON_COMPLETE #include "adc_context.h" LOG_MODULE_REGISTER(adc_numaker, CONFIG_ADC_LOG_LEVEL); @@ -45,6 +46,7 @@ struct adc_numaker_data { uint16_t *repeat_buffer; bool is_differential; uint32_t channels; + uint32_t acq_time; }; static int adc_numaker_channel_setup(const struct device *dev, @@ -54,9 +56,13 @@ static int adc_numaker_channel_setup(const struct device *dev, struct adc_numaker_data *data = dev->data; if (chan_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) { - LOG_ERR("Not support acquisition time"); - return -ENOTSUP; + if ((ADC_ACQ_TIME_UNIT(chan_cfg->acquisition_time) != ADC_ACQ_TIME_TICKS) || + (ADC_ACQ_TIME_VALUE(chan_cfg->acquisition_time) > 255)) { + LOG_ERR("Selected ADC acquisition time is not in 0~255 ticks"); + return -EINVAL; + } } + data->acq_time = ADC_ACQ_TIME_VALUE(chan_cfg->acquisition_time); if (chan_cfg->gain != ADC_GAIN_1) { LOG_ERR("Not support channel gain"); @@ -115,9 +121,6 @@ static void adc_numaker_isr(const struct device *dev) uint16_t conv_data; uint32_t pend_flag; - /* Clear pending flag first */ - pend_flag = eadc->PENDSTS; - eadc->PENDSTS = pend_flag; LOG_DBG("ADC ISR pend flag: 0x%X\n", pend_flag); LOG_DBG("ADC ISR STATUS2[0x%x] STATUS3[0x%x]", eadc->STATUS2, eadc->STATUS3); /* Complete the conversion of channels. @@ -151,9 +154,6 @@ static void adc_numaker_isr(const struct device *dev) eadc->SCTL[module_id] = 0; } - /* Disable ADC */ - EADC_Close(eadc); - /* Inform sampling is done */ adc_context_on_sampling_done(&data->ctx, data->dev); } @@ -179,6 +179,8 @@ static void m_adc_numaker_start_scan(const struct device *dev) channel_mask &= ~BIT(channel_id); EADC_ConfigSampleModule(eadc, module_id, EADC_SOFTWARE_TRIGGER, channel_id); + /* Set sample module external sampling time to 0 */ + EADC_SetExtendSampleTime(eadc, module_id, data->acq_time); } /* Clear the A/D ADINT0 interrupt flag for safe */ @@ -221,6 +223,19 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, } } +static void adc_context_on_complete(struct adc_context *ctx, int status) +{ + struct adc_numaker_data *data = + CONTAINER_OF(ctx, struct adc_numaker_data, ctx); + const struct adc_numaker_config *cfg = data->dev->config; + EADC_T *eadc = cfg->eadc_base; + + ARG_UNUSED(status); + + /* Disable ADC */ + EADC_Close(eadc); +} + static int m_adc_numaker_start_read(const struct device *dev, const struct adc_sequence *sequence) { @@ -243,14 +258,9 @@ static int m_adc_numaker_start_read(const struct device *dev, /* Enable the A/D converter */ if (data->is_differential) { - err = EADC_Open(eadc, EADC_CTL_DIFFEN_DIFFERENTIAL); + EADC_Open(eadc, EADC_CTL_DIFFEN_DIFFERENTIAL); } else { - err = EADC_Open(eadc, EADC_CTL_DIFFEN_SINGLE_END); - } - - if (err) { - LOG_ERR("ADC Open fail (%u)", err); - return -ENODEV; + EADC_Open(eadc, EADC_CTL_DIFFEN_SINGLE_END); } data->buffer = sequence->buffer; diff --git a/dts/arm/nuvoton/m2l31x.dtsi b/dts/arm/nuvoton/m2l31x.dtsi index 2edad5732b7801..1ebbd9118a0740 100644 --- a/dts/arm/nuvoton/m2l31x.dtsi +++ b/dts/arm/nuvoton/m2l31x.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { chosen { @@ -306,6 +307,19 @@ #address-cells = <1>; #size-cells = <0>; }; + + eadc0: eadc@40043000 { + compatible = "nuvoton,numaker-adc"; + reg = <0x40043000 0xffc>; + interrupts = <42 0>; + resets = <&rst NUMAKER_EADC0_RST>; + clocks = <&pcc NUMAKER_EADC0_MODULE + NUMAKER_CLK_CLKSEL0_EADC0SEL_HCLK + NUMAKER_CLK_CLKDIV0_EADC0(2)>; + channels = <31>; + status = "disabled"; + #io-channel-cells = <1>; + }; }; }; From 0d9667a044a133b92ef61f7ba49105617192f6eb Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0033/1389] tests: drivers: adc_api: support numaker_m2l31ki Add support for Nuvoton numaker board numaker_m2l31ki. Signed-off-by: cyliang tw --- .../adc/adc_api/boards/numaker_m2l31ki.conf | 1 + .../adc_api/boards/numaker_m2l31ki.overlay | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/drivers/adc/adc_api/boards/numaker_m2l31ki.conf create mode 100644 tests/drivers/adc/adc_api/boards/numaker_m2l31ki.overlay diff --git a/tests/drivers/adc/adc_api/boards/numaker_m2l31ki.conf b/tests/drivers/adc/adc_api/boards/numaker_m2l31ki.conf new file mode 100644 index 00000000000000..9fb2581d7f4a24 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/numaker_m2l31ki.conf @@ -0,0 +1 @@ +CONFIG_TEST_USERSPACE=n diff --git a/tests/drivers/adc/adc_api/boards/numaker_m2l31ki.overlay b/tests/drivers/adc/adc_api/boards/numaker_m2l31ki.overlay new file mode 100644 index 00000000000000..1fb978f147eb4e --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/numaker_m2l31ki.overlay @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + zephyr,user { + io-channels = <&eadc0 5>, <&eadc0 7>; + }; +}; + +&pinctrl { + /* EVB's UNO Pin A2 & A0 for channel 5 & 7 --> PB5, PB7 */ + eadc0_default: eadc0_default { + group0 { + pinmux = , ; + }; + }; +}; + +&eadc0 { + status = "okay"; + pinctrl-0 = <&eadc0_default>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + channel@5 { + reg = <5>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <10>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <10>; + }; +}; From 9bbf00b7caa5e2b0c70a399803ec7670509a4410 Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0034/1389] west.yaml: update hal_espressif after SDHC porting Update revision reference for PR #71165 as needed. Signed-off-by: Sylvio Alves --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 30e2269aae4b15..12da756463efc6 100644 --- a/west.yml +++ b/west.yml @@ -152,7 +152,7 @@ manifest: groups: - hal - name: hal_espressif - revision: e554857b07d54e2152c6f1a9b39da6d6c13fe7f7 + revision: c49581173bab8625d1f08d5c41d5a186afc240b3 path: modules/hal/espressif west-commands: west/west-commands.yml groups: From 9c5ffcffab64dfe0eb72f6c2e260616bf12a0109 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0035/1389] boards: arduino: uno_r4: Add Arduino connector for Minima and WiFi Add Arduino connector definitions for Minima and WiFi Signed-off-by: TOKITA Hiroshi --- .../arduino/uno_r4/arduino_uno_r4_minima.dts | 29 +++++++++++++++++++ boards/arduino/uno_r4/arduino_uno_r4_wifi.dts | 29 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/boards/arduino/uno_r4/arduino_uno_r4_minima.dts b/boards/arduino/uno_r4/arduino_uno_r4_minima.dts index 6984b6c5354ff5..d80ca6d4f1fcd9 100644 --- a/boards/arduino/uno_r4/arduino_uno_r4_minima.dts +++ b/boards/arduino/uno_r4/arduino_uno_r4_minima.dts @@ -21,4 +21,33 @@ aliases { led0 = &led; }; + + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &ioport0 14 0>, /* A0 */ + <1 0 &ioport0 0 0>, /* A1 */ + <2 0 &ioport0 1 0>, /* A2 */ + <3 0 &ioport0 2 0>, /* A3 */ + <4 0 &ioport1 1 0>, /* A4 */ + <5 0 &ioport1 0 0>, /* A5 */ + <6 0 &ioport3 1 0>, /* D0 */ + <7 0 &ioport3 2 0>, /* D1 */ + <8 0 &ioport1 5 0>, /* D2 */ + <9 0 &ioport1 4 0>, /* D3 */ + <10 0 &ioport1 3 0>, /* D4 */ + <11 0 &ioport1 2 0>, /* D5 */ + <12 0 &ioport1 6 0>, /* D6 */ + <13 0 &ioport1 7 0>, /* D7 */ + <14 0 &ioport3 4 0>, /* D8 */ + <15 0 &ioport3 3 0>, /* D9 */ + <16 0 &ioport1 12 0>, /* D10 */ + <17 0 &ioport1 9 0>, /* D11 */ + <18 0 &ioport1 10 0>, /* D12 */ + <19 0 &ioport1 11 0>, /* D13 */ + <20 0 &ioport1 1 0>, /* D14 */ + <21 0 &ioport1 0 0>; /* D15 */ + }; }; diff --git a/boards/arduino/uno_r4/arduino_uno_r4_wifi.dts b/boards/arduino/uno_r4/arduino_uno_r4_wifi.dts index 2cba24cdf16f33..a3a2019990ebcc 100644 --- a/boards/arduino/uno_r4/arduino_uno_r4_wifi.dts +++ b/boards/arduino/uno_r4/arduino_uno_r4_wifi.dts @@ -21,4 +21,33 @@ aliases { led0 = &led; }; + + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &ioport0 14 0>, /* A0 */ + <1 0 &ioport0 0 0>, /* A1 */ + <2 0 &ioport0 1 0>, /* A2 */ + <3 0 &ioport0 2 0>, /* A3 */ + <4 0 &ioport1 1 0>, /* A4 */ + <5 0 &ioport1 0 0>, /* A5 */ + <6 0 &ioport3 1 0>, /* D0 */ + <7 0 &ioport3 2 0>, /* D1 */ + <8 0 &ioport1 4 0>, /* D2 */ + <9 0 &ioport1 5 0>, /* D3 */ + <10 0 &ioport1 6 0>, /* D4 */ + <11 0 &ioport1 7 0>, /* D5 */ + <12 0 &ioport1 11 0>, /* D6 */ + <13 0 &ioport1 12 0>, /* D7 */ + <14 0 &ioport3 4 0>, /* D8 */ + <15 0 &ioport3 3 0>, /* D9 */ + <16 0 &ioport1 3 0>, /* D10 */ + <17 0 &ioport4 11 0>, /* D11 */ + <18 0 &ioport4 10 0>, /* D12 */ + <19 0 &ioport1 2 0>, /* D13 */ + <20 0 &ioport1 1 0>, /* D14 */ + <21 0 &ioport1 0 0>; /* D15 */ + }; }; From 946f8315b6d390ad01f39f988b87e6628dbf68ff Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0036/1389] tests: bsim: Bluetooth: Fix sim_length for central_hr_peripheral_hr Fix sim_length value for central_hr_peripheral_hr so that the simulation does not end while the test is still in progress. Signed-off-by: Vinayak Kariappa Chettimada --- .../tests_scripts/central_hr_peripheral_hr.sh | 5 ++--- .../tests_scripts/central_hr_peripheral_hr_extended.sh | 5 ++--- .../tests_scripts/central_hr_peripheral_hr_phy_coded.sh | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr.sh b/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr.sh index 29cec0cc114222..301a8834b7e33c 100755 --- a/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr.sh +++ b/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr.sh @@ -4,11 +4,10 @@ simulation_id="central_hr_peripheral_hr_test" verbosity_level=2 +EXECUTE_TIMEOUT=60 source ${ZEPHYR_BASE}/tests/bsim/sh_common.source -EXECUTE_TIMEOUT=10 - cd ${BSIM_OUT_PATH}/bin Execute ./bs_${BOARD_TS}_samples_bluetooth_peripheral_hr_prj_conf \ @@ -19,6 +18,6 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_samples_central_hr_peripheral_hr_p -testid=central_hr_peripheral_hr Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ - -D=2 -sim_length=10e6 $@ + -D=2 -sim_length=12e6 $@ wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails diff --git a/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_extended.sh b/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_extended.sh index ad6d4cede4c7c6..b2083ca1f06725 100755 --- a/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_extended.sh +++ b/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_extended.sh @@ -7,8 +7,7 @@ source ${ZEPHYR_BASE}/tests/bsim/sh_common.source simulation_id="central_hr_peripheral_hr_extended_test" test_long_name="$(guess_test_long_name)" verbosity_level=2 - -EXECUTE_TIMEOUT=10 +EXECUTE_TIMEOUT=60 cd ${BSIM_OUT_PATH}/bin @@ -20,6 +19,6 @@ Execute ./bs_${BOARD_TS}_${test_long_name}_prj_conf_overlay-extended_conf \ -testid=central_hr_peripheral_hr Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ - -D=2 -sim_length=10e6 $@ + -D=2 -sim_length=12e6 $@ wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails diff --git a/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_phy_coded.sh b/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_phy_coded.sh index 633ca41f538ae1..7232fe454a9b8f 100755 --- a/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_phy_coded.sh +++ b/tests/bsim/bluetooth/samples/central_hr_peripheral_hr/tests_scripts/central_hr_peripheral_hr_phy_coded.sh @@ -7,8 +7,7 @@ source ${ZEPHYR_BASE}/tests/bsim/sh_common.source simulation_id="central_hr_peripheral_hr_phy_coded_test" test_long_name="$(guess_test_long_name)" verbosity_level=2 - -EXECUTE_TIMEOUT=10 +EXECUTE_TIMEOUT=60 cd ${BSIM_OUT_PATH}/bin @@ -20,6 +19,6 @@ Execute ./bs_${BOARD_TS}_${test_long_name}_prj_conf_overlay-phy_coded_conf \ -testid=central_hr_peripheral_hr Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ - -D=2 -sim_length=10e6 $@ + -D=2 -sim_length=12e6 $@ wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails From 623532f0d5e0ce92b196221bcb8a1739816df84b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0037/1389] Bluetooth: Controller: Fix BT_CTLR_EARLY_ABORT_PREVIOUS_PREPARE Fix BT_CTLR_EARLY_ABORT_PREVIOUS_PREPARE to setup new shorter preempt timeout irrespective of whether there is a previous prepare enqueued in the prepare pipeline. Relates to commit d573951f0daf ("Bluetooth: Controller: Revert back early abort of previous prepare"). Signed-off-by: Vinayak Kariappa Chettimada --- .../controller/ll_sw/nordic/lll/lll.c | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index ed459c20d199eb..d8eb94a08b6847 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -945,13 +945,6 @@ static uint32_t preempt_ticker_start(struct lll_event *first, (preempt_req != preempt_ack)) { uint32_t diff; - /* preempt timeout already started but no role/state in the head - * of prepare pipeline. - */ - if (!prev || prev->is_aborted) { - return TICKER_STATUS_SUCCESS; - } - /* Calc the preempt timeout */ p = &next->prepare_param; ull = HDR_LLL2ULL(p->param); @@ -985,14 +978,20 @@ static uint32_t preempt_ticker_start(struct lll_event *first, * A proper solution will be to re-design the pipeline * as a ordered list, instead of the current FIFO. */ - /* Set early as we get called again through the call to - * abort_cb(). + /* preempt timeout already started but no role/state in the head + * of prepare pipeline. */ - ticks_at_preempt = ticks_at_preempt_new; - - /* Abort previous prepare that set the preempt timeout */ - prev->is_aborted = 1U; - prev->abort_cb(&prev->prepare_param, prev->prepare_param.param); + if (prev && !prev->is_aborted) { + /* Set early as we get called again through the call to + * abort_cb(). + */ + ticks_at_preempt = ticks_at_preempt_new; + + /* Abort previous prepare that set the preempt timeout */ + prev->is_aborted = 1U; + prev->abort_cb(&prev->prepare_param, + prev->prepare_param.param); + } #endif /* CONFIG_BT_CTLR_EARLY_ABORT_PREVIOUS_PREPARE */ /* Schedule short preempt timeout */ From e087c81b1a9f0f3b261fb4950f0f2db21e7bbce3 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0038/1389] Bluetooth: Controller: Add assertion check for use of scan aux context Add assertion check for use of scan aux context so that scan aux context is not assigned again while there is already an existing LLL scheduling in use by the scan context. Signed-off-by: Vinayak Kariappa Chettimada --- .../bluetooth/controller/ll_sw/ull_scan_aux.c | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 67c9af4778e2be..409c9f1cb0bd54 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -621,16 +621,32 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * with a valid context. */ if (ftr->aux_lll_sched) { - /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being setup */ - ftr->aux_sched = 1U; - if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) && sync_lll) { sync_lll->lll_aux = lll_aux; + /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being + * setup + */ + ftr->aux_sched = 1U; + /* In sync context, dispatch immediately */ ll_rx_put_sched(link, rx); } else { + /* check scan context is not already using LLL + * scheduling, or receiving a chain then it will + * reuse the aux context. + */ + LL_ASSERT(!lll->lll_aux || (lll->lll_aux == lll_aux)); + + /* scan context get the aux context so that it can + * continue reception in LLL scheduling. + */ lll->lll_aux = lll_aux; + + /* AUX_ADV_IND/AUX_CHAIN_IND PDU reception is being + * setup + */ + ftr->aux_sched = 1U; } /* Reset auxiliary channel PDU scan state which otherwise is From 4faa44aac5289823e7fc25681bc1a0724bb7d85d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0039/1389] Bluetooth: Controller: Add prepare pipeline assertion checks Add prepare pipeline assertion checks to detect faults like stopping preempt timeout without prior start. Also, check if the preemptor param is correct when preemption is performed. Check that the prepare pipeline is not infinitely looping. Signed-off-by: Vinayak Kariappa Chettimada --- .../controller/ll_sw/nordic/lll/lll.c | 14 +++++++- subsys/bluetooth/controller/ll_sw/ull.c | 33 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index d8eb94a08b6847..92ea7b66ebfc72 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -898,11 +898,21 @@ static uint8_t volatile preempt_ack; static void ticker_stop_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - ARG_UNUSED(status); LL_ASSERT(preempt_stop_req != preempt_stop_ack); preempt_stop_ack = preempt_stop_req; + /* We do not fail on status not being success because under scenarios + * where there is ticker_start then ticker_stop and then ticker_start, + * the call to ticker_stop will fail and this is acceptable. + * Also, the preempt_req and preempt_ack would not be update as the + * ticker_start was not processed before ticker_stop. Hence, it is + * safe to reset preempt_req and preempt_ack here. + */ + if (status == TICKER_STATUS_SUCCESS) { + LL_ASSERT(preempt_req != preempt_ack); + } + preempt_req = preempt_ack; } @@ -1135,6 +1145,8 @@ static void preempt(void *param) /* No ready prepare */ return; } + + LL_ASSERT(ready->prepare_param.param == param); } /* Check if current event want to continue */ diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 17d9ddd2b82f42..f4133b9af8de15 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -2072,6 +2072,34 @@ void ull_prepare_dequeue(uint8_t caller_id) void *param_resume_head = NULL; void *param_resume_next = NULL; struct lll_event *next; + uint8_t loop; + + /* Development assertion check to ensure the below loop processing + * has a limit. + * + * Only 2 scanner and 1 advertiser (directed adv) gets enqueue back: + * + * Already in queue max 7 (EVENT_PIPELINE_MAX): + * - 2 continuous scan prepare in queue (1M and Coded PHY) + * - 2 continuous scan resume in queue (1M and Coded PHY) + * - 1 directed adv prepare + * - 1 directed adv resume + * - 1 any other role with time reservation + * + * The loop removes the duplicates (scan and advertiser) with is_aborted + * flag set in 7 iterations: + * - 1 scan prepare (1M) + * - 1 scan prepare (Coded PHY) + * - 1 directed adv prepare + * + * and has enqueue the following in these 7 iterations: + * - 1 scan resume (1M) + * - 1 scan resume (Coded PHY) + * - 1 directed adv resume + * + * Hence, it should be (EVENT_PIPELINE_MAX + 3U) iterations max. + */ + loop = (EVENT_PIPELINE_MAX + 3U); next = ull_prepare_dequeue_get(); while (next) { @@ -2079,6 +2107,11 @@ void ull_prepare_dequeue(uint8_t caller_id) uint8_t is_aborted = next->is_aborted; uint8_t is_resume = next->is_resume; + /* Assert if we exceed iterations processing the prepare queue + */ + LL_ASSERT(loop); + loop--; + /* Let LLL invoke the `prepare` interface if radio not in active * use. Otherwise, enqueue at end of the prepare pipeline queue. */ From e2313ddfb224731fc9728242a12b78e844f593d1 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0040/1389] Bluetooth: Controller: Fix short prepare preempt timeout start Fix short prepare preempt timeout start, such that if there are any normal prepare before a short prepare in the pipeline, then find the short prepare and start its preempt timeout. Signed-off-by: Vinayak Kariappa Chettimada --- .../controller/ll_sw/nordic/lll/lll.c | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 92ea7b66ebfc72..6aec56a0ab4a64 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -719,6 +719,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, struct lll_prepare_param *prepare_param, uint8_t is_resume, uint8_t is_dequeue) { + struct lll_event *ready_short = NULL; struct lll_event *ready; struct lll_event *next; uint8_t idx; @@ -728,9 +729,35 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, idx = UINT8_MAX; ready = prepare_dequeue_iter_ready_get(&idx); + /* Find any short prepare */ + if (ready) { + uint32_t ticks_at_preempt_min = ready->prepare_param.ticks_at_expire; + + do { + uint32_t ticks_at_preempt_next; + struct lll_event *ready_next; + uint32_t diff; + + ready_next = prepare_dequeue_iter_ready_get(&idx); + if (!ready_next) { + break; + } + + ticks_at_preempt_next = ready_next->prepare_param.ticks_at_expire; + diff = ticker_ticks_diff_get(ticks_at_preempt_next, + ticks_at_preempt_min); + if ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U) { + continue; + } + + ready_short = ready_next; + ticks_at_preempt_min = ticks_at_preempt_next; + } while (true); + } + /* Current event active or another prepare is ready in the pipeline */ if ((!is_dequeue && !is_done_sync()) || - event.curr.abort_cb || + event.curr.abort_cb || ready_short || (ready && is_resume)) { #if defined(CONFIG_BT_CTLR_LOW_LAT) lll_prepare_cb_t resume_cb; @@ -751,6 +778,11 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, return -EINPROGRESS; } + /* Find any short prepare */ + if (ready_short) { + ready = ready_short; + } + /* Always start preempt timeout for first prepare in pipeline */ struct lll_event *first = ready ? ready : next; uint32_t ret; From 44b3f0888b52b4668bb768f4738d28155942317b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0041/1389] Bluetooth: Controller: Enable ticker slot window yield for mesh Enable use of ticker slow window yield feature under mesh usecase. This is make sure scan window either slides within is window or skips to next interval so that it does not lead to advertising event being skipped. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/Kconfig.ll_sw_split | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index c6fd9794c6ea4a..9613dc8ebb262f 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -1091,7 +1091,7 @@ config BT_TICKER_EXT config BT_TICKER_EXT_SLOT_WINDOW_YIELD bool "Tickers with slot window always yields" depends on BT_TICKER_EXT - default y if BT_CTLR_ADV_ISO + default y if BT_MESH || BT_CTLR_ADV_ISO help This options forces tickers with slot window extensions to yield to normal tickers and be placed at the end of their slot window. From b502e68e03c1130229622f9d463c412fe2ff3bd7 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0042/1389] Bluetooth: Controller: Use reschedule margin as minimum ticks_slot Use reschedule margin as minimum ticks_slot when ticker with reschedule expires. This will ensure not too many unreserved tickers expire in close proximity that can lead of pile up of CPU processing time and eventually causing timeout callbacks to be delayed. This mitigate possible LL asserts due to overhead in start of radio events. Signed-off-by: Vinayak Kariappa Chettimada --- .../controller/ll_sw/nordic/hal/nrf5/ticker.h | 3 +- subsys/bluetooth/controller/ticker/ticker.c | 41 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h index 10d780a559cb50..1a5c1a3f8a797a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h @@ -68,8 +68,9 @@ HAL_TICKER_TICKS_TO_US(HAL_TICKER_PSEC_PER_USEC) /* Macro defining the margin for positioning re-scheduled nodes */ +#define HAL_TICKER_RESCHEDULE_MARGIN_US 150U #define HAL_TICKER_RESCHEDULE_MARGIN \ - HAL_TICKER_US_TO_TICKS(150) + HAL_TICKER_US_TO_TICKS(HAL_TICKER_RESCHEDULE_MARGIN_US) /* Remove ticks and return positive remainder value in microseconds */ static inline void hal_ticker_remove_jitter(uint32_t *ticks, diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index 639cd0ed57dc1f..efeeff1bae7bdc 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -840,6 +840,7 @@ static uint8_t ticker_resolve_collision(struct ticker_node *nodes, while (id_head != TICKER_NULL) { struct ticker_node *ticker_next = &nodes[id_head]; + uint32_t ticker_next_ticks_slot; /* Accumulate ticks_to_expire for each node */ acc_ticks_to_expire += ticker_next->ticks_to_expire; @@ -847,8 +848,17 @@ static uint8_t ticker_resolve_collision(struct ticker_node *nodes, break; } + if (TICKER_HAS_SLOT_WINDOW(ticker_next) && + (ticker_next->ticks_slot == 0U)) { + ticker_next_ticks_slot = + HAL_TICKER_RESCHEDULE_MARGIN; + } else { + ticker_next_ticks_slot = + ticker_next->ticks_slot; + } + /* We only care about nodes with slot reservation */ - if (ticker_next->ticks_slot == 0U) { + if (ticker_next_ticks_slot == 0U) { id_head = ticker_next->next; continue; } @@ -977,7 +987,8 @@ static uint8_t ticker_resolve_collision(struct ticker_node *nodes, /* Check if next node is within this reservation slot * and wins conflict resolution */ - if (curr_has_ticks_slot_window || + if ((curr_has_ticks_slot_window && + next_not_ticks_slot_window) || (!lazy_next_periodic_skip && (next_is_critical || next_force || @@ -1295,11 +1306,19 @@ void ticker_worker(void *param) #if !defined(CONFIG_BT_TICKER_LOW_LAT) && \ !defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC) + uint32_t ticker_ticks_slot; + + if (TICKER_HAS_SLOT_WINDOW(ticker) && + (ticker->ticks_slot == 0U)) { + ticker_ticks_slot = HAL_TICKER_RESCHEDULE_MARGIN; + } else { + ticker_ticks_slot = ticker->ticks_slot; + } + /* Check if node has slot reservation and resolve any collision * with other ticker nodes */ - if (((ticker->ticks_slot != 0U) || - TICKER_HAS_SLOT_WINDOW(ticker)) && + if ((ticker_ticks_slot != 0U) && (slot_reserved || (instance->ticks_slot_previous > ticks_expired) || ticker_resolve_collision(node, ticker))) { @@ -1431,7 +1450,7 @@ void ticker_worker(void *param) #if !defined(CONFIG_BT_TICKER_LOW_LAT) && \ !defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC) - if (ticker->ticks_slot != 0U) { + if (ticker_ticks_slot != 0U) { /* Any further nodes will be skipped */ slot_reserved = 1U; } @@ -2061,13 +2080,21 @@ static inline void ticker_job_worker_bh(struct ticker_instance *instance, instance->ticks_slot_previous = 0U; } + uint32_t ticker_ticks_slot; + + if (TICKER_HAS_SLOT_WINDOW(ticker) && !ticker->ticks_slot) { + ticker_ticks_slot = HAL_TICKER_RESCHEDULE_MARGIN; + } else { + ticker_ticks_slot = ticker->ticks_slot; + } + /* If a reschedule is set pending, we will need to keep * the slot_previous information */ - if (ticker->ticks_slot && (state == 2U) && !skip_collision && + if (ticker_ticks_slot && (state == 2U) && !skip_collision && !TICKER_RESCHEDULE_PENDING(ticker)) { instance->ticker_id_slot_previous = id_expired; - instance->ticks_slot_previous = ticker->ticks_slot; + instance->ticks_slot_previous = ticker_ticks_slot; } #endif /* CONFIG_BT_TICKER_SLOT_AGNOSTIC */ From e5f3d937c7c6ce0a2a586021303b5d7fc6f5af95 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:24 +0200 Subject: [PATCH 0043/1389] kernel: coding guidelines: add explicit cast to void - added explicit cast to void when returned value is expectedly ignored Signed-off-by: frei tycho --- kernel/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/smp.c b/kernel/smp.c index 6e6cad2688fab5..346432707d40fd 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -74,7 +74,7 @@ void z_smp_global_unlock(unsigned int key) _current->base.global_lock_count--; if (!_current->base.global_lock_count) { - atomic_clear(&global_lock); + (void)atomic_clear(&global_lock); } } @@ -85,7 +85,7 @@ void z_smp_global_unlock(unsigned int key) void z_smp_release_global_lock(struct k_thread *thread) { if (!thread->base.global_lock_count) { - atomic_clear(&global_lock); + (void)atomic_clear(&global_lock); } } From 0304bab6a002aa8732f575c1ec388ef3469cd304 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0044/1389] docs: Bluetooth: Audio: Move audio related files to subdir Add a new subdir, audio, and move all the audio related documentation files to that directory, similar to mesh. Signed-off-by: Emil Gydesen --- MAINTAINERS.yml | 6 +--- doc/_scripts/redirects.py | 18 ++++++++++ .../bluetooth/api/{ => audio}/audio.rst | 0 .../bluetooth/api/{ => audio}/bap.rst | 0 .../audio}/bluetooth-le-audio-arch.rst | 0 .../bluetooth/api/{ => audio}/cap.rst | 0 .../api/{ => audio}/coordinated_sets.rst | 0 .../{ => api/audio}/img/ble_audio_arch.svg | 0 .../{ => api/audio}/img/cap_proc.svg | 0 .../bluetooth/{ => api/audio}/img/gaf.svg | 0 .../{ => api/audio}/img/zephyr_gaf.svg | 0 .../bluetooth/api/{ => audio}/media.rst | 0 .../bluetooth/api/{ => audio}/microphone.rst | 0 .../bluetooth/api/{ => audio}/shell/bap.rst | 0 .../shell/bap_broadcast_assistant.rst | 0 .../{ => audio}/shell/bap_scan_delegator.rst | 0 .../bluetooth/api/{ => audio}/shell/cap.rst | 0 .../bluetooth/api/{ => audio}/shell/ccp.rst | 0 .../bluetooth/api/{ => audio}/shell/csip.rst | 0 .../bluetooth/api/{ => audio}/shell/gmap.rst | 0 .../bluetooth/api/{ => audio}/shell/mcp.rst | 0 .../bluetooth/api/{ => audio}/shell/pbp.rst | 0 .../bluetooth/api/{ => audio}/shell/tmap.rst | 0 .../bluetooth/api/{ => audio}/volume.rst | 0 doc/connectivity/bluetooth/api/index.rst | 36 +++++++++---------- doc/connectivity/bluetooth/index.rst | 2 +- 26 files changed, 38 insertions(+), 24 deletions(-) rename doc/connectivity/bluetooth/api/{ => audio}/audio.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/bap.rst (100%) rename doc/connectivity/bluetooth/{ => api/audio}/bluetooth-le-audio-arch.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/cap.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/coordinated_sets.rst (100%) rename doc/connectivity/bluetooth/{ => api/audio}/img/ble_audio_arch.svg (100%) rename doc/connectivity/bluetooth/{ => api/audio}/img/cap_proc.svg (100%) rename doc/connectivity/bluetooth/{ => api/audio}/img/gaf.svg (100%) rename doc/connectivity/bluetooth/{ => api/audio}/img/zephyr_gaf.svg (100%) rename doc/connectivity/bluetooth/api/{ => audio}/media.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/microphone.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/bap.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/bap_broadcast_assistant.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/bap_scan_delegator.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/cap.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/ccp.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/csip.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/gmap.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/mcp.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/pbp.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/shell/tmap.rst (100%) rename doc/connectivity/bluetooth/api/{ => audio}/volume.rst (100%) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 53de3ee3da2bb3..ee64c0ea6403ef 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -446,11 +446,7 @@ Bluetooth Audio: - tests/bluetooth/audio/ - tests/bsim/bluetooth/audio/ - tests/bluetooth/shell/audio.conf - - doc/connectivity/bluetooth/img/ble_audio_arch.svg - - doc/connectivity/bluetooth/img/cap_proc.svg - - doc/connectivity/bluetooth/img/gaf.svg - - doc/connectivity/bluetooth/img/zephyr_gaf.svg - - doc/connectivity/bluetooth/bluetooth-le-audio-arch.rst + - doc/connectivity/bluetooth/api/audio/ - samples/bluetooth/broadcast_audio*/ - samples/bluetooth/hap*/ - samples/bluetooth/public_broadcast*/ diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index 64130c7f87a335..bf4f9262749a29 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -18,15 +18,33 @@ ('boards/arduino/uno_r4_minima/doc/index', 'boards/arduino/uno_r4/doc/index'), ('boards/x86/ehl_crb/doc/index', 'boards/x86/intel_ehl/doc/index'), ('boards/x86/rpl_crb/doc/index', 'boards/x86/intel_rpl/doc/index'), + ('connectivity/bluetooth/audio', 'connectivity/bluetooth/api/audio/audio'), + ('connectivity/bluetooth/bap', 'connectivity/bluetooth/api/audio/bap'), ('connectivity/bluetooth/bluetooth-audio-arch', 'connectivity/bluetooth/bluetooth-le-audio-arch'), + ('connectivity/bluetooth/bluetooth-le-audio-arch', 'connectivity/bluetooth/api/audio/bluetooth-le-audio-arch'), + ('connectivity/bluetooth/cap', 'connectivity/bluetooth/api/audio/cap'), + ('connectivity/bluetooth/coordinated_sets', 'connectivity/bluetooth/api/audio/coordinated_sets'), ('connectivity/bluetooth/dis-pics', 'connectivity/bluetooth/ics/dis'), ('connectivity/bluetooth/gap-pics', 'connectivity/bluetooth/ics/gap'), ('connectivity/bluetooth/gatt-pics', 'connectivity/bluetooth/ics/gatt'), ('connectivity/bluetooth/l2cap-pics', 'connectivity/bluetooth/ics/l2cap'), + ('connectivity/bluetooth/media', 'connectivity/bluetooth/api/audio/media'), ('connectivity/bluetooth/mesh-pics', 'connectivity/bluetooth/ics/mesh'), + ('connectivity/bluetooth/microphone', 'connectivity/bluetooth/api/audio/microphone'), ('connectivity/bluetooth/overview', 'connectivity/bluetooth/features'), ('connectivity/bluetooth/rfcomm-pics', 'connectivity/bluetooth/ics/rfcomm'), + ('connectivity/bluetooth/shell/bap', 'connectivity/bluetooth/api/audio/shell/bap'), + ('connectivity/bluetooth/shell/bap_broadcast_assistant', 'connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant'), + ('connectivity/bluetooth/shell/bap_scan_delegator', 'connectivity/bluetooth/api/audio/shell/bap_scan_delegator'), + ('connectivity/bluetooth/shell/cap', 'connectivity/bluetooth/api/audio/shell/cap'), + ('connectivity/bluetooth/shell/ccp', 'connectivity/bluetooth/api/audio/shell/ccp'), + ('connectivity/bluetooth/shell/csip', 'connectivity/bluetooth/api/audio/shell/csip'), + ('connectivity/bluetooth/shell/gmap', 'connectivity/bluetooth/api/audio/shell/gmap'), + ('connectivity/bluetooth/shell/mcp', 'connectivity/bluetooth/api/audio/shell/mcp'), + ('connectivity/bluetooth/shell/pbp', 'connectivity/bluetooth/api/audio/shell/pbp'), + ('connectivity/bluetooth/shell/tmap', 'connectivity/bluetooth/api/audio/shell/tmap'), ('connectivity/bluetooth/sm-pics', 'connectivity/bluetooth/ics/sm'), + ('connectivity/bluetooth/volume', 'connectivity/bluetooth/api/audio/volume'), ('connectivity/networking/networking-api-usage', 'connectivity/networking/api/index'), ('development_process/code_flow', 'project/code_flow'), ('development_process/index', 'project/index'), diff --git a/doc/connectivity/bluetooth/api/audio.rst b/doc/connectivity/bluetooth/api/audio/audio.rst similarity index 100% rename from doc/connectivity/bluetooth/api/audio.rst rename to doc/connectivity/bluetooth/api/audio/audio.rst diff --git a/doc/connectivity/bluetooth/api/bap.rst b/doc/connectivity/bluetooth/api/audio/bap.rst similarity index 100% rename from doc/connectivity/bluetooth/api/bap.rst rename to doc/connectivity/bluetooth/api/audio/bap.rst diff --git a/doc/connectivity/bluetooth/bluetooth-le-audio-arch.rst b/doc/connectivity/bluetooth/api/audio/bluetooth-le-audio-arch.rst similarity index 100% rename from doc/connectivity/bluetooth/bluetooth-le-audio-arch.rst rename to doc/connectivity/bluetooth/api/audio/bluetooth-le-audio-arch.rst diff --git a/doc/connectivity/bluetooth/api/cap.rst b/doc/connectivity/bluetooth/api/audio/cap.rst similarity index 100% rename from doc/connectivity/bluetooth/api/cap.rst rename to doc/connectivity/bluetooth/api/audio/cap.rst diff --git a/doc/connectivity/bluetooth/api/coordinated_sets.rst b/doc/connectivity/bluetooth/api/audio/coordinated_sets.rst similarity index 100% rename from doc/connectivity/bluetooth/api/coordinated_sets.rst rename to doc/connectivity/bluetooth/api/audio/coordinated_sets.rst diff --git a/doc/connectivity/bluetooth/img/ble_audio_arch.svg b/doc/connectivity/bluetooth/api/audio/img/ble_audio_arch.svg similarity index 100% rename from doc/connectivity/bluetooth/img/ble_audio_arch.svg rename to doc/connectivity/bluetooth/api/audio/img/ble_audio_arch.svg diff --git a/doc/connectivity/bluetooth/img/cap_proc.svg b/doc/connectivity/bluetooth/api/audio/img/cap_proc.svg similarity index 100% rename from doc/connectivity/bluetooth/img/cap_proc.svg rename to doc/connectivity/bluetooth/api/audio/img/cap_proc.svg diff --git a/doc/connectivity/bluetooth/img/gaf.svg b/doc/connectivity/bluetooth/api/audio/img/gaf.svg similarity index 100% rename from doc/connectivity/bluetooth/img/gaf.svg rename to doc/connectivity/bluetooth/api/audio/img/gaf.svg diff --git a/doc/connectivity/bluetooth/img/zephyr_gaf.svg b/doc/connectivity/bluetooth/api/audio/img/zephyr_gaf.svg similarity index 100% rename from doc/connectivity/bluetooth/img/zephyr_gaf.svg rename to doc/connectivity/bluetooth/api/audio/img/zephyr_gaf.svg diff --git a/doc/connectivity/bluetooth/api/media.rst b/doc/connectivity/bluetooth/api/audio/media.rst similarity index 100% rename from doc/connectivity/bluetooth/api/media.rst rename to doc/connectivity/bluetooth/api/audio/media.rst diff --git a/doc/connectivity/bluetooth/api/microphone.rst b/doc/connectivity/bluetooth/api/audio/microphone.rst similarity index 100% rename from doc/connectivity/bluetooth/api/microphone.rst rename to doc/connectivity/bluetooth/api/audio/microphone.rst diff --git a/doc/connectivity/bluetooth/api/shell/bap.rst b/doc/connectivity/bluetooth/api/audio/shell/bap.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/bap.rst rename to doc/connectivity/bluetooth/api/audio/shell/bap.rst diff --git a/doc/connectivity/bluetooth/api/shell/bap_broadcast_assistant.rst b/doc/connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/bap_broadcast_assistant.rst rename to doc/connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant.rst diff --git a/doc/connectivity/bluetooth/api/shell/bap_scan_delegator.rst b/doc/connectivity/bluetooth/api/audio/shell/bap_scan_delegator.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/bap_scan_delegator.rst rename to doc/connectivity/bluetooth/api/audio/shell/bap_scan_delegator.rst diff --git a/doc/connectivity/bluetooth/api/shell/cap.rst b/doc/connectivity/bluetooth/api/audio/shell/cap.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/cap.rst rename to doc/connectivity/bluetooth/api/audio/shell/cap.rst diff --git a/doc/connectivity/bluetooth/api/shell/ccp.rst b/doc/connectivity/bluetooth/api/audio/shell/ccp.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/ccp.rst rename to doc/connectivity/bluetooth/api/audio/shell/ccp.rst diff --git a/doc/connectivity/bluetooth/api/shell/csip.rst b/doc/connectivity/bluetooth/api/audio/shell/csip.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/csip.rst rename to doc/connectivity/bluetooth/api/audio/shell/csip.rst diff --git a/doc/connectivity/bluetooth/api/shell/gmap.rst b/doc/connectivity/bluetooth/api/audio/shell/gmap.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/gmap.rst rename to doc/connectivity/bluetooth/api/audio/shell/gmap.rst diff --git a/doc/connectivity/bluetooth/api/shell/mcp.rst b/doc/connectivity/bluetooth/api/audio/shell/mcp.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/mcp.rst rename to doc/connectivity/bluetooth/api/audio/shell/mcp.rst diff --git a/doc/connectivity/bluetooth/api/shell/pbp.rst b/doc/connectivity/bluetooth/api/audio/shell/pbp.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/pbp.rst rename to doc/connectivity/bluetooth/api/audio/shell/pbp.rst diff --git a/doc/connectivity/bluetooth/api/shell/tmap.rst b/doc/connectivity/bluetooth/api/audio/shell/tmap.rst similarity index 100% rename from doc/connectivity/bluetooth/api/shell/tmap.rst rename to doc/connectivity/bluetooth/api/audio/shell/tmap.rst diff --git a/doc/connectivity/bluetooth/api/volume.rst b/doc/connectivity/bluetooth/api/audio/volume.rst similarity index 100% rename from doc/connectivity/bluetooth/api/volume.rst rename to doc/connectivity/bluetooth/api/audio/volume.rst diff --git a/doc/connectivity/bluetooth/api/index.rst b/doc/connectivity/bluetooth/api/index.rst index e9c45edd6deaed..6135df5e6a2048 100644 --- a/doc/connectivity/bluetooth/api/index.rst +++ b/doc/connectivity/bluetooth/api/index.rst @@ -19,24 +19,23 @@ Bluetooth LE Audio .. toctree:: :maxdepth: 1 - audio.rst - bap.rst - cap.rst - coordinated_sets.rst - media.rst - microphone.rst - volume.rst - shell/bap.rst - shell/bap_broadcast_assistant.rst - shell/bap_scan_delegator.rst - shell/cap.rst - shell/ccp.rst - shell/csip.rst - shell/gmap.rst - shell/iso.rst - shell/mcp.rst - shell/tmap.rst - shell/pbp.rst + audio/audio.rst + audio/bap.rst + audio/cap.rst + audio/coordinated_sets.rst + audio/media.rst + audio/microphone.rst + audio/volume.rst + audio/shell/bap.rst + audio/shell/bap_broadcast_assistant.rst + audio/shell/bap_scan_delegator.rst + audio/shell/cap.rst + audio/shell/ccp.rst + audio/shell/csip.rst + audio/shell/gmap.rst + audio/shell/mcp.rst + audio/shell/tmap.rst + audio/shell/pbp.rst Bluetooth LE Host ================= @@ -46,6 +45,7 @@ Bluetooth LE Host services.rst gap.rst + shell/iso.rst gatt.rst att.rst diff --git a/doc/connectivity/bluetooth/index.rst b/doc/connectivity/bluetooth/index.rst index c4f43563e6d9b5..05e6ff410f7175 100644 --- a/doc/connectivity/bluetooth/index.rst +++ b/doc/connectivity/bluetooth/index.rst @@ -17,7 +17,7 @@ hardware, as well as portions of a Classical Bluetooth (BR/EDR) Host layer. bluetooth-qual.rst bluetooth-arch.rst bluetooth-le-host.rst - bluetooth-le-audio-arch.rst + api/audio/bluetooth-le-audio-arch.rst bluetooth-ctlr-arch.rst bluetooth-dev.rst api/index.rst From 12deb6dc37e8c52f90d494a53a8f43f16eb7b6fe Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0045/1389] bluetooth: tester: Add support for OTS This implemnets OTS service and provides OTS instance with two objects for behavior valid and invalid test cases. Service implementation is inspired by peripheral_ots sample. Signed-off-by: Szymon Janc --- tests/bluetooth/tester/CMakeLists.txt | 4 + tests/bluetooth/tester/prj.conf | 9 + tests/bluetooth/tester/src/btp/btp.h | 4 +- tests/bluetooth/tester/src/btp/btp_ots.h | 28 ++ tests/bluetooth/tester/src/btp/bttester.h | 3 + tests/bluetooth/tester/src/btp_core.c | 10 + tests/bluetooth/tester/src/btp_ots.c | 339 ++++++++++++++++++++++ 7 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 tests/bluetooth/tester/src/btp/btp_ots.h create mode 100644 tests/bluetooth/tester/src/btp_ots.c diff --git a/tests/bluetooth/tester/CMakeLists.txt b/tests/bluetooth/tester/CMakeLists.txt index 3efd379c7c27f0..eb3ad4bda24458 100644 --- a/tests/bluetooth/tester/CMakeLists.txt +++ b/tests/bluetooth/tester/CMakeLists.txt @@ -94,3 +94,7 @@ endif() if(CONFIG_BT_TMAP) target_sources(app PRIVATE src/btp_tmap.c) endif() + +if(CONFIG_BT_OTS) + target_sources(app PRIVATE src/btp_ots.c) +endif() diff --git a/tests/bluetooth/tester/prj.conf b/tests/bluetooth/tester/prj.conf index ac240dbe63c40c..84ba74652ddc16 100644 --- a/tests/bluetooth/tester/prj.conf +++ b/tests/bluetooth/tester/prj.conf @@ -39,3 +39,12 @@ CONFIG_BT_RX_STACK_SIZE=4096 CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_TESTING=y CONFIG_UTF8=y + +CONFIG_BT_OTS=y +CONFIG_BT_OTS_DIR_LIST_OBJ=y +CONFIG_BT_OTS_OBJ_NAME_WRITE_SUPPORT=y +CONFIG_BT_OTS_OACP_WRITE_SUPPORT=y +CONFIG_BT_OTS_OACP_PATCH_SUPPORT=y +CONFIG_BT_OTS_OACP_CREATE_SUPPORT=y +CONFIG_BT_OTS_OACP_DELETE_SUPPORT=y +CONFIG_BT_OTS_OACP_CHECKSUM_SUPPORT=y diff --git a/tests/bluetooth/tester/src/btp/btp.h b/tests/bluetooth/tester/src/btp/btp.h index d57e38892b4c78..50443463997342 100644 --- a/tests/bluetooth/tester/src/btp/btp.h +++ b/tests/bluetooth/tester/src/btp/btp.h @@ -37,6 +37,7 @@ #include "btp_cap.h" #include "btp_tbs.h" #include "btp_tmap.h" +#include "btp_ots.h" #define BTP_MTU 1024 #define BTP_DATA_MAX_SIZE (BTP_MTU - sizeof(struct btp_hdr)) @@ -73,8 +74,9 @@ #define BTP_SERVICE_ID_CAP 26 #define BTP_SERVICE_ID_TBS 27 #define BTP_SERVICE_ID_TMAP 28 +#define BTP_SERVICE_ID_OTS 29 -#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_TMAP +#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_OTS #define BTP_STATUS_SUCCESS 0x00 #define BTP_STATUS_FAILED 0x01 diff --git a/tests/bluetooth/tester/src/btp/btp_ots.h b/tests/bluetooth/tester/src/btp/btp_ots.h new file mode 100644 index 00000000000000..ae6900eb0f517e --- /dev/null +++ b/tests/bluetooth/tester/src/btp/btp_ots.h @@ -0,0 +1,28 @@ +/* btp_ots.h - Bluetooth OTS tester headers */ + +/* + * Copyright (c) 2024 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* OTS commands */ +#define BTP_OTS_READ_SUPPORTED_COMMANDS 0x01 +struct btp_ots_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +#define BTP_OTS_REGISTER_OBJECT_FLAGS_SKIP_UNSUPPORTED_PROPS 0x01 + +#define BTP_OTS_REGISTER_OBJECT 0x02 +struct btp_ots_register_object_cmd { + uint8_t flags; + uint32_t ots_props; + uint32_t alloc_size; + uint32_t current_size; + uint8_t name_len; + uint8_t name[0]; +} __packed; +struct btp_ots_register_object_rp { + uint64_t object_id; +} __packed; diff --git a/tests/bluetooth/tester/src/btp/bttester.h b/tests/bluetooth/tester/src/btp/bttester.h index a5f29dd61d8f46..d7ce2699310408 100644 --- a/tests/bluetooth/tester/src/btp/bttester.h +++ b/tests/bluetooth/tester/src/btp/bttester.h @@ -135,3 +135,6 @@ uint8_t tester_unregister_tbs(void); uint8_t tester_init_tmap(void); uint8_t tester_unregister_tmap(void); + +uint8_t tester_init_ots(void); +uint8_t tester_unregister_ots(void); diff --git a/tests/bluetooth/tester/src/btp_core.c b/tests/bluetooth/tester/src/btp_core.c index 3492013b130965..a3f496bece6688 100644 --- a/tests/bluetooth/tester/src/btp_core.c +++ b/tests/bluetooth/tester/src/btp_core.c @@ -245,6 +245,11 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len, status = tester_init_tmap(); break; #endif /* CONFIG_BT_TMAP */ +#if defined(CONFIG_BT_OTS) + case BTP_SERVICE_ID_OTS: + status = tester_init_ots(); + break; +#endif /* CONFIG_BT_OTS */ default: LOG_WRN("unknown id: 0x%02x", cp->id); status = BTP_STATUS_FAILED; @@ -387,6 +392,11 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len, status = tester_unregister_tmap(); break; #endif /* CONFIG_BT_TMAP */ +#if defined(CONFIG_BT_OTS) + case BTP_SERVICE_ID_OTS: + status = tester_unregister_ots(); + break; +#endif /* CONFIG_BT_OTS */ default: LOG_WRN("unknown id: 0x%x", cp->id); status = BTP_STATUS_FAILED; diff --git a/tests/bluetooth/tester/src/btp_ots.c b/tests/bluetooth/tester/src/btp_ots.c new file mode 100644 index 00000000000000..defea7d2fed6b6 --- /dev/null +++ b/tests/bluetooth/tester/src/btp_ots.c @@ -0,0 +1,339 @@ +/* btp_ots.c - Bluetooth OTS Tester */ + +/* + * Copyright (c) 2024 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include + +#include +#define LOG_MODULE_NAME bttester_ots +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); + +#include "btp/btp.h" + +#define OBJ_POOL_SIZE CONFIG_BT_OTS_MAX_OBJ_CNT +#define OBJ_MAX_SIZE 100 + +static struct object { + uint8_t data[OBJ_MAX_SIZE]; + char name[CONFIG_BT_OTS_OBJ_MAX_NAME_LEN + 1]; + bool in_use; +} objects[OBJ_POOL_SIZE]; + +struct object_creation_data { + struct object *object; + struct bt_ots_obj_size size; + uint32_t props; +}; + +#define OTS_OBJ_ID_TO_OBJ_IDX(id) (((id) - BT_OTS_OBJ_ID_MIN) % ARRAY_SIZE(objects)) + +static struct object_creation_data *object_being_created; + +static struct bt_ots *ots; + +static uint8_t ots_supported_commands(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + struct btp_ots_read_supported_commands_rp *rp = rsp; + + tester_set_bit(rp->data, BTP_OTS_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_OTS_REGISTER_OBJECT); + + *rsp_len = sizeof(*rp) + 1; + + return BTP_STATUS_SUCCESS; +} + +static struct object *get_object(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(objects); i++) { + if (!objects[i].in_use) { + objects[i].in_use = true; + return &objects[i]; + } + } + + return NULL; +} + +static uint8_t register_object(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_ots_register_object_cmd *cp = cmd; + struct btp_ots_register_object_rp *rp = rsp; + struct object_creation_data obj_data; + struct bt_ots_obj_add_param param; + uint32_t supported_props = 0; + struct object *obj; + uint32_t props; + int err; + + if ((cmd_len < sizeof(*cp)) || (cmd_len != sizeof(*cp) + cp->name_len)) { + return BTP_STATUS_FAILED; + } + + if (cp->name_len == 0 || cp->name_len > CONFIG_BT_OTS_OBJ_MAX_NAME_LEN) { + return BTP_STATUS_FAILED; + } + + /* all supported props (execute, append, truncate not supported) */ + BT_OTS_OBJ_SET_PROP_DELETE(supported_props); + BT_OTS_OBJ_SET_PROP_READ(supported_props); + BT_OTS_OBJ_SET_PROP_WRITE(supported_props); + BT_OTS_OBJ_SET_PROP_PATCH(supported_props); + + props = sys_le32_to_cpu(cp->ots_props); + if (cp->flags & BTP_OTS_REGISTER_OBJECT_FLAGS_SKIP_UNSUPPORTED_PROPS) { + props &= supported_props; + } + + obj = get_object(); + if (!obj) { + return BTP_STATUS_FAILED; + } + + (void)memset(&obj_data, 0, sizeof(obj_data)); + + memcpy(obj->name, cp->name, cp->name_len); + obj_data.object = obj; + obj_data.size.cur = sys_le32_to_cpu(cp->current_size); + obj_data.size.alloc = sys_le32_to_cpu(cp->alloc_size); + obj_data.props = props; + + /* bt_ots_obj_add() lacks user_data so we need to use global for + * passing this + */ + object_being_created = &obj_data; + + param.size = obj_data.size.alloc; + param.type.uuid.type = BT_UUID_TYPE_16; + param.type.uuid_16.val = BT_UUID_OTS_TYPE_UNSPECIFIED_VAL; + + err = bt_ots_obj_add(ots, ¶m); + object_being_created = NULL; + + if (err < 0) { + memset(obj, 0, sizeof(*obj)); + return BTP_STATUS_FAILED; + } + + rp->object_id = sys_cpu_to_le64(err); + *rsp_len = sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + +static const struct btp_handler ots_handlers[] = { + { + .opcode = BTP_OTS_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = ots_supported_commands + }, + { + .opcode = BTP_OTS_REGISTER_OBJECT, + .index = 0, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = register_object + }, +}; + +static int ots_obj_created(struct bt_ots *ots, struct bt_conn *conn, uint64_t id, + const struct bt_ots_obj_add_param *add_param, + struct bt_ots_obj_created_desc *created_desc) +{ + struct object *obj; + + LOG_DBG("id=%"PRIu64" size=%u", id, add_param->size); + + /* TS suggests to use OTS service UUID for testing this */ + if (conn && bt_uuid_cmp(&add_param->type.uuid, BT_UUID_OTS) == 0) { + return -ENOTSUP; + } + + if (add_param->size > OBJ_MAX_SIZE) { + return -ENOMEM; + } + + if (conn || !object_being_created) { + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + + if (obj_index >= OBJ_POOL_SIZE) { + return -ENOMEM; + } + + obj = &objects[obj_index]; + if (obj->in_use) { + return -ENOMEM; + } + + obj->in_use = false; + created_desc->name = obj->name; + created_desc->size.alloc = OBJ_MAX_SIZE; + BT_OTS_OBJ_SET_PROP_READ(created_desc->props); + BT_OTS_OBJ_SET_PROP_WRITE(created_desc->props); + BT_OTS_OBJ_SET_PROP_PATCH(created_desc->props); + BT_OTS_OBJ_SET_PROP_DELETE(created_desc->props); + } else { + obj = object_being_created->object; + created_desc->name = obj->name; + created_desc->size = object_being_created->size; + created_desc->props = object_being_created->props; + } + + return 0; +} + +static int ots_obj_deleted(struct bt_ots *ots, struct bt_conn *conn, + uint64_t id) +{ + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + struct object *obj; + + LOG_DBG("id=%"PRIu64, id); + + if (obj_index >= OBJ_POOL_SIZE) { + return -ENOENT; + } + + obj = &objects[obj_index]; + memset(obj, 0, sizeof(*obj)); + + return 0; +} + +static void ots_obj_selected(struct bt_ots *ots, struct bt_conn *conn, + uint64_t id) +{ + LOG_DBG("id=%"PRIu64, id); +} + +static ssize_t ots_obj_read(struct bt_ots *ots, struct bt_conn *conn, + uint64_t id, void **data, size_t len, + off_t offset) +{ + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + + LOG_DBG("id=%"PRIu64" data=%p offset=%ld len=%zu", id, data, (long)offset, len); + + if (!data) { + return 0; + } + + if (obj_index >= OBJ_POOL_SIZE) { + return -ENOENT; + } + + *data = &objects[obj_index].data[offset]; + + return len; +} + +static ssize_t ots_obj_write(struct bt_ots *ots, struct bt_conn *conn, + uint64_t id, const void *data, size_t len, + off_t offset, size_t rem) +{ + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + + LOG_DBG("id=%"PRIu64" data=%p offset=%ld len=%zu", id, data, (long)offset, len); + + if (obj_index >= OBJ_POOL_SIZE) { + return -ENOENT; + } + + (void)memcpy(&objects[obj_index].data[offset], data, len); + + return len; +} + +static void ots_obj_name_written(struct bt_ots *ots, struct bt_conn *conn, + uint64_t id, const char *cur_name, const char *new_name) +{ + LOG_DBG("id=%"PRIu64"cur_name=%s new_name=%s", id, cur_name, new_name); +} + +static int ots_obj_cal_checksum(struct bt_ots *ots, struct bt_conn *conn, uint64_t id, + off_t offset, size_t len, void **data) +{ + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + + if (obj_index >= OBJ_POOL_SIZE) { + return -ENOENT; + } + + *data = &objects[obj_index].data[offset]; + return 0; +} + +static struct bt_ots_cb ots_callbacks = { + .obj_created = ots_obj_created, + .obj_deleted = ots_obj_deleted, + .obj_selected = ots_obj_selected, + .obj_read = ots_obj_read, + .obj_write = ots_obj_write, + .obj_name_written = ots_obj_name_written, + .obj_cal_checksum = ots_obj_cal_checksum, +}; + +static int ots_init(void) +{ + int err; + struct bt_ots_init_param ots_init; + + /* Configure OTS initialization. */ + (void)memset(&ots_init, 0, sizeof(ots_init)); + BT_OTS_OACP_SET_FEAT_READ(ots_init.features.oacp); + BT_OTS_OACP_SET_FEAT_WRITE(ots_init.features.oacp); + BT_OTS_OACP_SET_FEAT_CREATE(ots_init.features.oacp); + BT_OTS_OACP_SET_FEAT_DELETE(ots_init.features.oacp); + BT_OTS_OACP_SET_FEAT_CHECKSUM(ots_init.features.oacp); + BT_OTS_OACP_SET_FEAT_PATCH(ots_init.features.oacp); + BT_OTS_OLCP_SET_FEAT_GO_TO(ots_init.features.olcp); + ots_init.cb = &ots_callbacks; + + /* Initialize OTS instance. */ + err = bt_ots_init(ots, &ots_init); + if (err) { + LOG_ERR("Failed to init OTS (err:%d)\n", err); + return err; + } + + return 0; +} + +uint8_t tester_init_ots(void) +{ + int err; + + /* TODO there is no API to return OTS instance to pool */ + if (!ots) { + ots = bt_ots_free_instance_get(); + } + + if (!ots) { + return BTP_STATUS_FAILED; + } + + err = ots_init(); + if (err) { + return BTP_STATUS_VAL(err); + } + + tester_register_command_handlers(BTP_SERVICE_ID_OTS, ots_handlers, + ARRAY_SIZE(ots_handlers)); + + return BTP_STATUS_SUCCESS; +} + +uint8_t tester_unregister_ots(void) +{ + memset(objects, 0, sizeof(objects)); + + return BTP_STATUS_SUCCESS; +} From 957214b8a3252bfe18facd6ebc33b2998f78a522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0046/1389] west.yml: update loramac-node for FragDecoder Kconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Required to allow configuring FragDecoder via Kconfig. Signed-off-by: Martin Jäger --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 12da756463efc6..6d879bce8e6502 100644 --- a/west.yml +++ b/west.yml @@ -271,7 +271,7 @@ manifest: - fs revision: 408c16a909dd6cf128874a76f21c793798c9e423 - name: loramac-node - revision: 1bf2120cffcedae174ae35d695a28a46caefcb23 + revision: fb00b383072518c918e2258b0916c996f2d4eebe path: modules/lib/loramac-node - name: lvgl revision: 2b498e6f36d6b82ae1da12c8b7742e318624ecf5 From 8933a0b52cbea42bd741ccf98fc666be2faf9402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0047/1389] lorawan: services: add Fragmented Data Block Transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This service receives fragmented data (usually firmware images) and stores them in the slot1_partition in the flash. Also update CMakeLists.txt in loramac-node module to be able to use FragDecoder.c Signed-off-by: Martin Jäger --- include/zephyr/lorawan/lorawan.h | 18 ++ modules/loramac-node/CMakeLists.txt | 6 + subsys/lorawan/services/CMakeLists.txt | 6 + subsys/lorawan/services/Kconfig | 84 ++++++ subsys/lorawan/services/frag_flash.c | 129 ++++++++++ subsys/lorawan/services/frag_flash.h | 69 +++++ subsys/lorawan/services/frag_transport.c | 310 +++++++++++++++++++++++ 7 files changed, 622 insertions(+) create mode 100644 subsys/lorawan/services/frag_flash.c create mode 100644 subsys/lorawan/services/frag_flash.h create mode 100644 subsys/lorawan/services/frag_transport.c diff --git a/include/zephyr/lorawan/lorawan.h b/include/zephyr/lorawan/lorawan.h index 1bad5130730be2..4ce1605237a698 100644 --- a/include/zephyr/lorawan/lorawan.h +++ b/include/zephyr/lorawan/lorawan.h @@ -373,6 +373,24 @@ int lorawan_clock_sync_get(uint32_t *gps_time); #endif /* CONFIG_LORAWAN_APP_CLOCK_SYNC */ +#ifdef CONFIG_LORAWAN_FRAG_TRANSPORT + +/** + * @brief Run Fragmented Data Block Transport service + * + * This service receives fragmented data (usually firmware images) and + * stores them in the image-1 flash partition. + * + * After all fragments have been received, the provided callback is invoked. + * + * @param transport_finished_cb Callback for notification of finished data transfer. + * + * @return 0 if successful, negative errno otherwise. + */ +int lorawan_frag_transport_run(void (*transport_finished_cb)(void)); + +#endif /* CONFIG_LORAWAN_FRAG_TRANSPORT */ + #ifdef __cplusplus } #endif diff --git a/modules/loramac-node/CMakeLists.txt b/modules/loramac-node/CMakeLists.txt index 1a84a5f6ac4ae9..9e0bdbc98771ce 100644 --- a/modules/loramac-node/CMakeLists.txt +++ b/modules/loramac-node/CMakeLists.txt @@ -30,6 +30,8 @@ if(${CONFIG_HAS_SEMTECH_LORAMAC}) zephyr_library_include_directories( ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/mac ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/mac/region + # required for FUOTA FragDecoder.h + ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/apps/LoRaMac/common/LmHandler/packages ) endif() @@ -53,6 +55,10 @@ zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_LORAMAC ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/mac/LoRaMacSerializer.c ) +zephyr_library_sources_ifdef(CONFIG_LORAWAN_FRAG_TRANSPORT + ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/apps/LoRaMac/common/LmHandler/packages/FragDecoder.c +) + zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_LORAMAC ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/mac/region/Region.c ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/mac/region/RegionCommon.c diff --git a/subsys/lorawan/services/CMakeLists.txt b/subsys/lorawan/services/CMakeLists.txt index b634efd69b3a2c..2f3aeeeaca23fa 100644 --- a/subsys/lorawan/services/CMakeLists.txt +++ b/subsys/lorawan/services/CMakeLists.txt @@ -9,6 +9,12 @@ if(CONFIG_LORAWAN_SERVICES) clock_sync.c ) + zephyr_library_sources_ifdef( + CONFIG_LORAWAN_FRAG_TRANSPORT + frag_flash.c + frag_transport.c + ) + zephyr_library_sources_ifdef( CONFIG_LORAWAN_REMOTE_MULTICAST multicast.c diff --git a/subsys/lorawan/services/Kconfig b/subsys/lorawan/services/Kconfig index 6ab6d4e55afafb..95905a7cbffadd 100644 --- a/subsys/lorawan/services/Kconfig +++ b/subsys/lorawan/services/Kconfig @@ -54,6 +54,90 @@ config LORAWAN_APP_CLOCK_SYNC_PERIODICITY Default setting: 24h. +config LORAWAN_FRAG_TRANSPORT + bool "Fragmented Data Block Transport" + select FLASH_MAP + select FLASH_PAGE_LAYOUT + select IMG_MANAGER + help + Enables the LoRaWAN Fragmented Data Block Transport service + according to TS004-1.0.0 as published by the LoRa Alliance. + + The used default port for this service is 201. + +DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition + +config LORAWAN_FRAG_TRANSPORT_IMAGE_SIZE + int "Total size of firmware image" + depends on LORAWAN_FRAG_TRANSPORT + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_CODE_PARTITION)) + help + Size of the flash partition for the application firmware image + in bytes. + + The minimum number of fragments to be transferred is calculated from + this value divided by the fragment size. + + This setting has significant influence on RAM usage. + +config LORAWAN_FRAG_TRANSPORT_MAX_FRAG_SIZE + int "Maximum size of transported fragments" + depends on LORAWAN_FRAG_TRANSPORT + range 1 239 + default 232 + help + Maximum size of one fragment transferred during the fragmented data + block transport session of the FUOTA process. It is chosen on the + server side. + + The fragment has to fit into the LoRaWAN payload, which can be up to + 242 bytes depending on the region and frequency settings. 3 bytes of + the payload are consumed for protocol information. + + For some MCUs like the STM32WL the fragment size has to be a multiple + of 8 (see flash driver for further information). + + This setting has significant influence on RAM usage. If the exact + fragment size is known, use that value for MIN and MAX config to + reduce memory consumption. + +config LORAWAN_FRAG_TRANSPORT_MIN_FRAG_SIZE + int "Minimum size of transported fragments" + depends on LORAWAN_FRAG_TRANSPORT + range 1 239 + default 48 + help + Minimum size of one fragment transferred during the fragmented data + block transport session of the FUOTA process. It is chosen on the + server side. + + The fragment has to fit into the LoRaWAN payload, which can be up to + 242 bytes depending on the region and frequency settings. 3 bytes of + the payload are consumed for protocol information. + + For some MCUs like the STM32WL the fragment size has to be a multiple + of 8 (see flash driver for further information). + + This setting has significant influence on RAM usage. If the exact + fragment size is known, use that value for MIN and MAX config to + reduce memory consumption. + +config LORAWAN_FRAG_TRANSPORT_MAX_REDUNDANCY + int "Percentage of redundant fragments" + depends on LORAWAN_FRAG_TRANSPORT + range 1 100 + default 20 + help + The built-in forward error correction (FEC) mechanism allows to + reconstruct missed packages from additional redundant packages + sent by the server after all packages have been sent. + + This parameter specifies the maximum amount of packet loss (in + percent) for which it should be possible to reconstruct the full + firmware image. + + This setting has significant influence on RAM usage. + config LORAWAN_REMOTE_MULTICAST bool "Remote Multicast Setup" depends on LORAWAN_APP_CLOCK_SYNC diff --git a/subsys/lorawan/services/frag_flash.c b/subsys/lorawan/services/frag_flash.c new file mode 100644 index 00000000000000..2d5db55a7a8bb8 --- /dev/null +++ b/subsys/lorawan/services/frag_flash.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2022-2024 Libre Solar Technologies GmbH + * Copyright (c) 2022-2024 tado GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "frag_flash.h" + +#include + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(lorawan_frag_flash, CONFIG_LORAWAN_SERVICES_LOG_LEVEL); + +#define TARGET_IMAGE_AREA FIXED_PARTITION_ID(slot1_partition) + +struct frag_cache_entry { + uint32_t addr; + uint8_t data[FRAG_MAX_SIZE]; +}; + +static struct frag_cache_entry frag_cache[FRAG_MAX_REDUNDANCY]; +static uint32_t frag_size; +static int cached_frags; +static bool use_cache; + +static const struct flash_area *fa; + +int frag_flash_init(uint32_t fragment_size) +{ + int err; + + if (fragment_size > FRAG_MAX_SIZE) { + return -ENOSPC; + } + + frag_size = fragment_size; + cached_frags = 0; + use_cache = false; + + err = flash_area_open(TARGET_IMAGE_AREA, &fa); + if (err) { + return err; + } + + LOG_DBG("Starting to erase flash area"); + + err = flash_area_erase(fa, 0, fa->fa_size); + + LOG_DBG("Finished erasing flash area"); + + return err; +} + +int8_t frag_flash_write(uint32_t addr, uint8_t *data, uint32_t size) +{ + int8_t err = 0; + + if (!use_cache) { + LOG_DBG("Writing %u bytes to addr 0x%X", size, addr); + + err = flash_area_write(fa, addr, data, size); + } else { + LOG_DBG("Caching %u bytes for addr 0x%X", size, addr); + + if (size != frag_size) { + LOG_ERR("Invalid fragment size %d", size); + return -EINVAL; + } + + /* overwrite fragment in cache if existing */ + for (int i = 0; i < cached_frags; i++) { + if (frag_cache[i].addr == addr) { + memcpy(frag_cache[i].data, data, size); + return 0; + } + } + + /* otherwise create new cache entry */ + if (cached_frags < ARRAY_SIZE(frag_cache)) { + frag_cache[cached_frags].addr = addr; + memcpy(frag_cache[cached_frags].data, data, size); + cached_frags++; + } else { + LOG_ERR("Fragment cache too small"); + err = -ENOSPC; + } + } + + return err == 0 ? 0 : -1; +} + +int8_t frag_flash_read(uint32_t addr, uint8_t *data, uint32_t size) +{ + for (int i = 0; i < cached_frags; i++) { + if (frag_cache[i].addr == addr) { + memcpy(data, frag_cache[i].data, size); + return 0; + } + } + + return flash_area_read(fa, addr, data, size) == 0 ? 0 : -1; +} + +void frag_flash_use_cache(void) +{ + use_cache = true; +} + +void frag_flash_finish(void) +{ + int err; + + for (int i = 0; i < cached_frags; i++) { + LOG_DBG("Writing %u bytes to addr 0x%x", frag_size, frag_cache[i].addr); + flash_area_write(fa, frag_cache[i].addr, frag_cache[i].data, frag_size); + } + + flash_area_close(fa); + + err = boot_request_upgrade(BOOT_UPGRADE_TEST); + if (err) { + LOG_ERR("Failed to request upgrade (err %d)", err); + } +} diff --git a/subsys/lorawan/services/frag_flash.h b/subsys/lorawan/services/frag_flash.h new file mode 100644 index 00000000000000..cecb91f3acc694 --- /dev/null +++ b/subsys/lorawan/services/frag_flash.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022-2024 Libre Solar Technologies GmbH + * Copyright (c) 2022-2024 tado GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SUBSYS_LORAWAN_SERVICES_FRAG_FLASH_H_ +#define ZEPHYR_SUBSYS_LORAWAN_SERVICES_FRAG_FLASH_H_ + +#include + +/** + * Initialize flash driver and prepare partition for new firmware image. + * + * This function mass-erases the flash partition and may take a while to return. + * + * @param frag_size Fragment size used for this session + * + * @returns 0 for success, otherwise negative error code + */ +int frag_flash_init(uint32_t frag_size); + +/** + * Write received data fragment to flash. + * + * This function is called by FragDecoder from LoRaMAC-node stack. + * + * @param addr Flash address relative to start of slot + * @param data Data buffer + * @param size Number of bytes in the buffer + * + * @returns 0 for success, otherwise negative error code + */ +int8_t frag_flash_write(uint32_t addr, uint8_t *data, uint32_t size); + +/** + * Read back data from flash. + * + * This function is called by FragDecoder from LoRaMAC-node stack. + * + * @param addr Flash address relative to start of slot + * @param data Data buffer + * @param size Number of bytes in the buffer + * + * @returns 0 for success, otherwise negative error code + */ +int8_t frag_flash_read(uint32_t addr, uint8_t *data, uint32_t size); + +/** + * Start caching fragments in RAM. + * + * Coded/redundant fragments may be overwritten with future fragments, + * so we have to cache them in RAM instead of flash. + * + * This function must be called once all uncoded fragments have been received. + */ +void frag_flash_use_cache(void); + +/** + * Finalize flashing after sufficient fragments have been received. + * + * This call will also write cached fragments to flash. + * + * After this call the new firmware is ready to be checked and booted. + */ +void frag_flash_finish(void); + +#endif /* ZEPHYR_SUBSYS_LORAWAN_SERVICES_FRAG_FLASH_H_ */ diff --git a/subsys/lorawan/services/frag_transport.c b/subsys/lorawan/services/frag_transport.c new file mode 100644 index 00000000000000..2db28bb03661b4 --- /dev/null +++ b/subsys/lorawan/services/frag_transport.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2022-2024 Libre Solar Technologies GmbH + * Copyright (c) 2022-2024 tado GmbH + * + * Parts of this implementation were inspired by LmhpFragmentation.c from the + * LoRaMac-node firmware repository https://github.com/Lora-net/LoRaMac-node + * written by Miguel Luis (Semtech). + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "frag_flash.h" +#include "lorawan_services.h" + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(lorawan_frag_transport, CONFIG_LORAWAN_SERVICES_LOG_LEVEL); + +/** + * Version of LoRaWAN Fragmented Data Block Transport Specification + * + * This implementation only supports TS004-1.0.0. + */ +#define FRAG_TRANSPORT_VERSION 1 + +/** + * Maximum expected number of frag transport commands per packet + * + * The standard states "A message MAY carry more than one command". Even though this was not + * observed during testing, space for up to 3 packages is reserved. + */ +#define FRAG_TRANSPORT_MAX_CMDS_PER_PACKAGE 3 + +/* maximum length of frag_transport answers */ +#define FRAG_TRANSPORT_MAX_ANS_LEN 5 + +enum frag_transport_commands { + FRAG_TRANSPORT_CMD_PKG_VERSION = 0x00, + FRAG_TRANSPORT_CMD_FRAG_STATUS = 0x01, + FRAG_TRANSPORT_CMD_FRAG_SESSION_SETUP = 0x02, + FRAG_TRANSPORT_CMD_FRAG_SESSION_DELETE = 0x03, + FRAG_TRANSPORT_CMD_DATA_FRAGMENT = 0x08, +}; + +struct frag_transport_context { + /** Stores if a session is active */ + bool is_active; + union { + uint8_t frag_session; + struct { + /** Multicast groups allowed to input to this frag session */ + uint8_t mc_group_bit_mask: 4; + /** Identifies this session */ + uint8_t frag_index: 2; + }; + }; + /** Number of fragments of the data block for this session, max. 2^14-1 */ + uint16_t nb_frag; + /** Number of fragments received in this session (including coded, uncoded and repeated) */ + uint16_t nb_frag_received; + /** Size of each fragment in octets */ + uint8_t frag_size; + union { + uint8_t control; + struct { + /** Random delay for some responses between 0 and 2^(BlockAckDelay + 4) */ + uint8_t block_ack_delay: 3; + /** Used fragmentation algorithm (0 for forward error correction) */ + uint8_t frag_algo: 3; + }; + }; + /** Padding in the last fragment if total size is not a multiple of frag_size */ + uint8_t padding; + /** Application-specific descriptor for the data block, e.g. firmware version */ + uint32_t descriptor; + + /* variables required for FragDecoder.h */ + FragDecoderCallbacks_t decoder_callbacks; + int32_t decoder_process_status; +}; + +/* + * The frag decoder is a singleton, so we can only have one ongoing frag session at a time, even + * though the standard allows up to 4 sessions + */ +static struct frag_transport_context ctx; + +/* Callback for notification of finished firmware transfer */ +static void (*finished_cb)(void); + +static void frag_transport_package_callback(uint8_t port, bool data_pending, int16_t rssi, + int8_t snr, uint8_t len, const uint8_t *rx_buf) +{ + uint8_t tx_buf[FRAG_TRANSPORT_MAX_CMDS_PER_PACKAGE * FRAG_TRANSPORT_MAX_ANS_LEN]; + uint8_t tx_pos = 0; + uint8_t rx_pos = 0; + int ans_delay = 0; + + __ASSERT(port == LORAWAN_PORT_FRAG_TRANSPORT, "Wrong port %d", port); + + while (rx_pos < len) { + uint8_t command_id = rx_buf[rx_pos++]; + + if (sizeof(tx_buf) - tx_pos < FRAG_TRANSPORT_MAX_ANS_LEN) { + LOG_ERR("insufficient tx_buf size, some requests discarded"); + break; + } + + switch (command_id) { + case FRAG_TRANSPORT_CMD_PKG_VERSION: + tx_buf[tx_pos++] = FRAG_TRANSPORT_CMD_PKG_VERSION; + tx_buf[tx_pos++] = LORAWAN_PACKAGE_ID_FRAG_TRANSPORT_BLOCK; + tx_buf[tx_pos++] = FRAG_TRANSPORT_VERSION; + break; + case FRAG_TRANSPORT_CMD_FRAG_STATUS: { + uint8_t frag_status = rx_buf[rx_pos++] & 0x07; + uint8_t participants = frag_status & 0x01; + uint8_t index = frag_status >> 1; + + LOG_DBG("FragSessionStatusReq index %d, participants: %u", index, + participants); + + uint8_t missing_frag = CLAMP(ctx.nb_frag - ctx.nb_frag_received, 0, 255); + + FragDecoderStatus_t decoder_status = FragDecoderGetStatus(); + uint8_t memory_error = decoder_status.MatrixError; + + if (participants == 1 || missing_frag > 0) { + tx_buf[tx_pos++] = FRAG_TRANSPORT_CMD_FRAG_STATUS; + tx_buf[tx_pos++] = ctx.nb_frag_received & 0xFF; + tx_buf[tx_pos++] = + (index << 6) | ((ctx.nb_frag_received >> 8) & 0x3F); + tx_buf[tx_pos++] = missing_frag; + tx_buf[tx_pos++] = memory_error & 0x01; + + ans_delay = sys_rand32_get() % (1U << (ctx.block_ack_delay + 4)); + + LOG_DBG("FragSessionStatusAns index %d, NbFragReceived: %u, " + "MissingFrag: %u, MemoryError: %u, delay: %d", + index, ctx.nb_frag_received, missing_frag, memory_error, + ans_delay); + } + break; + } + case FRAG_TRANSPORT_CMD_FRAG_SESSION_SETUP: { + uint8_t frag_session = rx_buf[rx_pos++] & 0x3F; + uint8_t index = frag_session >> 4; + uint8_t status = index << 6; + + if (!ctx.is_active || ctx.frag_index == index) { + ctx.frag_session = frag_session; + ctx.nb_frag_received = 0; + + ctx.nb_frag = sys_get_le16(rx_buf + rx_pos); + rx_pos += sizeof(uint16_t); + + ctx.frag_size = rx_buf[rx_pos++]; + ctx.control = rx_buf[rx_pos++]; + ctx.padding = rx_buf[rx_pos++]; + + ctx.descriptor = sys_get_le32(rx_buf + rx_pos); + rx_pos += sizeof(uint32_t); + + LOG_INF("FragSessionSetupReq index %d, nb_frag: %u, frag_size: %u, " + "padding: %u, control: 0x%x, descriptor: 0x%.8x", + index, ctx.nb_frag, ctx.frag_size, ctx.padding, ctx.control, + ctx.descriptor); + } else { + /* FragIndex unsupported */ + status |= BIT(2); + + LOG_WRN("FragSessionSetupReq failed. Session %u still active", + ctx.frag_index); + } + + if (ctx.frag_algo > 0) { + /* FragAlgo unsupported */ + status |= BIT(0); + } + + if (ctx.nb_frag > FRAG_MAX_NB || ctx.frag_size > FRAG_MAX_SIZE || + ctx.nb_frag * ctx.frag_size > FragDecoderGetMaxFileSize()) { + /* Not enough memory */ + status |= BIT(1); + } + + /* Descriptor not used: Ignore Wrong Descriptor error */ + + if ((status & 0x1F) == 0) { + /* + * Assign callbacks after initialization to prevent the FragDecoder + * from writing byte-wise 0xFF to the entire flash. Instead, erase + * flash properly with own implementation. + */ + ctx.decoder_callbacks.FragDecoderWrite = NULL; + ctx.decoder_callbacks.FragDecoderRead = NULL; + + FragDecoderInit(ctx.nb_frag, ctx.frag_size, &ctx.decoder_callbacks); + + ctx.decoder_callbacks.FragDecoderWrite = frag_flash_write; + ctx.decoder_callbacks.FragDecoderRead = frag_flash_read; + + frag_flash_init(ctx.frag_size); + ctx.is_active = true; + ctx.decoder_process_status = FRAG_SESSION_ONGOING; + } + + tx_buf[tx_pos++] = FRAG_TRANSPORT_CMD_FRAG_SESSION_SETUP; + tx_buf[tx_pos++] = status; + break; + } + case FRAG_TRANSPORT_CMD_FRAG_SESSION_DELETE: { + uint8_t index = rx_buf[rx_pos++] & 0x03; + uint8_t status = 0x00; + + status |= index; + if (!ctx.is_active || ctx.frag_index != index) { + /* Session does not exist */ + status |= BIT(2); + } else { + ctx.is_active = false; + } + + tx_buf[tx_pos++] = FRAG_TRANSPORT_CMD_FRAG_SESSION_DELETE; + tx_buf[tx_pos++] = status; + break; + } + case FRAG_TRANSPORT_CMD_DATA_FRAGMENT: { + ctx.nb_frag_received++; + + uint16_t frag_index_n = sys_get_le16(rx_buf + rx_pos); + + rx_pos += 2; + + uint16_t frag_counter = frag_index_n & 0x3FFF; + uint8_t index = (frag_index_n >> 14) & 0x03; + + if (!ctx.is_active || index != ctx.frag_index) { + LOG_DBG("DataFragment received for inactive session %u", index); + break; + } + + if (ctx.decoder_process_status == FRAG_SESSION_ONGOING) { + if (frag_counter > ctx.nb_frag) { + /* Additional fragments have to be cached in RAM for + * recovery algorithm. + */ + frag_flash_use_cache(); + } + + ctx.decoder_process_status = FragDecoderProcess( + frag_counter, (uint8_t *)&rx_buf[rx_pos]); + } + + LOG_INF("DataFragment %u of %u (%u lost), session: %u, decoder result: %d", + frag_counter, ctx.nb_frag, frag_counter - ctx.nb_frag_received, + index, ctx.decoder_process_status); + + if (ctx.decoder_process_status >= 0) { + /* Positive status corresponds to number of lost (but recovered) + * fragments. Value >= 0 means the transport is done. + */ + frag_flash_finish(); + + LOG_INF("Frag Transport finished successfully"); + + if (finished_cb != NULL) { + finished_cb(); + } + + ctx.is_active = false; + /* avoid processing further fragments */ + ctx.decoder_process_status = FRAG_SESSION_NOT_STARTED; + } + + rx_pos += ctx.frag_size; + break; + } + default: + return; + } + } + + if (tx_pos > 0) { + lorawan_services_schedule_uplink(LORAWAN_PORT_FRAG_TRANSPORT, tx_buf, tx_pos, + ans_delay); + } +} + +static struct lorawan_downlink_cb downlink_cb = { + .port = (uint8_t)LORAWAN_PORT_FRAG_TRANSPORT, + .cb = frag_transport_package_callback, +}; + +int lorawan_frag_transport_run(void (*transport_finished_cb)(void)) +{ + finished_cb = transport_finished_cb; + + /* initialize non-zero static variables */ + ctx.decoder_process_status = FRAG_SESSION_NOT_STARTED; + + lorawan_register_downlink_callback(&downlink_cb); + + return 0; +} From ec90eb7eee4c4346b93c0503a98d9c45d31343f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0048/1389] tests: subsys: lorawan: add frag_decoder unit-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unit test allows to test the frag decoder algorithms using random binary data. The coded fragments are created on the fly using the encoder algorithm described by Semtech in the LoRaWAN TS004-1.0.0 document. Signed-off-by: Martin Jäger --- .../lorawan/frag_decoder/CMakeLists.txt | 9 ++ .../frag_decoder/boards/native_sim.conf | 4 + .../frag_decoder/boards/native_sim.overlay | 50 +++++++ tests/subsys/lorawan/frag_decoder/prj.conf | 33 +++++ .../lorawan/frag_decoder/src/frag_encoder.c | 113 ++++++++++++++++ .../lorawan/frag_decoder/src/frag_encoder.h | 29 ++++ tests/subsys/lorawan/frag_decoder/src/main.c | 127 ++++++++++++++++++ .../subsys/lorawan/frag_decoder/testcase.yaml | 7 + 8 files changed, 372 insertions(+) create mode 100644 tests/subsys/lorawan/frag_decoder/CMakeLists.txt create mode 100644 tests/subsys/lorawan/frag_decoder/boards/native_sim.conf create mode 100644 tests/subsys/lorawan/frag_decoder/boards/native_sim.overlay create mode 100644 tests/subsys/lorawan/frag_decoder/prj.conf create mode 100644 tests/subsys/lorawan/frag_decoder/src/frag_encoder.c create mode 100644 tests/subsys/lorawan/frag_decoder/src/frag_encoder.h create mode 100644 tests/subsys/lorawan/frag_decoder/src/main.c create mode 100644 tests/subsys/lorawan/frag_decoder/testcase.yaml diff --git a/tests/subsys/lorawan/frag_decoder/CMakeLists.txt b/tests/subsys/lorawan/frag_decoder/CMakeLists.txt new file mode 100644 index 00000000000000..664fc0371ad55d --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lorawan_frag_decoder_test) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/lorawan/frag_decoder/boards/native_sim.conf b/tests/subsys/lorawan/frag_decoder/boards/native_sim.conf new file mode 100644 index 00000000000000..ef6a05851848c1 --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/boards/native_sim.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Turn off log messages for failed communication with non-existing LoRa PHY +CONFIG_LORA_LOG_LEVEL_OFF=y diff --git a/tests/subsys/lorawan/frag_decoder/boards/native_sim.overlay b/tests/subsys/lorawan/frag_decoder/boards/native_sim.overlay new file mode 100644 index 00000000000000..5101a21d8c33f5 --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/boards/native_sim.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 A Labs GmbH + * + * SPDX-License-Identifier: Apache-2.0 + * + * This overlay defines a fake LoRa PHY node which is required to build the driver. + */ + +#include + +/ { + chosen { + zephyr,code-partition = &slot0_partition; + }; + + aliases { + lora0 = &lora; + }; + + test { + #address-cells = <1>; + #size-cells = <1>; + + test_spi: spi@33334444 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "vnd,spi"; + reg = <0x33334444 0x1000>; + status = "okay"; + clock-frequency = <2000000>; + + cs-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + + lora: lora@0 { + compatible = "semtech,sx1262"; + status = "okay"; + reg = <0>; + reset-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + busy-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; + tx-enable-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + rx-enable-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + dio1-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + dio2-tx-enable; + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <5>; + spi-max-frequency = <1000000>; + }; + }; + }; +}; diff --git a/tests/subsys/lorawan/frag_decoder/prj.conf b/tests/subsys/lorawan/frag_decoder/prj.conf new file mode 100644 index 00000000000000..50141338caf54a --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/prj.conf @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y + +# General Zephyr settings +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +CONFIG_THREAD_NAME=y +CONFIG_LOG=y + +# LoRa PHY and required peripherals +CONFIG_LORA=y +CONFIG_SPI=y +CONFIG_GPIO=y + +# Random number generator required for several LoRaWAN services +CONFIG_ENTROPY_GENERATOR=y + +# LoRaWAN application layer +CONFIG_LORAWAN=y +CONFIG_LORAWAN_EMUL=y +CONFIG_LORAMAC_REGION_EU868=y + +# LoRaWAN services required for this test +CONFIG_LORAWAN_SERVICES=y +CONFIG_LORAWAN_FRAG_TRANSPORT=y + +# Flash driver to store firmware image +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y diff --git a/tests/subsys/lorawan/frag_decoder/src/frag_encoder.c b/tests/subsys/lorawan/frag_decoder/src/frag_encoder.c new file mode 100644 index 00000000000000..a782647c22b47c --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/src/frag_encoder.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 A Labs GmbH + * Copyright (c) 2024 tado GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Implementation of the fragment encoding algorithm described in the LoRaWAN TS004-1.0.0. + * https://lora-alliance.org/wp-content/uploads/2020/11/fragmented_data_block_transport_v1.0.0.pdf + * + * Note: This algorithm is not compatible with TS004-2.0.0, which has some subtle differences + * in the parity matrix generation. + * + * Variable naming according to LoRaWAN specification: + * + * M: Number of uncoded fragments (original data) + * N: Number of coded fragments (including the original data at the beginning) + * CR: Coding ratio M/N + */ + +#include "frag_encoder.h" + +#include +#include + +LOG_MODULE_REGISTER(lorawan_frag_enc, CONFIG_LORAWAN_SERVICES_LOG_LEVEL); + +/** + * Generate a 23bit Pseudorandom Binary Sequence (PRBS) + * + * @param seed Seed input value + * + * @returns Pseudorandom output value + */ +static int32_t prbs23(int32_t seed) +{ + int32_t b0 = seed & 1; + int32_t b1 = (seed & 32) / 32; + + return (seed / 2) + ((b0 ^ b1) << 22); +} + +/** + * Generate vector for coded fragment n of the MxN parity matrix + * + * @param m Total number of uncoded fragments (M) + * @param n Coded fragment number (starting at 1 and not 0) + * @param vec Output vector (buffer size must be greater than m) + */ +void lorawan_fec_parity_matrix_vector(int m, int n, uint8_t *vec) +{ + int mm, x, r; + + memset(vec, 0, m); + + /* + * Powers of 2 must be treated differently to make sure matrix content is close + * to random. Powers of 2 tend to generate patterns. + */ + if (is_power_of_two(m)) { + mm = m + 1; + } else { + mm = m; + } + + x = 1 + (1001 * n); + + for (int nb_coeff = 0; nb_coeff < (m / 2); nb_coeff++) { + r = (1 << 16); + while (r >= m) { + x = prbs23(x); + r = x % mm; + } + vec[r] = 1; + } +} + +int lorawan_frag_encoder(const uint8_t *uncoded, size_t uncoded_len, uint8_t *coded, + size_t coded_size, size_t frag_size, unsigned int redundant_frags) +{ + int uncoded_frags = DIV_ROUND_UP(uncoded_len, frag_size); + int coded_frags = uncoded_frags + redundant_frags; + uint8_t parity_vec[frag_size]; + + memset(parity_vec, 0, sizeof(parity_vec)); + + if (coded_size < coded_frags * frag_size) { + LOG_ERR("output buffer not large enough"); + return -EINVAL; + } + + /* copy uncoded frags to the beginning of coded fragments and pad with zeros */ + memcpy(coded, uncoded, uncoded_len); + memset(coded + uncoded_len, 0, uncoded_frags * frag_size - uncoded_len); + + /* generate remaining coded (redundant) frags */ + for (int i = 1; i <= redundant_frags; i++) { + lorawan_fec_parity_matrix_vector(uncoded_frags, i, parity_vec); + + uint8_t *out = coded + (uncoded_frags + i - 1) * frag_size; + + for (int j = 0; j < uncoded_frags; j++) { + if (parity_vec[j] == 1) { + for (int m = 0; m < frag_size; m++) { + out[m] ^= coded[j * frag_size + m]; + } + } + } + } + + return 0; +} diff --git a/tests/subsys/lorawan/frag_decoder/src/frag_encoder.h b/tests/subsys/lorawan/frag_decoder/src/frag_encoder.h new file mode 100644 index 00000000000000..62c660aa27d605 --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/src/frag_encoder.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 A Labs GmbH + * Copyright (c) 2024 tado GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TEST_SUBSYS_LORAWAN_FRAG_DECODER_SRC_FRAG_ENCODER_H_ +#define TEST_SUBSYS_LORAWAN_FRAG_DECODER_SRC_FRAG_ENCODER_H_ + +#include +#include + +/** + * Generate coded binary data according to LoRaWAN TS004-1.0.0 + * + * @param uncoded Pointer to uncoded data buffer (e.g. firmware binary) + * @param uncoded_len Length of uncoded data in bytes + * @param coded Pointer to buffer for resulting coded data + * @param coded_size Size of the buffer for coded data + * @param frag_size Fragment size to be used + * @param redundant_frags Absolute number of redundant fragments to be generated + * + * @returns 0 for success or negative error code otherwise. + */ +int lorawan_frag_encoder(const uint8_t *uncoded, size_t uncoded_len, uint8_t *coded, + size_t coded_size, size_t frag_size, unsigned int redundant_frags); + +#endif /* TEST_SUBSYS_LORAWAN_FRAG_DECODER_SRC_FRAG_ENCODER_H_ */ diff --git a/tests/subsys/lorawan/frag_decoder/src/main.c b/tests/subsys/lorawan/frag_decoder/src/main.c new file mode 100644 index 00000000000000..20714c8a4b1435 --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/src/main.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024 A Labs GmbH + * Copyright (c) 2024 tado GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "frag_encoder.h" + +#define FRAG_SIZE CONFIG_LORAWAN_FRAG_TRANSPORT_MAX_FRAG_SIZE +#define FIRMWARE_SIZE (FRAG_SIZE * 100 + 1) /* not divisible by frag size to test padding */ +#define UNCODED_FRAGS (DIV_ROUND_UP(FIRMWARE_SIZE, FRAG_SIZE)) +#define REDUNDANT_FRAGS \ + (DIV_ROUND_UP(UNCODED_FRAGS * CONFIG_LORAWAN_FRAG_TRANSPORT_MAX_REDUNDANCY, 100)) +#define PADDING (UNCODED_FRAGS * FRAG_SIZE - FIRMWARE_SIZE) + +#define CMD_FRAG_SESSION_SETUP (0x02) +#define CMD_DATA_FRAGMENT (0x08) +#define FRAG_TRANSPORT_PORT (201) +#define FRAG_SESSION_INDEX (1) + +#define TARGET_IMAGE_AREA FIXED_PARTITION_ID(slot1_partition) + +/* below array would normally hold the actual firmware binary */ +static uint8_t fw_uncoded[FIRMWARE_SIZE]; + +/* enough space for redundancy of up to 100% */ +static uint8_t fw_coded[(UNCODED_FRAGS + REDUNDANT_FRAGS) * FRAG_SIZE]; + +static const struct flash_area *fa; + +static struct k_sem fuota_finished_sem; + +static void fuota_finished(void) +{ + k_sem_give(&fuota_finished_sem); +} + +ZTEST(frag_decoder, test_frag_transport) +{ + uint8_t buf[256]; /* maximum size of one LoRaWAN message */ + uint8_t frag_session_setup_req[] = { + CMD_FRAG_SESSION_SETUP, + 0x1f, + UNCODED_FRAGS & 0xFF, + (UNCODED_FRAGS >> 8) & 0xFF, + FRAG_SIZE, + 0x01, + PADDING, + 0x00, + 0x00, + 0x00, + 0x00, + }; + int ret; + + k_sem_reset(&fuota_finished_sem); + + lorawan_emul_send_downlink(FRAG_TRANSPORT_PORT, false, 0, 0, sizeof(frag_session_setup_req), + frag_session_setup_req); + + for (int i = 0; i < sizeof(fw_coded) / FRAG_SIZE; i++) { + if (i % 10 == 9) { + /* loose every 10th packet */ + continue; + } + buf[0] = CMD_DATA_FRAGMENT; + buf[1] = (i + 1) & 0xFF; + buf[2] = (FRAG_SESSION_INDEX << 6) | ((i + 1) >> 8); + memcpy(buf + 3, fw_coded + i * FRAG_SIZE, FRAG_SIZE); + lorawan_emul_send_downlink(FRAG_TRANSPORT_PORT, false, 0, 0, FRAG_SIZE + 3, buf); + } + + for (int i = 0; i < UNCODED_FRAGS; i++) { + size_t num_bytes = (i == UNCODED_FRAGS - 1) ? (FRAG_SIZE - PADDING) : FRAG_SIZE; + + flash_area_read(fa, i * FRAG_SIZE, buf, num_bytes); + zassert_mem_equal(buf, fw_coded + i * FRAG_SIZE, num_bytes, "fragment %d invalid", + i + 1); + } + + ret = k_sem_take(&fuota_finished_sem, K_MSEC(100)); + zassert_equal(ret, 0, "FUOTA finish timed out"); +} + +static void *frag_decoder_setup(void) +{ + const struct device *lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); + struct lorawan_join_config join_cfg = {0}; + int ret; + + /* populate firmware image with random data */ + sys_rand_get(fw_uncoded, sizeof(fw_uncoded)); + + /* create coded data (including redundant fragments) from firmware image */ + ret = lorawan_frag_encoder(fw_uncoded, sizeof(fw_uncoded), fw_coded, sizeof(fw_coded), + FRAG_SIZE, REDUNDANT_FRAGS); + zassert_equal(ret, 0, "creating coded data failed: %d", ret); + + k_sem_init(&fuota_finished_sem, 0, 1); + + ret = flash_area_open(TARGET_IMAGE_AREA, &fa); + zassert_equal(ret, 0, "opening flash area failed: %d", ret); + + zassert_true(device_is_ready(lora_dev), "LoRa device not ready"); + + ret = lorawan_start(); + zassert_equal(ret, 0, "lorawan_start failed: %d", ret); + + ret = lorawan_join(&join_cfg); + zassert_equal(ret, 0, "lorawan_join failed: %d", ret); + + lorawan_frag_transport_run(fuota_finished); + + return NULL; +} + +ZTEST_SUITE(frag_decoder, NULL, frag_decoder_setup, NULL, NULL, NULL); diff --git a/tests/subsys/lorawan/frag_decoder/testcase.yaml b/tests/subsys/lorawan/frag_decoder/testcase.yaml new file mode 100644 index 00000000000000..fe68bfe2957dd8 --- /dev/null +++ b/tests/subsys/lorawan/frag_decoder/testcase.yaml @@ -0,0 +1,7 @@ +common: + tags: + - lorawan +tests: + lorawan.frag_decoder: + platform_allow: + - native_sim From 5e995b10aac86d67f5ed5100886196b74f9d18d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0049/1389] samples: subsys: lorawan: fuota: add basic sample application MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add basic sample application that starts the LoRaWAN FUOTA services. Signed-off-by: Martin Jäger --- samples/subsys/lorawan/fuota/CMakeLists.txt | 9 ++ samples/subsys/lorawan/fuota/README.rst | 41 ++++++ .../lorawan/fuota/boards/nucleo_wl55jc.conf | 5 + samples/subsys/lorawan/fuota/prj.conf | 36 +++++ samples/subsys/lorawan/fuota/sample.yaml | 21 +++ samples/subsys/lorawan/fuota/src/main.c | 134 ++++++++++++++++++ samples/subsys/lorawan/fuota/sysbuild.conf | 4 + .../lorawan/fuota/sysbuild/mcuboot.conf | 4 + 8 files changed, 254 insertions(+) create mode 100644 samples/subsys/lorawan/fuota/CMakeLists.txt create mode 100644 samples/subsys/lorawan/fuota/README.rst create mode 100644 samples/subsys/lorawan/fuota/boards/nucleo_wl55jc.conf create mode 100644 samples/subsys/lorawan/fuota/prj.conf create mode 100644 samples/subsys/lorawan/fuota/sample.yaml create mode 100644 samples/subsys/lorawan/fuota/src/main.c create mode 100644 samples/subsys/lorawan/fuota/sysbuild.conf create mode 100644 samples/subsys/lorawan/fuota/sysbuild/mcuboot.conf diff --git a/samples/subsys/lorawan/fuota/CMakeLists.txt b/samples/subsys/lorawan/fuota/CMakeLists.txt new file mode 100644 index 00000000000000..44d48475bb9aa2 --- /dev/null +++ b/samples/subsys/lorawan/fuota/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lorawan_fuota) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/lorawan/fuota/README.rst b/samples/subsys/lorawan/fuota/README.rst new file mode 100644 index 00000000000000..608a9f63dcc263 --- /dev/null +++ b/samples/subsys/lorawan/fuota/README.rst @@ -0,0 +1,41 @@ +.. zephyr:code-sample:: lorawan-fuota + :name: LoRaWAN FUOTA + :relevant-api: lorawan_api + + Perform a LoRaWAN firmware-upgrade over the air (FUOTA) operation. + +Overview +******** + +An application to demonstrate firmware-upgrade over the air (FUOTA) over LoRaWAN. + +The following services specified by the LoRa Alliance are used: + +- Application Layer Clock Synchronization (`TS003-2.0.0`_) +- Remote Multicast Setup (`TS005-1.0.0`_) +- Fragmented Data Block Transport (`TS004-1.0.0`_) + +The FUOTA process is started by the application and afterwards runs in the background in its own +work queue thread. After a firmware upgrade is successfully received, the application is notified +via a callback and can reboot the device into MCUboot to apply the upgrade. + +A LoRaWAN Application Server implementing the relevant services is required for this sample to work. + +.. _`TS003-2.0.0`: https://resources.lora-alliance.org/technical-specifications/ts003-2-0-0-application-layer-clock-synchronization +.. _`TS005-1.0.0`: https://resources.lora-alliance.org/technical-specifications/lorawan-remote-multicast-setup-specification-v1-0-0 +.. _`TS004-1.0.0`: https://resources.lora-alliance.org/technical-specifications/lorawan-fragmented-data-block-transport-specification-v1-0-0 + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/subsys/lorawan/fuota` in the Zephyr tree. + +Before building the sample, make sure to select the correct region in the ``prj.conf`` file. + +The following commands build and flash the sample. + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/lorawan/fuota + :board: nucleo_wl55jc + :goals: build flash + :compact: diff --git a/samples/subsys/lorawan/fuota/boards/nucleo_wl55jc.conf b/samples/subsys/lorawan/fuota/boards/nucleo_wl55jc.conf new file mode 100644 index 00000000000000..cbc1e8478987d0 --- /dev/null +++ b/samples/subsys/lorawan/fuota/boards/nucleo_wl55jc.conf @@ -0,0 +1,5 @@ +# use fixed frag size (min and max 232 bytes) to avoid RAM overflow +CONFIG_LORAWAN_FRAG_TRANSPORT_MIN_FRAG_SIZE=232 + +# alternatively, the redundancy could be reduced +# CONFIG_LORAWAN_FRAG_TRANSPORT_MAX_REDUNDANCY=7 diff --git a/samples/subsys/lorawan/fuota/prj.conf b/samples/subsys/lorawan/fuota/prj.conf new file mode 100644 index 00000000000000..884fa8da183aa0 --- /dev/null +++ b/samples/subsys/lorawan/fuota/prj.conf @@ -0,0 +1,36 @@ +# General Zephyr settings +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +CONFIG_THREAD_NAME=y +CONFIG_LOG=y + +# LoRa PHY and required peripherals +CONFIG_LORA=y +CONFIG_SPI=y +CONFIG_GPIO=y + +# NVS required to store LoRaWAN DevNonce +CONFIG_NVS=y +CONFIG_SETTINGS=y + +# Random number generator required for several LoRaWAN services +CONFIG_ENTROPY_GENERATOR=y + +# LoRaWAN application layer +CONFIG_LORAWAN=y +CONFIG_LORAMAC_REGION_EU868=y +CONFIG_LORAWAN_NVM_SETTINGS=y + +# LoRaWAN services required for FUOTA +CONFIG_LORAWAN_SERVICES=y +CONFIG_LORAWAN_SERVICES_LOG_LEVEL_DBG=y +CONFIG_LORAWAN_APP_CLOCK_SYNC=y +CONFIG_LORAWAN_REMOTE_MULTICAST=y +CONFIG_LORAWAN_FRAG_TRANSPORT=y + +# Flash driver to store firmware image +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y diff --git a/samples/subsys/lorawan/fuota/sample.yaml b/samples/subsys/lorawan/fuota/sample.yaml new file mode 100644 index 00000000000000..1715e0ce2be916 --- /dev/null +++ b/samples/subsys/lorawan/fuota/sample.yaml @@ -0,0 +1,21 @@ +sample: + description: Demonstration of LoRaWAN Firmware Upgrade Over The Air + name: LoRaWAN FUOTA +common: + depends_on: lora + tags: lorawan + filter: dt_label_with_parent_compat_enabled("slot0_partition", "fixed-partitions") + and dt_label_with_parent_compat_enabled("slot1_partition", "fixed-partitions") + and dt_chosen_enabled("zephyr,flash-controller") and CONFIG_FLASH_HAS_DRIVER_ENABLED + harness: console + harness_config: + type: one_line + regex: + - " lorawan_fuota: Joining network over OTAA" +tests: + sample.lorawan.fuota: + integration_platforms: + - nucleo_wl55jc + # only allow selected boards which are known to have sufficient RAM for the given settings + platform_allow: + - nucleo_wl55jc diff --git a/samples/subsys/lorawan/fuota/src/main.c b/samples/subsys/lorawan/fuota/src/main.c new file mode 100644 index 00000000000000..e6254bdf4b85b6 --- /dev/null +++ b/samples/subsys/lorawan/fuota/src/main.c @@ -0,0 +1,134 @@ +/* + * LoRaWAN FUOTA sample application + * + * Copyright (c) 2022-2024 Libre Solar Technologies GmbH + * Copyright (c) 2022-2024 tado GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(lorawan_fuota, CONFIG_LORAWAN_SERVICES_LOG_LEVEL); + +/* Customize based on device configuration */ +#define LORAWAN_DEV_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +#define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +#define LORAWAN_APP_KEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + +#define DELAY K_SECONDS(180) + +char data[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}; + +static void downlink_info(uint8_t port, bool data_pending, int16_t rssi, int8_t snr, + uint8_t len, const uint8_t *data) +{ + LOG_INF("Received from port %d, pending %d, RSSI %ddB, SNR %ddBm", + port, data_pending, rssi, snr); + if (data) { + LOG_HEXDUMP_INF(data, len, "Payload: "); + } +} + +static void datarate_changed(enum lorawan_datarate dr) +{ + uint8_t unused, max_size; + + lorawan_get_payload_sizes(&unused, &max_size); + LOG_INF("New Datarate: DR %d, Max Payload %d", dr, max_size); +} + +static void fuota_finished(void) +{ + LOG_INF("FUOTA finished. Reset device to apply firmware upgrade."); + + /* + * In an actual application the firmware should be rebooted here if + * no important tasks are pending + */ +} + +int main(void) +{ + const struct device *lora_dev; + struct lorawan_join_config join_cfg; + uint8_t dev_eui[] = LORAWAN_DEV_EUI; + uint8_t join_eui[] = LORAWAN_JOIN_EUI; + uint8_t app_key[] = LORAWAN_APP_KEY; + int ret; + + struct lorawan_downlink_cb downlink_cb = { + .port = LW_RECV_PORT_ANY, + .cb = downlink_info + }; + + lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); + if (!device_is_ready(lora_dev)) { + LOG_ERR("%s: device not ready.", lora_dev->name); + return -ENODEV; + } + + ret = lorawan_start(); + if (ret < 0) { + LOG_ERR("lorawan_start failed: %d", ret); + return ret; + } + + lorawan_register_downlink_callback(&downlink_cb); + lorawan_register_dr_changed_callback(datarate_changed); + + join_cfg.mode = LORAWAN_ACT_OTAA; + join_cfg.dev_eui = dev_eui; + join_cfg.otaa.join_eui = join_eui; + join_cfg.otaa.app_key = app_key; + join_cfg.otaa.nwk_key = app_key; + + LOG_INF("Joining network over OTAA"); + ret = lorawan_join(&join_cfg); + if (ret < 0) { + LOG_ERR("lorawan_join_network failed: %d", ret); + return ret; + } + + lorawan_enable_adr(true); + + /* + * Clock synchronization is required to schedule the multicast session + * in class C mode. It can also be used independent of FUOTA. + */ + lorawan_clock_sync_run(); + + /* + * The multicast session setup service is automatically started in the + * background. It is also responsible for switching to class C at a + * specified time. + */ + + /* + * The fragmented data transport transfers the actual firmware image. + * It could also be used in a class A session, but would take very long + * in that case. + */ + lorawan_frag_transport_run(fuota_finished); + + /* + * Regular uplinks are required to open downlink slots in class A for + * FUOTA setup by the server. + */ + while (1) { + ret = lorawan_send(2, data, sizeof(data), LORAWAN_MSG_UNCONFIRMED); + if (ret == 0) { + LOG_INF("Hello World sent!"); + } else { + LOG_ERR("lorawan_send failed: %d", ret); + } + + k_sleep(DELAY); + } + + return 0; +} diff --git a/samples/subsys/lorawan/fuota/sysbuild.conf b/samples/subsys/lorawan/fuota/sysbuild.conf new file mode 100644 index 00000000000000..92042e44734f70 --- /dev/null +++ b/samples/subsys/lorawan/fuota/sysbuild.conf @@ -0,0 +1,4 @@ +# Sysbuild configuration file. + +# Enable MCUboot per default for this sample. +SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/samples/subsys/lorawan/fuota/sysbuild/mcuboot.conf b/samples/subsys/lorawan/fuota/sysbuild/mcuboot.conf new file mode 100644 index 00000000000000..c1f6021fbdb40c --- /dev/null +++ b/samples/subsys/lorawan/fuota/sysbuild/mcuboot.conf @@ -0,0 +1,4 @@ +# Kconfig changes when building sample with MCUboot using sysbuild. + +CONFIG_MCUBOOT_LOG_LEVEL_INF=y +CONFIG_MCUBOOT_IMG_MANAGER=y From 1ed0811270c0515ca039068ea6adf4cdbab88279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0050/1389] samples: subsys: lorawan: class_a: remove clock sync and multicast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These LoRaWAN services are now covered by the FUOTA sample. Signed-off-by: Martin Jäger --- samples/subsys/lorawan/class_a/README.rst | 27 ------------------- .../lorawan/class_a/overlay-clock-sync.conf | 3 --- .../lorawan/class_a/overlay-multicast.conf | 9 ------- samples/subsys/lorawan/class_a/sample.yaml | 10 ------- samples/subsys/lorawan/class_a/src/main.c | 4 --- 5 files changed, 53 deletions(-) delete mode 100644 samples/subsys/lorawan/class_a/overlay-clock-sync.conf delete mode 100644 samples/subsys/lorawan/class_a/overlay-multicast.conf diff --git a/samples/subsys/lorawan/class_a/README.rst b/samples/subsys/lorawan/class_a/README.rst index c29853ae0642aa..22d9b8f3a48207 100644 --- a/samples/subsys/lorawan/class_a/README.rst +++ b/samples/subsys/lorawan/class_a/README.rst @@ -25,30 +25,3 @@ The following commands build and flash the sample. :board: nucleo_wl55jc :goals: build flash :compact: - -Extended Configuration -********************** - -This sample can be configured to run the application-layer clock -synchronization service and/or the remote multicast setup service -in the background. - -The following commands build and flash the sample with clock synchronization -enabled. - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/lorawan/class_a - :board: nucleo_wl55jc - :goals: build flash - :gen-args: -DEXTRA_CONF_FILE=overlay-clock-sync.conf - :compact: - -The following commands build and flash the sample with remote multicast setup -enabled. - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/lorawan/class_a - :board: nucleo_wl55jc - :goals: build flash - :gen-args: -DEXTRA_CONF_FILE=overlay-multicast.conf - :compact: diff --git a/samples/subsys/lorawan/class_a/overlay-clock-sync.conf b/samples/subsys/lorawan/class_a/overlay-clock-sync.conf deleted file mode 100644 index e19b01a42a6da7..00000000000000 --- a/samples/subsys/lorawan/class_a/overlay-clock-sync.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_LORAWAN_SERVICES=y -CONFIG_LORAWAN_SERVICES_LOG_LEVEL_DBG=y -CONFIG_LORAWAN_APP_CLOCK_SYNC=y diff --git a/samples/subsys/lorawan/class_a/overlay-multicast.conf b/samples/subsys/lorawan/class_a/overlay-multicast.conf deleted file mode 100644 index 6bd5165564328b..00000000000000 --- a/samples/subsys/lorawan/class_a/overlay-multicast.conf +++ /dev/null @@ -1,9 +0,0 @@ -# NVS required to store LoRaWAN DevNonce and multicast sessions -CONFIG_NVS=y -CONFIG_SETTINGS=y -CONFIG_LORAWAN_NVM_SETTINGS=y - -CONFIG_LORAWAN_SERVICES=y -CONFIG_LORAWAN_SERVICES_LOG_LEVEL_DBG=y -CONFIG_LORAWAN_APP_CLOCK_SYNC=y -CONFIG_LORAWAN_REMOTE_MULTICAST=y diff --git a/samples/subsys/lorawan/class_a/sample.yaml b/samples/subsys/lorawan/class_a/sample.yaml index 7a757da815d993..c617ec5feb4433 100644 --- a/samples/subsys/lorawan/class_a/sample.yaml +++ b/samples/subsys/lorawan/class_a/sample.yaml @@ -44,13 +44,3 @@ tests: extra_configs: - CONFIG_LORAMAC_REGION_EU868=y - CONFIG_LORAMAC_REGION_US915=y - sample.lorawan.class_a.clock_sync: - extra_args: OVERLAY_CONFIG="overlay-clock-sync.conf" - filter: CONFIG_ENTROPY_HAS_DRIVER - integration_platforms: - - nucleo_wl55jc - sample.lorawan.class_a.multicast: - extra_args: OVERLAY_CONFIG="overlay-multicast.conf" - filter: CONFIG_ENTROPY_HAS_DRIVER - integration_platforms: - - nucleo_wl55jc diff --git a/samples/subsys/lorawan/class_a/src/main.c b/samples/subsys/lorawan/class_a/src/main.c index 76ff5529f57f45..1e31baf36e477e 100644 --- a/samples/subsys/lorawan/class_a/src/main.c +++ b/samples/subsys/lorawan/class_a/src/main.c @@ -99,10 +99,6 @@ int main(void) return 0; } -#ifdef CONFIG_LORAWAN_APP_CLOCK_SYNC - lorawan_clock_sync_run(); -#endif - LOG_INF("Sending data..."); while (1) { ret = lorawan_send(2, data, sizeof(data), From 86ad98b3df18f9ef01a2a0d827f4285b30e5e2d6 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0051/1389] Bluetooth: Coverity fix dereference before null check https://scan9.scan.coverity.com/reports.htm#v45144/p12996/fileInstanceId=132878471&defectInstanceId=9972464&mergedDefectId=330625 Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/host/att.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 2ed3dfcb76834e..df7f16c09b14a6 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -3647,22 +3647,23 @@ int bt_eatt_disconnect(struct bt_conn *conn) #if defined(CONFIG_BT_TESTING) int bt_eatt_disconnect_one(struct bt_conn *conn) { - struct bt_att_chan *chan = att_get_fixed_chan(conn); - struct bt_att *att = chan->att; - int err = -ENOTCONN; + struct bt_att *att; + struct bt_att_chan *chan; if (!conn) { return -EINVAL; } + chan = att_get_fixed_chan(conn); + att = chan->att; + SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { if (bt_att_is_enhanced(chan)) { - err = bt_l2cap_chan_disconnect(&chan->chan.chan); - return err; + return bt_l2cap_chan_disconnect(&chan->chan.chan); } } - return err; + return -ENOTCONN; } int bt_eatt_reconfigure(struct bt_conn *conn, uint16_t mtu) From bb173536ddfb6c39b1a378bc4fb036f0d7930c50 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0052/1389] Bluetooth: Coverity fix dereference before null check https://scan9.scan.coverity.com/reports.htm#v45144/p12996/fileInstanceId=132878471&defectInstanceId=9972432&mergedDefectId=330636 Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/host/att.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index df7f16c09b14a6..6c73960d979771 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -3550,6 +3550,10 @@ int bt_eatt_connect(struct bt_conn *conn, size_t num_channels) size_t i = 0; int err; + if (!conn) { + return -EINVAL; + } + /* Check the encryption level for EATT */ if (bt_conn_get_security(conn) < BT_SECURITY_L2) { /* Vol 3, Part G, Section 5.3.2 Channel Requirements states: @@ -3562,10 +3566,6 @@ int bt_eatt_connect(struct bt_conn *conn, size_t num_channels) return -EINVAL; } - if (!conn) { - return -EINVAL; - } - att_chan = att_get_fixed_chan(conn); att = att_chan->att; From cd8974fd14d754350ac8795e957841353ecdce52 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0053/1389] Bluetooth: Coverity fix untrusted value https://scan9.scan.coverity.com/reports.htm#v45144/p12996/fileInstanceId=132890129&defectInstanceId=9972487&mergedDefectId=330721 Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/host/scan.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index 5836bad2fb798a..9957d818309ee6 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -668,6 +668,19 @@ void bt_hci_le_adv_ext_report(struct net_buf *buf) reassembling_advertiser.state = FRAG_ADV_DISCARDING; } + if (evt->length > buf->len) { + LOG_WRN("Adv report corrupted (wants %u out of %u)", evt->length, buf->len); + + /* Start discarding irrespective of the `more_to_come` flag. We + * assume we may have lost a partial adv report in the truncated + * data. + */ + reassembling_advertiser.state = FRAG_ADV_DISCARDING; + net_buf_reset(buf); + + return; + } + if (reassembling_advertiser.state == FRAG_ADV_DISCARDING) { if (!more_to_come) { /* We do no longer need to keep track of this advertiser as From 41eaa82ee8b6852873f53c6e3359bdf0c663ed2b Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0054/1389] Bluetooth: Coverity fix dereference before null check https://scan9.scan.coverity.com/reports.htm#v45144/p12996/fileInstanceId=132890135&defectInstanceId=9972463&mergedDefectId=363710 Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/host/l2cap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 0b237436451440..f0f04ab796fd81 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -2031,9 +2032,13 @@ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch, { int ret; size_t sent = 0; - size_t rem_len = buf->len; + size_t rem_len; - while (buf && sent != rem_len) { + __ASSERT_NO_MSG(buf); + + rem_len = buf->len; + + while (sent != rem_len) { ret = l2cap_chan_le_send(ch, buf, 0); if (ret < 0) { LOG_DBG("failed to send buf (ch %p cid 0x%04x sent %d)", From 283b8e563fb693899f6bfbcb5afe2bf7ebfafc5c Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0055/1389] manifest: mbedtls: bump to 3.6.0 Update MbedTLS from 3.5.2 to 3.6.0. Signed-off-by: Tomi Fontanilles --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 6d879bce8e6502..9383458dd21903 100644 --- a/west.yml +++ b/west.yml @@ -277,7 +277,7 @@ manifest: revision: 2b498e6f36d6b82ae1da12c8b7742e318624ecf5 path: modules/lib/gui/lvgl - name: mbedtls - revision: 6ec4abdcda78dfc47315af568f93e5ad4398dea0 + revision: 3217c450180fd5e817601c6f479116de69e57461 path: modules/crypto/mbedtls groups: - crypto From 6d34b88589ac9cb940251362959e71ca514927f9 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0056/1389] manifest: trusted-firmware-m: adapt to MbedTLS 3.6.0 Apply patches to the current TF-M version (2.0) so that it works with the updated MbedTLS (3.6.0). Signed-off-by: Tomi Fontanilles --- submanifests/optional.yaml | 2 +- west.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index 729e543c3f13d9..1e278cc8f6da41 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -40,7 +40,7 @@ manifest: groups: - optional - name: tf-m-tests - revision: 08a3158f0623a4205608a52d880b17ae394e31d2 + revision: 85f533a4aa5b4fe31247676a923db7453eb4429c path: modules/tee/tf-m/tf-m-tests remote: upstream groups: diff --git a/west.yml b/west.yml index 9383458dd21903..aede786127037c 100644 --- a/west.yml +++ b/west.yml @@ -322,7 +322,7 @@ manifest: groups: - crypto - name: trusted-firmware-m - revision: 0b898c9b72171b0a260c0bb64a92ea4713f9e931 + revision: 785d87492490069b62170159fcf21c385f90f4eb path: modules/tee/tf-m/trusted-firmware-m groups: - tee From ad13a4821f58938d704e90e7c70e91b2051c849d Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0057/1389] manifest: mcuboot: apply fix for MbedTLS 3.6.0 Fixes issues with MbedTLS's check_config.h. Signed-off-by: Tomi Fontanilles --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index aede786127037c..2dfce2b26ee286 100644 --- a/west.yml +++ b/west.yml @@ -282,7 +282,7 @@ manifest: groups: - crypto - name: mcuboot - revision: 78bfe750cde0f8dfcf81bb4c0a68243d45906def + revision: d4394c2f9b76e0a7b758441cea3a8ceb896f66c8 path: bootloader/mcuboot - name: mipi-sys-t path: modules/debug/mipi-sys-t From 3cf921b31138b83df24d92908d9a1d9f86da5624 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:25 +0200 Subject: [PATCH 0058/1389] modules: mbedtls: fix RSA's dependency on ASN1 With MbedTLS updated to 3.6.0 the RSA module does not depend on PK anymore. However, it is now dependent on ASN1. Signed-off-by: Tomi Fontanilles --- modules/mbedtls/configs/config-tls-generic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index eeb15571e42725..a6527f8166f5d7 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -429,11 +429,11 @@ #define MBEDTLS_PK_C #endif -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_ECDSA_C) || defined(MBEDTLS_RSA_C) || defined(MBEDTLS_X509_USE_C) #define MBEDTLS_ASN1_PARSE_C #endif -#if defined(MBEDTLS_ECDSA_C) || defined(MBEDTLS_PK_WRITE_C) +#if defined(MBEDTLS_ECDSA_C) || defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_WRITE_C) #define MBEDTLS_ASN1_WRITE_C #endif From ba3e773206f15f9fcb5c1aca1e6bbcafd258c2dd Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0059/1389] modules: mbedtls: force NS-side config to client-only when using TF-M When building with TF-M (CONFIG_BUILD_WITH_TFM), force MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C so that no NS code tries to act like the MbedTLS core is built on this side. This fixes compilation errors in (at least) interface/src/tfm_crypto_api.c after the update of MbedTLS to 3.6.0. Signed-off-by: Tomi Fontanilles --- modules/mbedtls/configs/config-tls-generic.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index a6527f8166f5d7..b852e42818fe40 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -495,4 +495,9 @@ #include CONFIG_MBEDTLS_USER_CONFIG_FILE #endif +#if defined(CONFIG_BUILD_WITH_TFM) +#define MBEDTLS_PSA_CRYPTO_CLIENT +#undef MBEDTLS_PSA_CRYPTO_C +#endif /* CONFIG_BUILD_WITH_TFM */ + #endif /* MBEDTLS_CONFIG_H */ From 71d8f412a524cbc87313ce5421917961e3f2fe96 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0060/1389] modules: tf-m: fix tfm_api's configuration of MbedTLS The configuration file was not passed down to tfm_api, which made the compilation of (at least) interface/src/tfm_crypto_api.c fail when updating MbedTLS to 3.6.0. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index d570727a964ed5..7502b0a71ebb87 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -366,6 +366,11 @@ if (CONFIG_BUILD_WITH_TFM) target_include_directories(tfm_api PRIVATE ${TFM_INTERFACE_INCLUDE_DIR} ${TFM_INTERFACE_INCLUDE_DIR}/crypto_keys + ${ZEPHYR_BASE}/modules/mbedtls/configs + ) + # Pass down the MbedTLS configuration file to use. + target_compile_definitions(tfm_api PRIVATE + MBEDTLS_CONFIG_FILE="${CONFIG_MBEDTLS_CFG_FILE}" ) zephyr_library_link_libraries( From 078f8f2cc32e2aa1b987769eb3840570f6af7c9c Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0061/1389] modules: tf-m: make CONFIG_BUILD_WITH_TFM imply CONFIG_MBEDTLS This fixes NS compilation on certain app/board combinations where TF-M is used but CONFIG_MBEDTLS was not set to y. With the update to MbedTLS 3.6.0, the compilation failed in (at least) interface/src/tfm_crypto_api.c when trying to include MbedTLS configuration file because the MbedTLS Kconfigs were not defined due to CONFIG_MBEDTLS being n (and the default MbedTLS configuration file not being found). TF-M's dependency on MbedTLS is pretty much a given. This change ensures that the configuration for MbedTLS is properly defined at all times when TF-M is in use. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/Kconfig.tfm | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 171ad6543078d3..1c11a997cf7ff9 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -32,6 +32,7 @@ menuconfig BUILD_WITH_TFM select BUILD_OUTPUT_HEX imply INIT_ARCH_HW_AT_BOOT imply ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS + imply MBEDTLS help When enabled, this option instructs the Zephyr build process to additionally generate a TF-M image for the Secure Execution From 822a853a8bdd5ae656eaf02aceb65fa574f4de4f Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0062/1389] samples: tfm_secure_partition: fix build of the ARoT With the update of MbedTLS to 3.6.0 the configuration files (mbedtls/mbedtls_config.h, psa/crypto_config.h) are not found anymore by default. Make the ARoT's CMake target inherit from psa_crypto_config; it defines what is needed to find the MbedTLS configuration files. Signed-off-by: Tomi Fontanilles --- .../tfm_secure_partition/dummy_partition/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt b/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt index 013332ccb1a0e9..fdb08e81ddbd03 100644 --- a/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt +++ b/samples/tfm_integration/tfm_secure_partition/dummy_partition/CMakeLists.txt @@ -36,6 +36,7 @@ target_link_libraries(tfm_app_rot_partition_dp PRIVATE platform_s tfm_sprt + psa_crypto_config ) target_link_libraries(tfm_spm From b9e70a6ebf3b68541f04439076f21a94e10f21f7 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0063/1389] drivers: entropy: fix TF-M enabled build with MbedTLS 3.6.0 This fixes the compilation of entropy_psa_crypto.c that failed when trying to include the MbedTLS configuration. Inherit the needed include folders and definitions from tfm_api. Signed-off-by: Tomi Fontanilles --- drivers/entropy/CMakeLists.txt | 6 +----- modules/trusted-firmware-m/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/entropy/CMakeLists.txt b/drivers/entropy/CMakeLists.txt index c3d37e1461a0e2..80d9c28d0e63c3 100644 --- a/drivers/entropy/CMakeLists.txt +++ b/drivers/entropy/CMakeLists.txt @@ -34,8 +34,4 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_GECKO_SE entropy_gecko_se. zephyr_library_sources_ifdef(CONFIG_ENTROPY_PSA_CRYPTO_RNG entropy_psa_crypto.c) zephyr_library_sources_ifdef(CONFIG_ENTROPY_NPCX_DRBG entropy_npcx_drbg.c) -if (CONFIG_BUILD_WITH_TFM) - target_include_directories(${ZEPHYR_CURRENT_LIBRARY} PRIVATE - $/api_ns/interface/include - ) -endif() +zephyr_library_link_libraries_ifdef(CONFIG_BUILD_WITH_TFM tfm_api) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 7502b0a71ebb87..6dde3956c15f6a 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -363,13 +363,13 @@ if (CONFIG_BUILD_WITH_TFM) zephyr_library_sources_ifdef(CONFIG_TFM_PARTITION_PLATFORM ${TFM_INTERFACE_SOURCE_DIR}/tfm_ioctl_core_ns_api.c) endif() - target_include_directories(tfm_api PRIVATE + target_include_directories(tfm_api PUBLIC ${TFM_INTERFACE_INCLUDE_DIR} ${TFM_INTERFACE_INCLUDE_DIR}/crypto_keys ${ZEPHYR_BASE}/modules/mbedtls/configs ) # Pass down the MbedTLS configuration file to use. - target_compile_definitions(tfm_api PRIVATE + target_compile_definitions(tfm_api PUBLIC MBEDTLS_CONFIG_FILE="${CONFIG_MBEDTLS_CFG_FILE}" ) From a5396d353fcb0f694587bb732ee129d0bd3970f8 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0064/1389] MAINTAINERS: Update Renesas maintainers Update maintainers for Renesas code to Renesas employees. Add @ioannis-karachalios as maintainer for Renesas SmartBond code. Add @KhiemNguyenT as maintainer for Renesas HAL. Signed-off-by: Andrzej Kaczmarek --- MAINTAINERS.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index ee64c0ea6403ef..e20c8ef4d894da 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3483,6 +3483,7 @@ nRF Platforms: Renesas SmartBond Platforms: status: maintained maintainers: + - ioannis-karachalios - andrzej-kaczmarek - blauret files: @@ -4345,6 +4346,7 @@ West: "West project: hal_renesas": status: maintained maintainers: + - KhiemNguyenT - andrzej-kaczmarek files: [] labels: From ae158fa005743404171a6161d09208cef2b62be8 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0065/1389] native_simulator: Rework fuzzing support The fuzzing support in the native_simulator had not got to work yet. Let's remove it, and instead let the test application handle it. For this we make public the functions which initialize the simulation and advance time, so the fuzzing tests can use it. Signed-off-by: Alberto Escolar Piedras --- .../common/src/include/nsi_main_semipublic.h | 36 ++++++++++++++ scripts/native_simulator/common/src/main.c | 47 ++++--------------- 2 files changed, 44 insertions(+), 39 deletions(-) create mode 100644 scripts/native_simulator/common/src/include/nsi_main_semipublic.h diff --git a/scripts/native_simulator/common/src/include/nsi_main_semipublic.h b/scripts/native_simulator/common/src/include/nsi_main_semipublic.h new file mode 100644 index 00000000000000..12486e392bedb4 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_main_semipublic.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_MAIN_SEMIPUBLIC_H +#define NSI_COMMON_SRC_INCL_NSI_MAIN_SEMIPUBLIC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These APIs are exposed for special use cases in which a developer needs to + * replace the native simulator main loop. + * An example of such a case is LLVMs fuzzing support. For this one sets + * NSI_NO_MAIN, and provides an specialized main() or hooks into the tooling + * provided main(). + * + * These APIs should be used with care, and not be used when the native + * simulator main() is built in. + * + * Check nsi_main.c for more information. + */ + +void nsi_init(int argc, char *argv[]); +void nsi_exec_for(uint64_t us); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_MAIN_SEMIPUBLIC_H */ diff --git a/scripts/native_simulator/common/src/main.c b/scripts/native_simulator/common/src/main.c index 9b5c566fae0635..34b4876a7e8bf2 100644 --- a/scripts/native_simulator/common/src/main.c +++ b/scripts/native_simulator/common/src/main.c @@ -52,9 +52,11 @@ NSI_FUNC_NORETURN void nsi_exit(int exit_code) /** * Run all early native simulator initialization steps, including command * line parsing and CPU start, until we are ready to let the HW models - * run via hwm_one_event() + * run via nsi_hws_one_event() + * + * Note: This API should normally only be called by the native simulator main() */ -static void nsi_init(int argc, char *argv[]) +void nsi_init(int argc, char *argv[]) { /* * Let's ensure that even if we are redirecting to a file, we get stdout @@ -92,6 +94,8 @@ static void nsi_init(int argc, char *argv[]) * return. Note that this does not affect event timing, so the "next * event" may be significantly after the request if the hardware has * not been configured to e.g. send an interrupt when expected. + * + * Note: This API should normally only be called by the native simulator main() */ void nsi_exec_for(uint64_t us) { @@ -102,7 +106,7 @@ void nsi_exec_for(uint64_t us) } while (nsi_hws_get_time() < (start + us)); } -#ifndef NSI_LIBFUZZER +#ifndef NSI_NO_MAIN /** * @@ -121,39 +125,4 @@ int main(int argc, char *argv[]) return 1; /* LCOV_EXCL_LINE */ } -#else /* NSI_LIBFUZZER */ - -/** - * Entry point for fuzzing (when enabled). Works by placing the data - * into two known symbols, triggering an app-visible interrupt, and - * then letting the simulator run for a fixed amount of time (intended to be - * "long enough" to handle the event and reach a quiescent state - * again) - */ -uint8_t *nsi_fuzz_buf, nsi_fuzz_sz; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) -{ - static bool nsi_initialized; - - if (!nsi_initialized) { - nsi_init(0, NULL); - nsi_initialized = true; - } - - /* Provide the fuzz data to the embedded OS as an interrupt, with - * "DMA-like" data placed into nsi_fuzz_buf/sz - */ - nsi_fuzz_buf = (void *)data; - nsi_fuzz_sz = sz; - hw_irq_ctrl_set_irq(NSI_FUZZ_IRQ); - - /* Give the OS time to process whatever happened in that - * interrupt and reach an idle state. - */ - nsi_exec_for(NSI_FUZZ_TIME); - - return 0; -} - -#endif /* NSI_LIBFUZZER */ +#endif /* NSI_NO_MAIN */ From c60b4cfe1f5a305165782aa9a11814db3b60f802 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0066/1389] sample fuzzer: Move fuzzer specific code to sample and fix for native_sim Move the LLVM fuzzing specific code out of the board main file and into the sample. That way we avoid needing to duplicate it for native_sim and avoid having a very adhoc interface between the fuzzer test and runner code. Also ensure it works for native_sim and not just native_posix Signed-off-by: Alberto Escolar Piedras --- arch/posix/CMakeLists.txt | 1 + boards/native/native_posix/main.c | 36 ------------------- samples/subsys/debug/fuzz/src/main.c | 54 ++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/arch/posix/CMakeLists.txt b/arch/posix/CMakeLists.txt index 74a0c9e2617009..8dfc696bc6d5f9 100644 --- a/arch/posix/CMakeLists.txt +++ b/arch/posix/CMakeLists.txt @@ -178,6 +178,7 @@ endif() if(CONFIG_ARCH_POSIX_LIBFUZZER) list(APPEND LLVM_SANITIZERS "fuzzer") + target_compile_options(native_simulator INTERFACE "-DNSI_NO_MAIN=1") if(NOT CONFIG_64BIT) # On i386, libfuzzer seems to dynamically relocate the binary, so # we need to emit PIC code. This limitation is undocumented and diff --git a/boards/native/native_posix/main.c b/boards/native/native_posix/main.c index 5e603ac6efdf95..f68f4dbf0e38b5 100644 --- a/boards/native/native_posix/main.c +++ b/boards/native/native_posix/main.c @@ -118,40 +118,4 @@ int main(int argc, char *argv[]) return 1; /* LCOV_EXCL_LINE */ } -#else /* CONFIG_ARCH_POSIX_LIBFUZZER */ - -const uint8_t *posix_fuzz_buf; -size_t posix_fuzz_sz; - -/** - * Entry point for fuzzing (when enabled). Works by placing the data - * into two known symbols, triggering an app-visible interrupt, and - * then letting the OS run for a fixed amount of time (intended to be - * "long enough" to handle the event and reach a quiescent state - * again) - */ -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) -{ - static bool posix_initialized; - - if (!posix_initialized) { - posix_init(0, NULL); - posix_initialized = true; - } - - /* Provide the fuzz data to Zephyr as an interrupt, with - * "DMA-like" data placed into posix_fuzz_buf/sz - */ - posix_fuzz_buf = data; - posix_fuzz_sz = sz; - hw_irq_ctrl_set_irq(CONFIG_ARCH_POSIX_FUZZ_IRQ); - - /* Give the OS time to process whatever happened in that - * interrupt and reach an idle state. - */ - posix_exec_for(k_ticks_to_us_ceil64(CONFIG_ARCH_POSIX_FUZZ_TICKS)); - - return 0; -} - #endif diff --git a/samples/subsys/debug/fuzz/src/main.c b/samples/subsys/debug/fuzz/src/main.c index ae486e9389479a..9d32301fb4a524 100644 --- a/samples/subsys/debug/fuzz/src/main.c +++ b/samples/subsys/debug/fuzz/src/main.c @@ -4,6 +4,19 @@ #include #include #include +#include +#if defined(CONFIG_BOARD_NATIVE_SIM) +#include +#include +#elif defined(CONFIG_BOARD_NATIVE_POSIX) +/* Note: native_posix will be deprecated soon */ +extern void posix_init(int argc, char *argv[]); +extern void posix_exec_for(uint64_t us); +#define nsi_init posix_init +#define nsi_exec_for posix_exec_for +#else +#error "Platform not supported" +#endif /* Fuzz testing is coverage-based, so we want to hide a failure case * (a write through a null pointer in this case) down inside a call @@ -49,8 +62,8 @@ GEN_CHECK(5, 6) GEN_CHECK(6, 0) /* Fuzz input received from LLVM via "interrupt" */ -extern const uint8_t *posix_fuzz_buf; -extern size_t posix_fuzz_sz; +static const uint8_t *fuzz_buf; +static size_t fuzz_sz; K_SEM_DEFINE(fuzz_sem, 0, K_SEM_MAX_LIMIT); @@ -76,7 +89,42 @@ int main(void) /* Execute the fuzz case we got from LLVM and passed * through an interrupt to this thread. */ - check0(posix_fuzz_buf, posix_fuzz_sz); + check0(fuzz_buf, fuzz_sz); } return 0; } + +/** + * Entry point for fuzzing. Works by placing the data + * into two known symbols, triggering an app-visible interrupt, and + * then letting the simulator run for a fixed amount of time (intended to be + * "long enough" to handle the event and reach a quiescent state + * again) + */ +#if defined(CONFIG_BOARD_NATIVE_SIM) +NATIVE_SIMULATOR_IF /* We expose this function to the final runner link stage*/ +#endif +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) +{ + static bool runner_initialized; + + if (!runner_initialized) { + nsi_init(0, NULL); + runner_initialized = true; + } + + /* Provide the fuzz data to the embedded OS as an interrupt, with + * "DMA-like" data placed into native_fuzz_buf/sz + */ + fuzz_buf = (void *)data; + fuzz_sz = sz; + + hw_irq_ctrl_set_irq(CONFIG_ARCH_POSIX_FUZZ_IRQ); + + /* Give the OS time to process whatever happened in that + * interrupt and reach an idle state. + */ + nsi_exec_for(k_ticks_to_us_ceil64(CONFIG_ARCH_POSIX_FUZZ_TICKS)); + + return 0; +} From 71ad75ee0c4904d76dc5da5cc4feaca0e457717d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0067/1389] samples fuzzer: Update README as it works on native_sim too Update the readme as the sample works on native_sim, and native_posix will be deprecated soon. Signed-off-by: Alberto Escolar Piedras --- samples/subsys/debug/fuzz/README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/subsys/debug/fuzz/README.rst b/samples/subsys/debug/fuzz/README.rst index 126594436a3d12..0ee086c4493c04 100644 --- a/samples/subsys/debug/fuzz/README.rst +++ b/samples/subsys/debug/fuzz/README.rst @@ -24,7 +24,7 @@ toolchain is installed in your host environment, and build with: Thread model: posix InstalledDir: /usr/bin $ export ZEPHYR_TOOLCHAIN_VARIANT=llvm - $ west build -t run -b native_posix/native/64 samples/subsys/debug/fuzz + $ west build -t run -b native_sim/native/64 samples/subsys/debug/fuzz Over 10-20 seconds or so (runtimes can be quite variable) you will see it discover and recurse deeper into the test's deliberately @@ -43,7 +43,7 @@ Example output: INFO: Loaded 1 PC tables (2112 PCs): 2112 [0x55cbe336f498,0x55cbe3377898), INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes *** Booting Zephyr OS build zephyr-v3.1.0-3976-g806034e02865 *** - Hello World! native_posix/native/64 + Hello World! native_sim/native/64 INFO: A corpus is not provided, starting from an empty corpus #2 INITED cov: 101 ft: 102 corp: 1/1b exec/s: 0 rss: 30Mb # From 8e9d524445516ffc7b748ad9731085ab64c7445f Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0068/1389] arch posix: Correct ARCH_POSIX_LIBFUZZER kconfig help message This option can be used now also with native_sim and seems to work fine with both 32 and 64 bit targets. Signed-off-by: Alberto Escolar Piedras --- arch/posix/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/posix/Kconfig b/arch/posix/Kconfig index a31e1349b21f47..77b781a8c9d9ef 100644 --- a/arch/posix/Kconfig +++ b/arch/posix/Kconfig @@ -27,7 +27,7 @@ menuconfig ARCH_POSIX_LIBFUZZER help Build the posix app as a LLVM libfuzzer target. Requires support from the toolchain (currently only clang works, and - only on native_posix/native/64), and should normally be used in + only on native_{posix,sim}[//64]), and should normally be used in concert with some of CONFIG_ASAN/UBSAN/MSAN for validation. The application needs to implement the LLVMFuzzerTestOneInput() entry point, which runs in the host From 3548b1a4473ea445088942325ffcdc1b6bc4d300 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0069/1389] arch posix fuzzing: Move kconfig options to sample Move the kconfig options used to configure the interrupt and wait time to the sample which uses them instead of having them in the architecture code. This options are very particular for this sample and not really an API. Signed-off-by: Alberto Escolar Piedras --- arch/posix/Kconfig | 26 ++------------------------ samples/subsys/debug/fuzz/Kconfig | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 samples/subsys/debug/fuzz/Kconfig diff --git a/arch/posix/Kconfig b/arch/posix/Kconfig index 77b781a8c9d9ef..1ed79b38976d82 100644 --- a/arch/posix/Kconfig +++ b/arch/posix/Kconfig @@ -22,10 +22,10 @@ config ARCH_POSIX_RECOMMENDED_STACK_SIZE thread stack, the real stack is the native underlying pthread stack. Therefore the allocated stack can be limited to this size) -menuconfig ARCH_POSIX_LIBFUZZER +config ARCH_POSIX_LIBFUZZER bool "Build fuzz test target" help - Build the posix app as a LLVM libfuzzer target. Requires + Build as an LLVM libfuzzer target. Requires support from the toolchain (currently only clang works, and only on native_{posix,sim}[//64]), and should normally be used in concert with some of CONFIG_ASAN/UBSAN/MSAN for validation. @@ -35,28 +35,6 @@ menuconfig ARCH_POSIX_LIBFUZZER sample and https://llvm.org/docs/LibFuzzer.html for more information. -if ARCH_POSIX_LIBFUZZER - -config ARCH_POSIX_FUZZ_IRQ - int "OS interrupt via which to deliver fuzz cases" - default 3 - help - When using libfuzzer, new fuzz cases are delivered to Zephyr - via interrupts. The IRQ should be otherwise unused, but can - be any value desired by the app. - -config ARCH_POSIX_FUZZ_TICKS - int "Ticks to allow for fuzz case processing" - default 2 - help - Fuzz interrupts are delivered, from the perspective of the - OS, at a steady cadence in simulated time. In general most - apps won't require much time to reach an idle state - following a unit-test style case, so the default is short to - prevent interaction with regular timer workloads. - -endif # CONFIG_ARCH_POSIX_LIBFUZZER - config ARCH_POSIX_TRAP_ON_FATAL bool "Raise a SIGTRAP on fatal error" help diff --git a/samples/subsys/debug/fuzz/Kconfig b/samples/subsys/debug/fuzz/Kconfig new file mode 100644 index 00000000000000..f4917b7e59b205 --- /dev/null +++ b/samples/subsys/debug/fuzz/Kconfig @@ -0,0 +1,22 @@ +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config ARCH_POSIX_FUZZ_IRQ + int "OS interrupt via which to deliver fuzz cases" + default 31 + help + In this sample, new fuzz cases are delivered to Zephyr + via interrupts. The IRQ should be otherwise unused, but can + be any value desired by the app. + +config ARCH_POSIX_FUZZ_TICKS + int "Ticks to allow for fuzz case processing" + default 2 + help + Fuzz interrupts are delivered, from the perspective of the + OS, at a steady cadence in simulated time. In general most + apps won't require much time to reach an idle state + following a unit-test style case, so the default is short to + prevent interaction with regular timer workloads. + +source "Kconfig.zephyr" From 7f3a9c72facd7e419b0af2f92e890aa8994335fa Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0070/1389] release note/migration guide: Mention fuzzing changes The fuzzing support only worked when targetting the native_posix board, and in a way which was very coupled with the fuzzing sample. This has now been refactored, so those who may have relied on hooking to the board in the same way as this sample will need to adapt. Signed-off-by: Alberto Escolar Piedras --- doc/releases/migration-guide-3.7.rst | 6 ++++++ doc/releases/release-notes-3.7.rst | 2 ++ 2 files changed, 8 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 022a8699ee9c2b..a344a3106fe738 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -343,5 +343,11 @@ Architectures are deprecated. Use :kconfig:option:`CONFIG_X86_DISABLE_SSBD` and :kconfig:option:`CONFIG_X86_ENABLE_EXTENDED_IBRS` instead. +* POSIX arch: + + * LLVM fuzzing support has been refactored. A test application now needs to provide its own + ``LLVMFuzzerTestOneInput()`` hook instead of relying on a board provided one. Check + ``samples/subsys/debug/fuzz/`` for an example. + Xtensa ====== diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index adbd2071b71850..814b4847358546 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -90,6 +90,8 @@ Boards & SoC Support * Made these changes for native/POSIX boards: + * LLVM fuzzing support has been refactored while adding support for it in native_sim. + * Added support for these following shields: Build system and Infrastructure From a23b0d6590c71053d9a90807166c3a1ca97f5cdb Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0071/1389] ipc_rpmsg_static_vrings: use names for WQ threads This patch adds names to the threads created by `mbox_init` via `k_work_queue_start`. The name of the thread is the same as the name in the device instance. The main reason for this has to do with how `mcumgr` reports [thread information](https://docs.zephyrproject.org/latest/services/device_mgmt/smp_groups/smp_group_0.html#task-statistics-command). Specifically, data about threads is sent in a CBOR encoded map where the map keys are the thread names (at least in the default configuration). If there's more than one IPC channel defined (one example of this being `samples/subsys/logging/multidomain`), both threads would be created with an empty name and `mcumgr` will only return the data associated with the thread created by the last call to `mbox_init`. Signed-off-by: Bogdan Marinescu --- subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c index 24653585202b1a..a2c0883c054693 100644 --- a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c +++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c @@ -325,13 +325,14 @@ static int mbox_init(const struct device *instance) { const struct backend_config_t *conf = instance->config; struct backend_data_t *data = instance->data; + struct k_work_queue_config wq_cfg = {.name = instance->name}; int prio, err; prio = (conf->wq_prio_type == PRIO_COOP) ? K_PRIO_COOP(conf->wq_prio) : K_PRIO_PREEMPT(conf->wq_prio); k_work_queue_init(&data->mbox_wq); - k_work_queue_start(&data->mbox_wq, mbox_stack[conf->id], WQ_STACK_SIZE, prio, NULL); + k_work_queue_start(&data->mbox_wq, mbox_stack[conf->id], WQ_STACK_SIZE, prio, &wq_cfg); if (IS_ENABLED(CONFIG_THREAD_NAME)) { char name[THREAD_MAX_NAME_LEN]; From cb421d10d9e95277f5e00f98aa90360c9ca75a79 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:26 +0200 Subject: [PATCH 0072/1389] tests/kernel: Bump kobj thread bitmask size for a few tests A scheduler fix for free memory usage on aborted threads is now using a per-CPU dummy thread instead of a single stack-based one at startup. These static thread objects need spots in the kobj bitmasks, and a few tests are sitting right at the default limit (16 threads). Signed-off-by: Andy Ross --- samples/net/sockets/echo_client/prj.conf | 1 + tests/kernel/common/prj.conf | 1 + tests/kernel/semaphore/semaphore/prj.conf | 1 + tests/kernel/semaphore/sys_sem/prj.conf | 1 + 4 files changed, 4 insertions(+) diff --git a/samples/net/sockets/echo_client/prj.conf b/samples/net/sockets/echo_client/prj.conf index 7965c86f2ec08c..f73510d861e3bd 100644 --- a/samples/net/sockets/echo_client/prj.conf +++ b/samples/net/sockets/echo_client/prj.conf @@ -15,6 +15,7 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_INIT_STACKS=y +CONFIG_MAX_THREAD_BYTES=3 # Logging CONFIG_NET_LOG=y diff --git a/tests/kernel/common/prj.conf b/tests/kernel/common/prj.conf index eb2a4d4ccd8cfe..53115b18cfa0e0 100644 --- a/tests/kernel/common/prj.conf +++ b/tests/kernel/common/prj.conf @@ -6,3 +6,4 @@ CONFIG_BOOT_DELAY=500 CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_BOUNDS_CHECK_BYPASS_MITIGATION=y +CONFIG_MAX_THREAD_BYTES=3 diff --git a/tests/kernel/semaphore/semaphore/prj.conf b/tests/kernel/semaphore/semaphore/prj.conf index a8b0a3e4d25ab7..e193f5f626dd2a 100644 --- a/tests/kernel/semaphore/semaphore/prj.conf +++ b/tests/kernel/semaphore/semaphore/prj.conf @@ -3,3 +3,4 @@ CONFIG_IRQ_OFFLOAD=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y CONFIG_PIPES=y +CONFIG_MAX_THREAD_BYTES=3 diff --git a/tests/kernel/semaphore/sys_sem/prj.conf b/tests/kernel/semaphore/sys_sem/prj.conf index 869fd338e6afd7..e9e323077453d8 100644 --- a/tests/kernel/semaphore/sys_sem/prj.conf +++ b/tests/kernel/semaphore/sys_sem/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MAX_THREAD_BYTES=3 From 382e8f38c3ffea9273634b78e4638e75ebcd0a4e Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0073/1389] kernel/spinlock: Fix SPIN_VALIDATE in ISRs Spinlocks taken in ISRs were storing the _current thread pointer of the interrupted thread as the owner, which was never strictly correct but was benign as the thread would never run until the lock was released. But now k_thread_abort(_current) in an ISR has been fixed to eliminate all references to the (now aborted) thread struct, and _current points to a dummy thread. Handle that edge case in the validation framework. Signed-off-by: Andy Ross --- kernel/spinlock_validate.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/spinlock_validate.c b/kernel/spinlock_validate.c index 90da6fac1b68aa..cb7ff5a3e7ff7a 100644 --- a/kernel/spinlock_validate.c +++ b/kernel/spinlock_validate.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include bool z_spin_lock_valid(struct k_spinlock *l) @@ -20,10 +20,17 @@ bool z_spin_lock_valid(struct k_spinlock *l) bool z_spin_unlock_valid(struct k_spinlock *l) { - if (l->thread_cpu != (_current_cpu->id | (uintptr_t)_current)) { + uintptr_t tcpu = l->thread_cpu; + + l->thread_cpu = 0; + + if (arch_is_in_isr() && _current->base.thread_state & _THREAD_DUMMY) { + /* Edge case where an ISR aborted _current */ + return true; + } + if (tcpu != (_current_cpu->id | (uintptr_t)_current)) { return false; } - l->thread_cpu = 0; return true; } From 39f1ee20af5212c9d1684ec39051a971c11769ee Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0074/1389] kernel/sched: Fix free-memory write when ISRs abort _current After a k_thread_abort(), the resulting thread struct is documented as unused/free memory that may be re-used (for example, to respawn a new thread). But in the special case of aborting the current thread from within an ISR, that wasn't quite happening. The scheduler cleanup would complete, but the architecture layer would still try to context switch away from the aborted thread on exit, and that can include writes to the now-reused thread struct! The specifics will depend on architecture (some do a full context save on entry, most don't), but in the case of USE_SWITCH=y it will at the very least write the switch_handle field. Fix this simply, with a per-cpu "switch dummy" thread struct for use as a target for context switches like this. There is some non-trivial memory cost to that; thread structs on many architectures are large. Pleasingly, this also addresses a known deadlock on SMP: because the "spin in ISR" step now happens as the very last stage of k_thread_abort() handling, the existing scheduler lock works to serialize calls such that it's impossible for a cycle of threads to independently decide to spin on each other: at least one will see itself as "already aborting" and break the cycle. Fixes #64646 Signed-off-by: Andy Ross --- kernel/include/ksched.h | 2 ++ kernel/init.c | 7 +------ kernel/sched.c | 44 +++++++++++++++++++++++++++++++++++------ kernel/smp.c | 3 +-- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/kernel/include/ksched.h b/kernel/include/ksched.h index 2943ee1e612109..dff2717702234f 100644 --- a/kernel/include/ksched.h +++ b/kernel/include/ksched.h @@ -37,6 +37,8 @@ BUILD_ASSERT(K_LOWEST_APPLICATION_THREAD_PRIO #define Z_ASSERT_VALID_PRIO(prio, entry_point) __ASSERT((prio) == -1, "") #endif /* CONFIG_MULTITHREADING */ +extern struct k_thread _thread_dummies[CONFIG_MP_MAX_NUM_CPUS]; + void z_sched_init(void); void z_move_thread_to_end_of_prio_q(struct k_thread *thread); void z_unpend_thread_no_timeout(struct k_thread *thread); diff --git a/kernel/init.c b/kernel/init.c index 54b34dce5e9288..f6edb54f5a9e99 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -650,12 +650,7 @@ FUNC_NORETURN void z_cstart(void) LOG_CORE_INIT(); #if defined(CONFIG_MULTITHREADING) - /* Note: The z_ready_thread() call in prepare_multithreading() requires - * a dummy thread even if CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN=y - */ - struct k_thread dummy_thread; - - z_dummy_thread_init(&dummy_thread); + z_dummy_thread_init(&_thread_dummies[0]); #endif /* CONFIG_MULTITHREADING */ /* do any necessary initialization of static devices */ z_device_state_init(); diff --git a/kernel/sched.c b/kernel/sched.c index 390a7efe8c5f3d..00d0efdb4db356 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -30,6 +30,11 @@ extern struct k_thread *pending_current; struct k_spinlock _sched_spinlock; +/* Storage to "complete" the context switch from an invalid/incomplete thread + * context (ex: exiting an ISR that aborted _current) + */ +__incoherent struct k_thread _thread_dummies[CONFIG_MP_MAX_NUM_CPUS]; + static void update_cache(int preempt_ok); static void halt_thread(struct k_thread *thread, uint8_t new_state); static void add_to_waitq_locked(struct k_thread *thread, _wait_q_t *wait_q); @@ -423,8 +428,9 @@ void z_sched_start(struct k_thread *thread) * another CPU to catch the IPI we sent and halt. Note that we check * for ourselves being asynchronously halted first to prevent simple * deadlocks (but not complex ones involving cycles of 3+ threads!). + * Acts to release the provided lock before returning. */ -static k_spinlock_key_t thread_halt_spin(struct k_thread *thread, k_spinlock_key_t key) +static void thread_halt_spin(struct k_thread *thread, k_spinlock_key_t key) { if (is_halting(_current)) { halt_thread(_current, @@ -432,10 +438,11 @@ static k_spinlock_key_t thread_halt_spin(struct k_thread *thread, k_spinlock_key } k_spin_unlock(&_sched_spinlock, key); while (is_halting(thread)) { + unsigned int k = arch_irq_lock(); + + arch_spin_relax(); /* Requires interrupts be masked */ + arch_irq_unlock(k); } - key = k_spin_lock(&_sched_spinlock); - z_sched_switch_spin(thread); - return key; } /* Shared handler for k_thread_{suspend,abort}(). Called with the @@ -465,8 +472,7 @@ static void z_thread_halt(struct k_thread *thread, k_spinlock_key_t key, arch_sched_ipi(); #endif if (arch_is_in_isr()) { - key = thread_halt_spin(thread, key); - k_spin_unlock(&_sched_spinlock, key); + thread_halt_spin(thread, key); } else { add_to_waitq_locked(_current, wq); z_swap(&_sched_spinlock, key); @@ -480,6 +486,10 @@ static void z_thread_halt(struct k_thread *thread, k_spinlock_key_t key, k_spin_unlock(&_sched_spinlock, key); } } + /* NOTE: the scheduler lock has been released. Don't put + * logic here, it's likely to be racy/deadlocky even if you + * re-take the lock! + */ } @@ -1280,6 +1290,8 @@ extern void thread_abort_hook(struct k_thread *thread); */ static void halt_thread(struct k_thread *thread, uint8_t new_state) { + bool dummify = false; + /* We hold the lock, and the thread is known not to be running * anywhere. */ @@ -1296,6 +1308,16 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) } (void)z_abort_thread_timeout(thread); unpend_all(&thread->join_queue); + + /* Edge case: aborting _current from within an + * ISR that preempted it requires clearing the + * _current pointer so the upcoming context + * switch doesn't clobber the now-freed + * memory + */ + if (thread == _current && arch_is_in_isr()) { + dummify = true; + } } #ifdef CONFIG_SMP unpend_all(&thread->halt_queue); @@ -1334,6 +1356,16 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) #ifdef CONFIG_THREAD_ABORT_NEED_CLEANUP k_thread_abort_cleanup(thread); #endif /* CONFIG_THREAD_ABORT_NEED_CLEANUP */ + + /* Do this "set _current to dummy" step last so that + * subsystems above can rely on _current being + * unchanged. Disabled for posix as that arch + * continues to use the _current pointer in its swap + * code. + */ + if (dummify && !IS_ENABLED(CONFIG_ARCH_POSIX)) { + z_dummy_thread_init(&_thread_dummies[_current_cpu->id]); + } } } diff --git a/kernel/smp.c b/kernel/smp.c index 346432707d40fd..f04a7270f31bee 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -108,7 +108,6 @@ static void wait_for_start_signal(atomic_t *start_flag) static inline void smp_init_top(void *arg) { - struct k_thread dummy_thread; struct cpu_start_cb csc = arg ? *(struct cpu_start_cb *)arg : (struct cpu_start_cb){0}; /* Let start_cpu() know that this CPU has powered up. */ @@ -123,7 +122,7 @@ static inline void smp_init_top(void *arg) /* Initialize the dummy thread struct so that * the scheduler can schedule actual threads to run. */ - z_dummy_thread_init(&dummy_thread); + z_dummy_thread_init(&_thread_dummies[arch_curr_cpu()->id]); } #ifdef CONFIG_SYS_CLOCK_EXISTS From 2f0ff198da7acf72ce5c4c057aecc967a83f736a Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0075/1389] tests/kernel/threads: Augment abort_from_isr test to detect FMW There's a easily-tripped-upon free memory write condition in the arch layers where they will write to a cached _current pointer after that thread has been aborted. Detect this by clobbering the thread data after the return from k_thread_abort() and validating that it's still clear after the ISR returns. Note that the clobbering of the thread struct requires the removal of a k_thread_join() that (obviously) requires that it see a DEAD flag set. Joining aborted threads isn't actually legal, but does still work as long as app code doesn't reuse the memory. Basically we can't test both cases here, and we have join coverage elsewhere already. Signed-off-by: Andy Ross --- .../src/test_threads_cancel_abort.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c b/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c index aad8842a11eadb..b99347a404ff85 100644 --- a/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c +++ b/tests/kernel/threads/thread_apis/src/test_threads_cancel_abort.c @@ -166,6 +166,11 @@ static void offload_func(const void *param) k_thread_abort(t); + /* Thread memory is unused now, validate that we can clobber it. */ + if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { + memset(t, 0, sizeof(*t)); + } + /* k_thread_abort() in an isr shouldn't affect the ISR's execution */ isr_finished = true; } @@ -201,6 +206,19 @@ ZTEST(threads_lifecycle, test_abort_from_isr) k_thread_join(&tdata, K_FOREVER); zassert_true(isr_finished, "ISR did not complete"); + /* Thread struct was cleared after the abort, make sure it is + * still clear (i.e. that the arch layer didn't write to it + * during interrupt exit). Doesn't work on posix, which needs + * the thread struct for its swap code. + */ + uint8_t *p = (uint8_t *)&tdata; + + if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { + for (int i = 0; i < sizeof(tdata); i++) { + zassert_true(p[i] == 0, "Free memory write to aborted thread"); + } + } + /* Notice: Recover back the offload_sem: This is use for releasing * offload_sem which might be held when thread aborts itself in ISR * context, it will cause irq_offload cannot be used again. @@ -248,6 +266,5 @@ ZTEST(threads_lifecycle, test_abort_from_isr_not_self) /* Simulate taking an interrupt which kills spwan thread */ irq_offload(offload_func, (void *)tid); - k_thread_join(&tdata, K_FOREVER); zassert_true(isr_finished, "ISR did not complete"); } From da0037b0e73f19e48dc53ef01eb484022ea4d136 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0076/1389] sched: Optimize dummy thread usage on SMP Nicolas Pitre points out that since these thread structs are just dummies for the context swtiching, they can be presumed to be "write only" and thus there's no point in having one per CPU, everyone can share the same one. The only gotcha is that we never really documented (nor really have a place to document) that rule, so it's not theoretically impossible for an architecture to read back what it might have written underneath arch_switch(). Leave this in a separate commit for bisection purposes, but the risk seems very low. Signed-off-by: Andy Ross --- kernel/include/ksched.h | 2 +- kernel/init.c | 2 +- kernel/sched.c | 4 ++-- kernel/smp.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/include/ksched.h b/kernel/include/ksched.h index dff2717702234f..058e44ebef3a99 100644 --- a/kernel/include/ksched.h +++ b/kernel/include/ksched.h @@ -37,7 +37,7 @@ BUILD_ASSERT(K_LOWEST_APPLICATION_THREAD_PRIO #define Z_ASSERT_VALID_PRIO(prio, entry_point) __ASSERT((prio) == -1, "") #endif /* CONFIG_MULTITHREADING */ -extern struct k_thread _thread_dummies[CONFIG_MP_MAX_NUM_CPUS]; +extern struct k_thread _thread_dummy; void z_sched_init(void); void z_move_thread_to_end_of_prio_q(struct k_thread *thread); diff --git a/kernel/init.c b/kernel/init.c index f6edb54f5a9e99..eaffb6ce763b37 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -650,7 +650,7 @@ FUNC_NORETURN void z_cstart(void) LOG_CORE_INIT(); #if defined(CONFIG_MULTITHREADING) - z_dummy_thread_init(&_thread_dummies[0]); + z_dummy_thread_init(&_thread_dummy); #endif /* CONFIG_MULTITHREADING */ /* do any necessary initialization of static devices */ z_device_state_init(); diff --git a/kernel/sched.c b/kernel/sched.c index 00d0efdb4db356..6ee12648560edd 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -33,7 +33,7 @@ struct k_spinlock _sched_spinlock; /* Storage to "complete" the context switch from an invalid/incomplete thread * context (ex: exiting an ISR that aborted _current) */ -__incoherent struct k_thread _thread_dummies[CONFIG_MP_MAX_NUM_CPUS]; +__incoherent struct k_thread _thread_dummy; static void update_cache(int preempt_ok); static void halt_thread(struct k_thread *thread, uint8_t new_state); @@ -1364,7 +1364,7 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) * code. */ if (dummify && !IS_ENABLED(CONFIG_ARCH_POSIX)) { - z_dummy_thread_init(&_thread_dummies[_current_cpu->id]); + z_dummy_thread_init(&_thread_dummy); } } } diff --git a/kernel/smp.c b/kernel/smp.c index f04a7270f31bee..704bfcd9caa9bf 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -122,7 +122,7 @@ static inline void smp_init_top(void *arg) /* Initialize the dummy thread struct so that * the scheduler can schedule actual threads to run. */ - z_dummy_thread_init(&_thread_dummies[arch_curr_cpu()->id]); + z_dummy_thread_init(&_thread_dummy); } #ifdef CONFIG_SYS_CLOCK_EXISTS From a1936aec0fb02b59ffffddeab98231eadf70dadf Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0077/1389] kernel/sched: Fix lockless ordering in halt_thread() We've had threads spinning on the thread state bits, but weren't being careful to ensure that those bits were the last things seen to change in a halting thread. Move it to the end, and add a barrier for correctness. Signed-off-by: Andy Ross --- kernel/sched.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 6ee12648560edd..f4890389ba5e00 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -195,6 +195,7 @@ static inline bool is_halting(struct k_thread *thread) /* Clear the halting bits (_THREAD_ABORTING and _THREAD_SUSPENDING) */ static inline void clear_halting(struct k_thread *thread) { + barrier_dmem_fence_full(); /* Other cpus spin on this locklessly! */ thread->base.thread_state &= ~(_THREAD_ABORTING | _THREAD_SUSPENDING); } @@ -1297,7 +1298,6 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) */ if ((thread->base.thread_state & new_state) == 0U) { thread->base.thread_state |= new_state; - clear_halting(thread); if (z_is_thread_queued(thread)) { dequeue_thread(thread); } @@ -1325,6 +1325,7 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) update_cache(1); if (new_state == _THREAD_SUSPENDED) { + clear_halting(thread); return; } @@ -1366,6 +1367,12 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) if (dummify && !IS_ENABLED(CONFIG_ARCH_POSIX)) { z_dummy_thread_init(&_thread_dummy); } + + /* Finally update the halting thread state, on which + * other CPUs might be spinning (see + * thread_halt_spin()). + */ + clear_halting(thread); } } From 30f62aeb7e3733e6f0a8dd33d8aecd8cab4507be Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0078/1389] kernel/sched: Fix edge^2 case in abort/join The previous abort-lifecycle fix missed a case: other threads can enter k_thread_join(), see that the thread is already dead, and then need to call z_thread_switch_spin() to wait for a context switch. But the new "dummification" code was (by design!) terminating the thread such that no context would be saved to it. So switch_handle stayed NULL and if you hit that timing case correctly[1] you'd deadlock waiting for a switch that would never come. Fix is just to set switch_handle when dummifying to any non-NULL value. Also add an assertion to catch the obvious case that a thread is actually dead on the exit path of k_thread_abort() to make sure the variant path continues to set flags correctly [1] CI was doing it fairly reliably via tests/kernel/smp_abort on qemu_cortex_a53 only. Only one of my dev systems could see it, and then only about 15% of the time. Signed-off-by: Andy Ross --- kernel/sched.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index f4890389ba5e00..32cdb5eff7e7eb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1362,10 +1362,17 @@ static void halt_thread(struct k_thread *thread, uint8_t new_state) * subsystems above can rely on _current being * unchanged. Disabled for posix as that arch * continues to use the _current pointer in its swap - * code. + * code. Note that we must leave a non-null switch + * handle for any threads spinning in join() (this can + * never be used, as our thread is flagged dead, but + * it must not be NULL otherwise join can deadlock). */ if (dummify && !IS_ENABLED(CONFIG_ARCH_POSIX)) { +#ifdef CONFIG_USE_SWITCH + _current->switch_handle = _current; +#endif z_dummy_thread_init(&_thread_dummy); + } /* Finally update the halting thread state, on which @@ -1402,6 +1409,8 @@ void z_impl_k_thread_abort(struct k_thread *thread) z_thread_abort(thread); + __ASSERT_NO_MSG((thread->base.thread_state & _THREAD_DEAD) != 0); + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, abort, thread); } #endif /* !CONFIG_ARCH_HAS_THREAD_ABORT */ From 8654f2f9bf940a2f71a7c1ab739aab9a0b93fb43 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0079/1389] tests: thread abort deadlock scenario Adds a test to verify that a series of k_thread_abort() issued from ISRs do not cause a deadlock. Filtered on x86 as the x86_64 irq_offload() implementation isn't SMP-safe. See #72172 Signed-off-by: Peter Mitsis --- tests/kernel/smp_abort/CMakeLists.txt | 12 ++++ tests/kernel/smp_abort/prj.conf | 3 + tests/kernel/smp_abort/src/main.c | 92 +++++++++++++++++++++++++++ tests/kernel/smp_abort/testcase.yaml | 7 ++ 4 files changed, 114 insertions(+) create mode 100644 tests/kernel/smp_abort/CMakeLists.txt create mode 100644 tests/kernel/smp_abort/prj.conf create mode 100644 tests/kernel/smp_abort/src/main.c create mode 100644 tests/kernel/smp_abort/testcase.yaml diff --git a/tests/kernel/smp_abort/CMakeLists.txt b/tests/kernel/smp_abort/CMakeLists.txt new file mode 100644 index 00000000000000..8419d0169e4544 --- /dev/null +++ b/tests/kernel/smp_abort/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(smp_abort) + +target_sources(app PRIVATE src/main.c) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/${ARCH}/include + ) diff --git a/tests/kernel/smp_abort/prj.conf b/tests/kernel/smp_abort/prj.conf new file mode 100644 index 00000000000000..eeaa3ed4861875 --- /dev/null +++ b/tests/kernel/smp_abort/prj.conf @@ -0,0 +1,3 @@ +CONFIG_ZTEST=y +CONFIG_IRQ_OFFLOAD=y +CONFIG_SMP=y diff --git a/tests/kernel/smp_abort/src/main.c b/tests/kernel/smp_abort/src/main.c new file mode 100644 index 00000000000000..e0eb2c78819d01 --- /dev/null +++ b/tests/kernel/smp_abort/src/main.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#if CONFIG_MP_MAX_NUM_CPUS < 2 +#error "SMP test requires at least two CPUs!" +#endif + +#define NUM_THREADS CONFIG_MP_MAX_NUM_CPUS +#define STACK_SIZE 1024 + +K_THREAD_STACK_ARRAY_DEFINE(thread_stack, NUM_THREADS, STACK_SIZE); +struct k_thread thread[NUM_THREADS]; + +struct isr_args { + volatile bool *sync; + volatile bool *wait; + struct k_thread *target; +}; + +volatile bool sync[NUM_THREADS]; + +struct isr_args isr_args[NUM_THREADS]; + +static void isr(const void *args) +{ + const struct isr_args *var = args; + + *(var->sync) = true; /* Flag that ISR is in progress */ + + while (*(var->wait) == false) { /* Wait upon dependent CPU */ + } + + k_thread_abort(var->target); /* Abort thread on another CPU */ +} + +static void thread_entry(void *p1, void *p2, void *p3) +{ + unsigned int index = (unsigned int)(uintptr_t)p1; + struct isr_args *var = p2; + + printk("Thread %u started\n", index); + + irq_offload(isr, var); + + zassert_true(false, "Thread %u did not abort!", index); +} + +ZTEST(smp_abort, test_smp_thread_abort_deadlock) +{ + unsigned int i; + int priority; + + priority = k_thread_priority_get(k_current_get()); + + /* + * Each thread will run on its own CPU and invoke an ISR. + * Each ISR will wait until the next thread enters its ISR + * before attempting to abort that thread. This ensures that + * we have a scenario where each CPU is attempting to abort + * the active thread that was interrupted by an ISR. + */ + + for (i = 0; i < NUM_THREADS; i++) { + isr_args[i].sync = &sync[i]; + isr_args[i].wait = &sync[(i + 1) % NUM_THREADS]; + isr_args[i].target = &thread[(i + 1) % NUM_THREADS]; + } + + for (i = 0; i < NUM_THREADS; i++) { + + k_thread_create(&thread[i], thread_stack[i], + STACK_SIZE, thread_entry, + (void *)(uintptr_t)i, &isr_args[i], NULL, + priority - 1, 0, K_NO_WAIT); + } + + for (i = 0; i < NUM_THREADS; i++) { + k_thread_join(&thread[i], K_FOREVER); + } + + printk("Done!\n"); +} + +ZTEST_SUITE(smp_abort, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/kernel/smp_abort/testcase.yaml b/tests/kernel/smp_abort/testcase.yaml new file mode 100644 index 00000000000000..3903e477e178c8 --- /dev/null +++ b/tests/kernel/smp_abort/testcase.yaml @@ -0,0 +1,7 @@ +tests: + kernel.smp_abort: + arch_exclude: x86 # Buggy irq_offload(), see #71172 + tags: + - kernel + - smp + filter: (CONFIG_MP_MAX_NUM_CPUS > 1) From 978f318db5b903cf06eeb9c6761497a617d596f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0080/1389] mgmt: hawkbit: use shell macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use short shell macros for printing. Signed-off-by: Fin Maaß --- subsys/mgmt/hawkbit/shell.c | 54 +++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/subsys/mgmt/hawkbit/shell.c b/subsys/mgmt/hawkbit/shell.c index 7f1efbd36aff59..f4df6474cd11eb 100644 --- a/subsys/mgmt/hawkbit/shell.c +++ b/subsys/mgmt/hawkbit/shell.c @@ -18,52 +18,49 @@ static void cmd_run(const struct shell *sh, size_t argc, char **argv) ARG_UNUSED(argc); ARG_UNUSED(argv); - shell_fprintf(sh, SHELL_INFO, "Starting hawkBit run...\n"); + + shell_info(sh, "Starting hawkBit run..."); switch (hawkbit_probe()) { case HAWKBIT_UNCONFIRMED_IMAGE: - shell_fprintf( - sh, SHELL_ERROR, - "Image is unconfirmed." - "Rebooting to revert back to previous confirmed image\n"); - hawkbit_reboot(); + shell_error(sh, "Image is unconfirmed." + "Rebooting to revert back to previous confirmed image"); break; case HAWKBIT_CANCEL_UPDATE: - shell_fprintf(sh, SHELL_INFO, - "hawkBit update Cancelled from server\n"); + shell_info(sh, "hawkBit update cancelled from server"); break; case HAWKBIT_NO_UPDATE: - shell_fprintf(sh, SHELL_INFO, "No update found\n"); + shell_info(sh, "No update found"); break; case HAWKBIT_OK: - shell_fprintf(sh, SHELL_INFO, "Image Already updated\n"); + shell_info(sh, "Image already updated"); break; case HAWKBIT_UPDATE_INSTALLED: - shell_fprintf(sh, SHELL_INFO, "Update Installed\n"); + shell_info(sh, "Update installed"); hawkbit_reboot(); break; case HAWKBIT_DOWNLOAD_ERROR: - shell_fprintf(sh, SHELL_INFO, "Download Error\n"); + shell_error(sh, "Download error"); break; case HAWKBIT_NETWORKING_ERROR: - shell_fprintf(sh, SHELL_INFO, "Networking Error\n"); + shell_error(sh, "Networking error"); break; case HAWKBIT_METADATA_ERROR: - shell_fprintf(sh, SHELL_INFO, "Metadata Error\n"); + shell_error(sh, "Metadata error"); break; case HAWKBIT_NOT_INITIALIZED: - shell_fprintf(sh, SHELL_ERROR, "hawkBit not initialized\n"); + shell_error(sh, "hawkBit not initialized"); break; default: - shell_fprintf(sh, SHELL_ERROR, "Invalid response\n"); + shell_error(sh, "Invalid response"); break; } k_sleep(K_MSEC(1)); @@ -81,15 +78,14 @@ static int cmd_info(const struct shell *sh, size_t argc, char *argv) hawkbit_get_device_identity(device_id, DEVICE_ID_HEX_MAX_SIZE); shell_print(sh, "Action id: %d", hawkbit_get_action_id()); - shell_fprintf(sh, SHELL_NORMAL, "Unique device id: %s\n", device_id); - shell_fprintf(sh, SHELL_NORMAL, "Firmware Version: %s\n", - firmware_version); - shell_fprintf(sh, SHELL_NORMAL, "Server address: %s\n", hawkbit_get_server_addr()); - shell_fprintf(sh, SHELL_NORMAL, "Server port: %d\n", hawkbit_get_server_port()); - shell_fprintf(sh, SHELL_NORMAL, "DDI security token: %s\n", - (IS_ENABLED(CONFIG_HAWKBIT_DDI_NO_SECURITY) - ? "" - : hawkbit_get_ddi_security_token())); + shell_print(sh, "Unique device id: %s", device_id); + shell_print(sh, "Firmware Version: %s", firmware_version); + shell_print(sh, "Server address: %s", hawkbit_get_server_addr()); + shell_print(sh, "Server port: %d", hawkbit_get_server_port()); + shell_print(sh, "DDI security token: %s", + (IS_ENABLED(CONFIG_HAWKBIT_DDI_NO_SECURITY) + ? "" + : hawkbit_get_ddi_security_token())); return 0; } @@ -99,7 +95,7 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv) ARG_UNUSED(argc); ARG_UNUSED(argv); - shell_fprintf(sh, SHELL_INFO, "Init hawkBit ...\n"); + shell_info(sh, "Init hawkBit ..."); hawkbit_init(); @@ -123,7 +119,7 @@ static int cmd_reset(const struct shell *sh, size_t argc, char *argv) static int cmd_set_addr(const struct shell *sh, size_t argc, char **argv) { if (argc < 2) { - shell_fprintf(sh, SHELL_ERROR, "Invalid number of arguments\n"); + shell_error(sh, "Invalid number of arguments"); return -EINVAL; } @@ -135,7 +131,7 @@ static int cmd_set_addr(const struct shell *sh, size_t argc, char **argv) static int cmd_set_port(const struct shell *sh, size_t argc, char **argv) { if (argc < 2) { - shell_fprintf(sh, SHELL_ERROR, "Invalid number of arguments\n"); + shell_error(sh, "Invalid number of arguments"); return -EINVAL; } @@ -148,7 +144,7 @@ static int cmd_set_port(const struct shell *sh, size_t argc, char **argv) static int cmd_set_token(const struct shell *sh, size_t argc, char **argv) { if (argc < 2) { - shell_fprintf(sh, SHELL_ERROR, "Invalid number of arguments\n"); + shell_error(sh, "Invalid number of arguments"); return -EINVAL; } From 22a37d7f4f5365299582a7441c007d315746aa82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0081/1389] mgmt: hawkbit: some doc improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit some doc improvements in hawkbit.h. Signed-off-by: Fin Maaß --- include/zephyr/mgmt/hawkbit.h | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/include/zephyr/mgmt/hawkbit.h b/include/zephyr/mgmt/hawkbit.h index 3516650a920746..55bc0e8411c41f 100644 --- a/include/zephyr/mgmt/hawkbit.h +++ b/include/zephyr/mgmt/hawkbit.h @@ -71,15 +71,16 @@ typedef int (*hawkbit_config_device_data_cb_handler_t)(const char *device_id, ui * * @param cb The callback function. * - * @return 0 on success. - * @return -EINVAL if the callback is NULL. + * @retval 0 on success. + * @retval -EINVAL if the callback is NULL. */ int hawkbit_set_custom_data_cb(hawkbit_config_device_data_cb_handler_t cb); /** * @brief Init the flash partition * - * @return 0 on success, negative on error. + * @retval 0 on success. + * @retval -errno if init fails. */ int hawkbit_init(void); @@ -94,12 +95,17 @@ void hawkbit_autohandler(void); /** * @brief The hawkBit probe verify if there is some update to be performed. * - * @return HAWKBIT_UPDATE_INSTALLED has an update available. - * @return HAWKBIT_NO_UPDATE no update available. - * @return HAWKBIT_NETWORKING_ERROR fail to connect to the hawkBit server. - * @return HAWKBIT_METADATA_ERROR fail to parse or to encode the metadata. - * @return HAWKBIT_OK if success. - * @return HAWKBIT_DOWNLOAD_ERROR fail while downloading the update package. + * @retval HAWKBIT_NETWORKING_ERROR fail to connect to the hawkBit server. + * @retval HAWKBIT_UNCONFIRMED_IMAGE image is unconfirmed. + * @retval HAWKBIT_PERMISSION_ERROR fail to get the permission to access the hawkBit server. + * @retval HAWKBIT_METADATA_ERROR fail to parse or to encode the metadata. + * @retval HAWKBIT_DOWNLOAD_ERROR fail while downloading the update package. + * @retval HAWKBIT_OK if the image was already updated. + * @retval HAWKBIT_UPDATE_INSTALLED if an update was installed. Reboot is required to apply it. + * @retval HAWKBIT_NO_UPDATE if no update was available. + * @retval HAWKBIT_CANCEL_UPDATE if the update was cancelled by the server. + * @retval HAWKBIT_NOT_INITIALIZED if hawkBit is not initialized. + * @retval HAWKBIT_PROBE_IN_PROGRESS if probe is currently running. */ enum hawkbit_response hawkbit_probe(void); @@ -123,8 +129,8 @@ typedef bool (*hawkbit_get_device_identity_cb_handler_t)(char *id, int id_max_le * * @param cb The callback function. * - * @return 0 on success. - * @return -EINVAL if the callback is NULL. + * @retval 0 on success. + * @retval -EINVAL if the callback is NULL. */ int hawkbit_set_device_identity_cb(hawkbit_get_device_identity_cb_handler_t cb); From fdd0430bacf2d0f845b3ba341eaf184deddf7984 Mon Sep 17 00:00:00 2001 From: Jose Alberto Meza Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0082/1389] treewide: drivers: espi: Adjust terms per eSPI specification 1.5 1) Replace master/slave in API for new terms in eSPI spec 1.5 2) Reflect eSPI VW change and macro changes across eSPI drivers 3) Update terms in eSPI driver sample and eSPI test driver Signed-off-by: Jose Alberto Meza --- drivers/espi/espi_it8xxx2.c | 8 +- drivers/espi/espi_mchp_xec.c | 134 +++++++++--------- drivers/espi/espi_mchp_xec_v2.c | 44 +++--- drivers/espi/espi_npcx.c | 30 ++-- .../microchip/mec172x/mec172x-vw-routing.dtsi | 4 +- include/zephyr/drivers/espi.h | 100 ++++++------- samples/drivers/espi/src/main.c | 24 ++-- subsys/emul/espi/emul_espi_host.c | 63 ++++---- 8 files changed, 204 insertions(+), 203 deletions(-) diff --git a/drivers/espi/espi_it8xxx2.c b/drivers/espi/espi_it8xxx2.c index 6694cf013ff68c..bd0d83c02103ef 100644 --- a/drivers/espi/espi_it8xxx2.c +++ b/drivers/espi/espi_it8xxx2.c @@ -597,10 +597,10 @@ static const struct vw_channel_t vw_channel_list[] = { VW_CHAN(ESPI_VWIRE_SIGNAL_PME, 0x04, BIT(3), BIT(7)), VW_CHAN(ESPI_VWIRE_SIGNAL_WAKE, 0x04, BIT(2), BIT(6)), VW_CHAN(ESPI_VWIRE_SIGNAL_OOB_RST_ACK, 0x04, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 0x05, BIT(3), BIT(7)), + VW_CHAN(ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 0x05, BIT(3), BIT(7)), VW_CHAN(ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, 0x05, BIT(2), BIT(6)), VW_CHAN(ESPI_VWIRE_SIGNAL_ERR_FATAL, 0x05, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, 0x05, BIT(0), BIT(4)), + VW_CHAN(ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 0x05, BIT(0), BIT(4)), VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_RST_ACK, 0x06, BIT(3), BIT(7)), VW_CHAN(ESPI_VWIRE_SIGNAL_RST_CPU_INIT, 0x06, BIT(2), BIT(6)), VW_CHAN(ESPI_VWIRE_SIGNAL_SMI, 0x06, BIT(1), BIT(5)), @@ -1598,9 +1598,9 @@ static void espi_it8xxx2_oob_ch_en_isr(const struct device *dev, bool enable) static void espi_it8xxx2_flash_ch_en_isr(const struct device *dev, bool enable) { if (enable) { - espi_it8xxx2_send_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 1); + espi_it8xxx2_send_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 1); espi_it8xxx2_send_vwire(dev, - ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, 1); + ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 1); } espi_it8xxx2_ch_notify_system_state(dev, ESPI_CHANNEL_FLASH, enable); diff --git a/drivers/espi/espi_mchp_xec.c b/drivers/espi/espi_mchp_xec.c index 58678914862c73..88af24554a1600 100644 --- a/drivers/espi/espi_mchp_xec.c +++ b/drivers/espi/espi_mchp_xec.c @@ -113,107 +113,107 @@ enum mchp_smvw_regs { }; /* Microchip canonical virtual wire mapping - * ------------------------------------------------------------------------| - * VW Idx | VW reg | SRC_ID3 | SRC_ID2 | SRC_ID1 | SRC_ID0 | - * ------------------------------------------------------------------------| + * --------------------------------------------------------------------------------| + * VW Idx | VW reg | SRC_ID3 | SRC_ID2 | SRC_ID1 | SRC_ID0 | + * --------------------------------------------------------------------------------| * System Event Virtual Wires - * ------------------------------------------------------------------------| - * 2h | MSVW00 | res | SLP_S5# | SLP_S4# | SLP_S3# | - * 3h | MSVW01 | res | OOB_RST_WARN | PLTRST# | SUS_STAT# | - * 4h | SMVW00 | PME# | WAKE# | res | OOB_RST_ACK | - * 5h | SMVW01 | SLV_BOOT_STS | ERR_NONFATAL | ERR_FATAL | SLV_BT_DONE | - * 6h | SMVW02 | HOST_RST_ACK | RCIN# | SMI# | SCI# | - * 7h | MSVW02 | res | res | res | HOS_RST_WARN| - * ------------------------------------------------------------------------| + * --------------------------------------------------------------------------------| + * 2h | MSVW00 | res | SLP_S5# | SLP_S4# | SLP_S3# | + * 3h | MSVW01 | res | OOB_RST_WARN | PLTRST# | SUS_STAT# | + * 4h | SMVW00 | PME# | WAKE# | res | OOB_RST_ACK | + * 5h | SMVW01 | TARGET_BOOT_STS | ERR_NONFATAL | ERR_FATAL | TARGET_BOOT_DONE | + * 6h | SMVW02 | HOST_RST_ACK | RCIN# | SMI# | SCI# | + * 7h | MSVW02 | res | res | res | HOS_RST_WARN | + * --------------------------------------------------------------------------------| * Platform specific virtual wires - * ------------------------------------------------------------------------| - * 40h | SMVW03 | res | res | DNX_ACK | SUS_ACK# | - * 41h | MSVW03 | SLP_A# | res | SUS_PDNACK| SUS_WARN# | - * 42h | MSVW04 | res | res | SLP_WLAN# | SLP_LAN# | - * 43h | MSVW05 | generic | generic | generic | generic | - * 44h | MSVW06 | generic | generic | generic | generic | - * 45h | SMVW04 | generic | generic | generic | generic | - * 46h | SMVW05 | generic | generic | generic | generic | - * 47h | MSVW07 | res | res | res | HOST_C10 | - * 4Ah | MSVW08 | res | res | DNX_WARN | res | - * 50h | SMVW06 | ESPI_OCB_3 | ESPI_OCB_2 | ESPI_OCB_1| ESPI_OCB_0 | + * --------------------------------------------------------------------------------| + * 40h | SMVW03 | res | res | DNX_ACK | SUS_ACK# | + * 41h | MSVW03 | SLP_A# | res | SUS_PDNACK| SUS_WARN# | + * 42h | MSVW04 | res | res | SLP_WLAN# | SLP_LAN# | + * 43h | MSVW05 | generic | generic | generic | generic | + * 44h | MSVW06 | generic | generic | generic | generic | + * 45h | SMVW04 | generic | generic | generic | generic | + * 46h | SMVW05 | generic | generic | generic | generic | + * 47h | MSVW07 | res | res | res | HOST_C10 | + * 4Ah | MSVW08 | res | res | DNX_WARN | res | + * 50h | SMVW06 | ESPI_OCB_3 | ESPI_OCB_2 | ESPI_OCB_1| ESPI_OCB_0 | */ static const struct xec_signal vw_tbl[] = { /* MSVW00 */ [ESPI_VWIRE_SIGNAL_SLP_S3] = {MCHP_MSVW00, ESPI_VWIRE_SRC_ID0, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_SLP_S4] = {MCHP_MSVW00, ESPI_VWIRE_SRC_ID1, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_SLP_S5] = {MCHP_MSVW00, ESPI_VWIRE_SRC_ID2, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* MSVW01 */ [ESPI_VWIRE_SIGNAL_SUS_STAT] = {MCHP_MSVW01, ESPI_VWIRE_SRC_ID0, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_PLTRST] = {MCHP_MSVW01, ESPI_VWIRE_SRC_ID1, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_OOB_RST_WARN] = {MCHP_MSVW01, ESPI_VWIRE_SRC_ID2, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* SMVW00 */ [ESPI_VWIRE_SIGNAL_OOB_RST_ACK] = {MCHP_SMVW00, ESPI_VWIRE_SRC_ID0, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_WAKE] = {MCHP_SMVW00, ESPI_VWIRE_SRC_ID2, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_PME] = {MCHP_SMVW00, ESPI_VWIRE_SRC_ID3, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, /* SMVW01 */ - [ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE] = {MCHP_SMVW01, ESPI_VWIRE_SRC_ID0, - ESPI_SLAVE_TO_MASTER}, + [ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE] = {MCHP_SMVW01, ESPI_VWIRE_SRC_ID0, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_ERR_FATAL] = {MCHP_SMVW01, ESPI_VWIRE_SRC_ID1, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_ERR_NON_FATAL] = {MCHP_SMVW01, ESPI_VWIRE_SRC_ID2, - ESPI_SLAVE_TO_MASTER}, - [ESPI_VWIRE_SIGNAL_SLV_BOOT_STS] = {MCHP_SMVW01, ESPI_VWIRE_SRC_ID3, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, + [ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS] = {MCHP_SMVW01, ESPI_VWIRE_SRC_ID3, + ESPI_TARGET_TO_CONTROLLER}, /* SMVW02 */ [ESPI_VWIRE_SIGNAL_SCI] = {MCHP_SMVW02, ESPI_VWIRE_SRC_ID0, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_SMI] = {MCHP_SMVW02, ESPI_VWIRE_SRC_ID1, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_RST_CPU_INIT] = {MCHP_SMVW02, ESPI_VWIRE_SRC_ID2, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_HOST_RST_ACK] = {MCHP_SMVW02, ESPI_VWIRE_SRC_ID3, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, /* MSVW02 */ [ESPI_VWIRE_SIGNAL_HOST_RST_WARN] = {MCHP_MSVW02, ESPI_VWIRE_SRC_ID0, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* SMVW03 */ [ESPI_VWIRE_SIGNAL_SUS_ACK] = {MCHP_SMVW03, ESPI_VWIRE_SRC_ID0, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_DNX_ACK] = {MCHP_SMVW03, ESPI_VWIRE_SRC_ID1, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, /* MSVW03 */ [ESPI_VWIRE_SIGNAL_SUS_WARN] = {MCHP_MSVW03, ESPI_VWIRE_SRC_ID0, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_SUS_PWRDN_ACK] = {MCHP_MSVW03, ESPI_VWIRE_SRC_ID1, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_SLP_A] = {MCHP_MSVW03, ESPI_VWIRE_SRC_ID3, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* MSVW04 */ [ESPI_VWIRE_SIGNAL_SLP_LAN] = {MCHP_MSVW04, ESPI_VWIRE_SRC_ID0, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, [ESPI_VWIRE_SIGNAL_SLP_WLAN] = {MCHP_MSVW04, ESPI_VWIRE_SRC_ID1, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* MSVW07 */ [ESPI_VWIRE_SIGNAL_HOST_C10] = {MCHP_MSVW07, ESPI_VWIRE_SRC_ID0, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* MSVW08 */ [ESPI_VWIRE_SIGNAL_DNX_WARN] = {MCHP_MSVW08, ESPI_VWIRE_SRC_ID1, - ESPI_MASTER_TO_SLAVE}, + ESPI_CONTROLLER_TO_TARGET}, /* SMVW06 */ [ESPI_VWIRE_SIGNAL_OCB_0] = {MCHP_SMVW06, ESPI_VWIRE_SRC_ID0, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_OCB_1] = {MCHP_SMVW06, ESPI_VWIRE_SRC_ID1, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_OCB_2] = {MCHP_SMVW06, ESPI_VWIRE_SRC_ID2, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, [ESPI_VWIRE_SIGNAL_OCB_3] = {MCHP_SMVW06, ESPI_VWIRE_SRC_ID3, - ESPI_SLAVE_TO_MASTER}, + ESPI_TARGET_TO_CONTROLLER}, }; /* Buffer size are expressed in bytes */ @@ -445,14 +445,14 @@ static int espi_xec_send_vwire(const struct device *dev, return -EINVAL; } - if (signal_info.dir == ESPI_MASTER_TO_SLAVE) { + if (signal_info.dir == ESPI_CONTROLLER_TO_TARGET) { ESPI_MSVW_REG *reg = &(ESPI_M2S_VW_REGS->MSVW00) + xec_id; uint8_t *p8 = (uint8_t *)®->SRC; *(p8 + (uintptr_t) src_id) = level; } - if (signal_info.dir == ESPI_SLAVE_TO_MASTER) { + if (signal_info.dir == ESPI_TARGET_TO_CONTROLLER) { ESPI_SMVW_REG *reg = &(ESPI_S2M_VW_REGS->SMVW00) + xec_id; uint8_t *p8 = (uint8_t *)®->SRC; @@ -483,12 +483,12 @@ static int espi_xec_receive_vwire(const struct device *dev, return -EINVAL; } - if (signal_info.dir == ESPI_MASTER_TO_SLAVE) { + if (signal_info.dir == ESPI_CONTROLLER_TO_TARGET) { ESPI_MSVW_REG *reg = &(ESPI_M2S_VW_REGS->MSVW00) + xec_id; *level = ((reg->SRC >> (src_id << 3)) & 0x01ul); } - if (signal_info.dir == ESPI_SLAVE_TO_MASTER) { + if (signal_info.dir == ESPI_TARGET_TO_CONTROLLER) { ESPI_SMVW_REG *reg = &(ESPI_S2M_VW_REGS->SMVW00) + xec_id; *level = ((reg->SRC >> (src_id << 3)) & 0x01ul); } @@ -748,17 +748,17 @@ static int espi_xec_manage_callback(const struct device *dev, } #ifdef CONFIG_ESPI_AUTOMATIC_BOOT_DONE_ACKNOWLEDGE -static void send_slave_bootdone(const struct device *dev) +static void send_target_bootdone(const struct device *dev) { int ret; uint8_t boot_done; - ret = espi_xec_receive_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, + ret = espi_xec_receive_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, &boot_done); if (!ret && !boot_done) { - /* SLAVE_BOOT_DONE & SLAVE_LOAD_STS have to be sent together */ - espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 1); - espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, 1); + /* TARGET_BOOT_DONE & TARGET_LOAD_STS have to be sent together */ + espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 1); + espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 1); } } #endif @@ -994,7 +994,7 @@ static void espi_vwire_chanel_isr(const struct device *dev) /* VW channel interrupt can disabled at this point */ MCHP_GIRQ_ENCLR(config->bus_girq_id) = MCHP_ESPI_VW_EN_GIRQ_VAL; #ifdef CONFIG_ESPI_AUTOMATIC_BOOT_DONE_ACKNOWLEDGE - send_slave_bootdone(dev); + send_target_bootdone(dev); #endif } @@ -1086,7 +1086,7 @@ static void espi_flash_isr(const struct device *dev) if (status & MCHP_ESPI_FC_STS_CHAN_EN) { espi_init_flash(dev); - /* Indicate flash channel is ready to eSPI master */ + /* Indicate flash channel is ready to eSPI controller */ ESPI_CAP_REGS->FC_RDY = MCHP_ESPI_FC_READY; evt.evt_data = 1; } @@ -1197,7 +1197,7 @@ static void vw_sus_warn_isr(const struct device *dev) notify_host_warning(dev, ESPI_VWIRE_SIGNAL_SUS_WARN); /* Configure spare VW register SMVW06 to VW index 50h. As per * per microchip recommendation, spare VW register should be - * configured between SLAVE_BOOT_LOAD_DONE = 1 VW event and + * configured between TARGET_BOOT_LOAD_DONE = 1 VW event and * point where SUS_ACK=1 VW is sent to SOC. */ espi_config_vw_ocb(); diff --git a/drivers/espi/espi_mchp_xec_v2.c b/drivers/espi/espi_mchp_xec_v2.c index a1a5acefd93dbe..46276db97b4d7b 100644 --- a/drivers/espi/espi_mchp_xec_v2.c +++ b/drivers/espi/espi_mchp_xec_v2.c @@ -122,28 +122,28 @@ static const struct xec_signal vw_tbl[] = { MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_PME, vw_pme_n), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_WAKE, vw_wake_n), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_OOB_RST_ACK, vw_oob_rst_ack), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, vw_slave_boot_status), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, vw_target_boot_status), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, vw_error_non_fatal), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_ERR_FATAL, vw_error_fatal), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, vw_slave_boot_done), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, vw_target_boot_done), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_HOST_RST_ACK, vw_host_rst_ack), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_RST_CPU_INIT, vw_rcin_n), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SMI, vw_smi_n), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SCI, vw_sci_n), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_DNX_ACK, vw_dnx_ack), MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SUS_ACK, vw_sus_ack_n), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_0, vw_t2c_gpio_0), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_1, vw_t2c_gpio_1), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_2, vw_t2c_gpio_2), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_3, vw_t2c_gpio_3), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_4, vw_t2c_gpio_4), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_5, vw_t2c_gpio_5), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_6, vw_t2c_gpio_6), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_7, vw_t2c_gpio_7), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_8, vw_t2c_gpio_8), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_9, vw_t2c_gpio_9), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_10, vw_t2c_gpio_10), - MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_SLV_GPIO_11, vw_t2c_gpio_11), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_0, vw_t2c_gpio_0), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_1, vw_t2c_gpio_1), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_2, vw_t2c_gpio_2), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_3, vw_t2c_gpio_3), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_4, vw_t2c_gpio_4), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_5, vw_t2c_gpio_5), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_6, vw_t2c_gpio_6), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_7, vw_t2c_gpio_7), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_8, vw_t2c_gpio_8), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_9, vw_t2c_gpio_9), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_10, vw_t2c_gpio_10), + MCHP_DT_ESPI_VW_ENTRY(ESPI_VWIRE_SIGNAL_TARGET_GPIO_11, vw_t2c_gpio_11), }; /* Buffer size are expressed in bytes */ @@ -311,13 +311,13 @@ static int espi_xec_send_vwire(const struct device *dev, dir = (signal_info.flags >> MCHP_DT_ESPI_VW_FLAG_DIR_POS) & BIT(0); - if (dir == ESPI_MASTER_TO_SLAVE) { + if (dir == ESPI_CONTROLLER_TO_TARGET) { regaddr = xec_msvw_addr(dev, xec_id); sys_write8(level, regaddr + MSVW_BI_SRC0 + src_id); } - if (dir == ESPI_SLAVE_TO_MASTER) { + if (dir == ESPI_TARGET_TO_CONTROLLER) { regaddr = xec_smvw_addr(dev, xec_id); sys_write8(level, regaddr + SMVW_BI_SRC0 + src_id); @@ -356,12 +356,12 @@ static int espi_xec_receive_vwire(const struct device *dev, dir = (signal_info.flags >> MCHP_DT_ESPI_VW_FLAG_DIR_POS) & BIT(0); - if (dir == ESPI_MASTER_TO_SLAVE) { + if (dir == ESPI_CONTROLLER_TO_TARGET) { regaddr = xec_msvw_addr(dev, xec_id); *level = sys_read8(regaddr + MSVW_BI_SRC0 + src_id) & BIT(0); } - if (dir == ESPI_SLAVE_TO_MASTER) { + if (dir == ESPI_TARGET_TO_CONTROLLER) { regaddr = xec_smvw_addr(dev, xec_id); *level = sys_read8(regaddr + SMVW_BI_SRC0 + src_id) & BIT(0); } @@ -631,12 +631,12 @@ static void send_slave_bootdone(const struct device *dev) int ret; uint8_t boot_done; - ret = espi_xec_receive_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, + ret = espi_xec_receive_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, &boot_done); if (!ret && !boot_done) { /* SLAVE_BOOT_DONE & SLAVE_LOAD_STS have to be sent together */ - espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 1); - espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, 1); + espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 1); + espi_xec_send_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 1); } } #endif @@ -1414,7 +1414,7 @@ static void xec_vw_cfg_properties(const struct xec_signal *p, uint32_t regaddr, */ static void xec_vw_config(const struct device *dev) { - for (int i = ESPI_VWIRE_SIGNAL_SLV_GPIO_0; i < ARRAY_SIZE(vw_tbl); i++) { + for (int i = ESPI_VWIRE_SIGNAL_TARGET_GPIO_0; i < ARRAY_SIZE(vw_tbl); i++) { const struct xec_signal *p = &vw_tbl[i]; uint32_t regaddr = xec_smvw_addr(dev, p->xec_reg_idx); uint8_t dir = (p->flags >> MCHP_DT_ESPI_VW_FLAG_DIR_POS) & BIT(0); diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 15cb5d489dce68..d7cece4eb07d53 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -153,10 +153,10 @@ static const struct npcx_vw_out_config vw_out_tbl[] = { NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_WAKE, vw_wake), NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_PME, vw_pme), /* index 05h (Out) */ - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, vw_slv_boot_done), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, vw_slv_boot_done), NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_ERR_FATAL, vw_err_fatal), NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, vw_err_non_fatal), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, vw_slv_boot_sts_with_done), /* index 06h (Out) */ NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SCI, vw_sci), @@ -171,15 +171,15 @@ static const struct npcx_vw_out_config vw_out_gpio_tbl1[] = { /* Only NPCX9 and later series support this feature */ #if defined(CONFIG_ESPI_NPCX_SUPP_VW_GPIO) /* index 50h (Out) */ - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_0, vw_slv_gpio_0), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_1, vw_slv_gpio_1), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_2, vw_slv_gpio_2), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_3, vw_slv_gpio_3), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_0, vw_slv_gpio_0), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_1, vw_slv_gpio_1), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_2, vw_slv_gpio_2), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_3, vw_slv_gpio_3), /* index 51h (Out) */ - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_4, vw_slv_gpio_4), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_5, vw_slv_gpio_5), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_6, vw_slv_gpio_6), - NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_SLV_GPIO_7, vw_slv_gpio_7), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_4, vw_slv_gpio_4), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_5, vw_slv_gpio_5), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_6, vw_slv_gpio_6), + NPCX_DT_VW_OUT_CONF(ESPI_VWIRE_SIGNAL_TARGET_GPIO_7, vw_slv_gpio_7), #endif }; @@ -618,11 +618,11 @@ static void espi_vw_send_bootload_done(const struct device *dev) uint8_t boot_done; ret = espi_npcx_receive_vwire(dev, - ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, &boot_done); + ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, &boot_done); LOG_DBG("%s: %d", __func__, boot_done); if (!ret && !boot_done) { /* Send slave boot status bit with done bit at the same time. */ - espi_npcx_send_vwire(dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 1); + espi_npcx_send_vwire(dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 1); } } @@ -773,7 +773,7 @@ static int espi_npcx_send_vwire(const struct device *dev, return -EINVAL; } - if (signal >= ESPI_VWIRE_SIGNAL_SLV_GPIO_0) { + if (signal >= ESPI_VWIRE_SIGNAL_TARGET_GPIO_0) { vw_tbl = vw_out_gpio_tbl1; vw_tbl_size = ARRAY_SIZE(vw_out_gpio_tbl1); reg_name = "VWGPSM"; @@ -797,7 +797,7 @@ static int espi_npcx_send_vwire(const struct device *dev, bitmask = vw_tbl[sig_idx].bitmask; /* Get wire field and set/clear wire bit */ - if (signal >= ESPI_VWIRE_SIGNAL_SLV_GPIO_0) { + if (signal >= ESPI_VWIRE_SIGNAL_TARGET_GPIO_0) { val = GET_FIELD(inst->VWGPSM[reg_idx], NPCX_VWEVSM_WIRE); } else { val = GET_FIELD(inst->VWEVSM[reg_idx], NPCX_VWEVSM_WIRE); @@ -809,7 +809,7 @@ static int espi_npcx_send_vwire(const struct device *dev, val &= ~bitmask; } - if (signal >= ESPI_VWIRE_SIGNAL_SLV_GPIO_0) { + if (signal >= ESPI_VWIRE_SIGNAL_TARGET_GPIO_0) { SET_FIELD(inst->VWGPSM[reg_idx], NPCX_VWEVSM_WIRE, val); reg_val = inst->VWGPSM[reg_idx]; } else { diff --git a/dts/arm/microchip/mec172x/mec172x-vw-routing.dtsi b/dts/arm/microchip/mec172x/mec172x-vw-routing.dtsi index a9ed8e01d96a23..5c3dfddbd141f6 100644 --- a/dts/arm/microchip/mec172x/mec172x-vw-routing.dtsi +++ b/dts/arm/microchip/mec172x/mec172x-vw-routing.dtsi @@ -107,7 +107,7 @@ vw-reg = <0x04 SMVW 0 3>; status = "okay"; }; - vw_slave_boot_done: vw_slave_boot_done { + vw_target_boot_done: vw_target_boot_done { vw-reg = <0x05 SMVW 1 0>; status = "okay"; }; @@ -119,7 +119,7 @@ vw-reg = <0x05 SMVW 1 2>; status = "okay"; }; - vw_slave_boot_status: vw_slave_boot_status { + vw_target_boot_status: vw_target_boot_status { vw-reg = <0x05 SMVW 1 3>; status = "okay"; }; diff --git a/include/zephyr/drivers/espi.h b/include/zephyr/drivers/espi.h index d2f77622fc58a9..d2e64d9c5e4804 100644 --- a/include/zephyr/drivers/espi.h +++ b/include/zephyr/drivers/espi.h @@ -43,7 +43,7 @@ enum espi_io_mode { * @code *+----------------------------------------------------------------------+ *| | - *| eSPI host +-------------+ | + *| eSPI controller +-------------+ | *| +-----------+ | Power | +----------+ | *| |Out of band| | management | | GPIO | | *| +------------+ |processor | | controller | | sources | | @@ -81,7 +81,7 @@ enum espi_io_mode { * +-----------------+ * | *+-----------------------------------------------------------------------+ - *| eSPI slave | + *| eSPI target | *| | *| CH0 | CH1 | CH2 | CH3 | *| eSPI endpoint | VWIRE | OOB | Flash | @@ -138,8 +138,8 @@ enum espi_pc_event { #define ESPI_PERIPHERAL_INDEX_1 1ul #define ESPI_PERIPHERAL_INDEX_2 2ul -#define ESPI_SLAVE_TO_MASTER 0ul -#define ESPI_MASTER_TO_SLAVE 1ul +#define ESPI_TARGET_TO_CONTROLLER 0ul +#define ESPI_CONTROLLER_TO_TARGET 1ul #define ESPI_VWIRE_SRC_ID0 0ul #define ESPI_VWIRE_SRC_ID1 1ul @@ -197,7 +197,7 @@ enum espi_cycle_type { * virtual wire channel */ enum espi_vwire_signal { - /* Virtual wires that can only be send from master to slave */ + /* Virtual wires that can only be send from controller to target */ ESPI_VWIRE_SIGNAL_SLP_S3, ESPI_VWIRE_SIGNAL_SLP_S4, ESPI_VWIRE_SIGNAL_SLP_S5, @@ -214,14 +214,14 @@ enum espi_vwire_signal { ESPI_VWIRE_SIGNAL_SLP_LAN, ESPI_VWIRE_SIGNAL_HOST_C10, ESPI_VWIRE_SIGNAL_DNX_WARN, - /* Virtual wires that can only be sent from slave to master */ + /* Virtual wires that can only be sent from target to controller */ ESPI_VWIRE_SIGNAL_PME, ESPI_VWIRE_SIGNAL_WAKE, ESPI_VWIRE_SIGNAL_OOB_RST_ACK, - ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, + ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, ESPI_VWIRE_SIGNAL_ERR_FATAL, - ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, + ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, ESPI_VWIRE_SIGNAL_HOST_RST_ACK, ESPI_VWIRE_SIGNAL_RST_CPU_INIT, /* System management interrupt */ @@ -231,31 +231,31 @@ enum espi_vwire_signal { ESPI_VWIRE_SIGNAL_DNX_ACK, ESPI_VWIRE_SIGNAL_SUS_ACK, /* - * Virtual wire GPIOs that can be sent from slave to master for + * Virtual wire GPIOs that can be sent from target to controller for * platform specific usage. */ - ESPI_VWIRE_SIGNAL_SLV_GPIO_0, - ESPI_VWIRE_SIGNAL_SLV_GPIO_1, - ESPI_VWIRE_SIGNAL_SLV_GPIO_2, - ESPI_VWIRE_SIGNAL_SLV_GPIO_3, - ESPI_VWIRE_SIGNAL_SLV_GPIO_4, - ESPI_VWIRE_SIGNAL_SLV_GPIO_5, - ESPI_VWIRE_SIGNAL_SLV_GPIO_6, - ESPI_VWIRE_SIGNAL_SLV_GPIO_7, - ESPI_VWIRE_SIGNAL_SLV_GPIO_8, - ESPI_VWIRE_SIGNAL_SLV_GPIO_9, - ESPI_VWIRE_SIGNAL_SLV_GPIO_10, - ESPI_VWIRE_SIGNAL_SLV_GPIO_11, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_0, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_1, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_2, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_3, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_4, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_5, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_6, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_7, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_8, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_9, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_10, + ESPI_VWIRE_SIGNAL_TARGET_GPIO_11, /* Number of Virtual Wires */ ESPI_VWIRE_SIGNAL_COUNT }; /* USB-C port over current */ -#define ESPI_VWIRE_SIGNAL_OCB_0 ESPI_VWIRE_SIGNAL_SLV_GPIO_0 -#define ESPI_VWIRE_SIGNAL_OCB_1 ESPI_VWIRE_SIGNAL_SLV_GPIO_1 -#define ESPI_VWIRE_SIGNAL_OCB_2 ESPI_VWIRE_SIGNAL_SLV_GPIO_2 -#define ESPI_VWIRE_SIGNAL_OCB_3 ESPI_VWIRE_SIGNAL_SLV_GPIO_3 +#define ESPI_VWIRE_SIGNAL_OCB_0 ESPI_VWIRE_SIGNAL_TARGET_GPIO_0 +#define ESPI_VWIRE_SIGNAL_OCB_1 ESPI_VWIRE_SIGNAL_TARGET_GPIO_1 +#define ESPI_VWIRE_SIGNAL_OCB_2 ESPI_VWIRE_SIGNAL_TARGET_GPIO_2 +#define ESPI_VWIRE_SIGNAL_OCB_3 ESPI_VWIRE_SIGNAL_TARGET_GPIO_3 /* eSPI LPC peripherals. */ enum lpc_peripheral_opcode { @@ -482,18 +482,18 @@ __subsystem struct espi_driver_api { * This routine provides a generic interface to override eSPI controller * capabilities. * - * If this eSPI controller is acting as slave, the values set here + * If this eSPI controller is acting as target, the values set here * will be discovered as part through the GET_CONFIGURATION command - * issued by the eSPI master during initialization. + * issued by the eSPI controller during initialization. * - * If this eSPI controller is acting as master, the values set here - * will be used by eSPI master to determine minimum common capabilities with - * eSPI slave then send via SET_CONFIGURATION command. + * If this eSPI controller is acting as controller, the values set here + * will be used by eSPI controller to determine minimum common capabilities with + * eSPI target then send via SET_CONFIGURATION command. * * @code - * +--------+ +---------+ +------+ +---------+ +---------+ - * | eSPI | | eSPI | | eSPI | | eSPI | | eSPI | - * | slave | | driver | | bus | | driver | | host | + * +---------+ +---------+ +------+ +---------+ +---------+ + * | eSPI | | eSPI | | eSPI | | eSPI | | eSPI | + * | target | | driver | | bus | | driver | | host | * +--------+ +---------+ +------+ +---------+ +---------+ * | | | | | * | espi_config | Set eSPI | Set eSPI | espi_config | @@ -522,7 +522,7 @@ __subsystem struct espi_driver_api { * @retval 0 If successful. * @retval -EIO General input / output error, failed to configure device. * @retval -EINVAL invalid capabilities, failed to configure device. - * @retval -ENOTSUP capability not supported by eSPI slave. + * @retval -ENOTSUP capability not supported by eSPI target. */ __syscall int espi_config(const struct device *dev, struct espi_cfg *cfg); @@ -690,10 +690,10 @@ static inline int z_impl_espi_write_lpc_request(const struct device *dev, * @brief Sends system/platform signal as a virtual wire packet. * * This routines provides a generic interface to send a virtual wire packet - * from slave to master. + * from target to controller. * * @param dev Pointer to the device structure for the driver instance. - * @param signal The signal to be send to eSPI master. + * @param signal The signal to be send to eSPI controller. * @param level The level of signal requested LOW or HIGH. * * @retval 0 If successful. @@ -717,13 +717,13 @@ static inline int z_impl_espi_send_vwire(const struct device *dev, * @brief Retrieves level status for a signal encapsulated in a virtual wire. * * This routines provides a generic interface to request a virtual wire packet - * from eSPI master and retrieve the signal level. + * from eSPI controller and retrieve the signal level. * * @param dev Pointer to the device structure for the driver instance. - * @param signal the signal to be requested from eSPI master. + * @param signal the signal to be requested from eSPI controller. * @param level the level of signal requested 0b LOW, 1b HIGH. * - * @retval -EIO General input / output error, failed request to master. + * @retval -EIO General input / output error, failed request to controller. */ __syscall int espi_receive_vwire(const struct device *dev, enum espi_vwire_signal signal, @@ -748,7 +748,7 @@ static inline int z_impl_espi_receive_vwire(const struct device *dev, * @param dev Pointer to the device structure for the driver instance. * @param pckt Address of the packet representation of SMBus transaction. * - * @retval -EIO General input / output error, failed request to master. + * @retval -EIO General input / output error, failed request to controller. */ __syscall int espi_send_oob(const struct device *dev, struct espi_oob_packet *pckt); @@ -775,7 +775,7 @@ static inline int z_impl_espi_send_oob(const struct device *dev, * @param dev Pointer to the device structure for the driver instance. * @param pckt Address of the packet representation of SMBus transaction. * - * @retval -EIO General input / output error, failed request to master. + * @retval -EIO General input / output error, failed request to controller. */ __syscall int espi_receive_oob(const struct device *dev, struct espi_oob_packet *pckt); @@ -797,14 +797,14 @@ static inline int z_impl_espi_receive_oob(const struct device *dev, * @brief Sends a read request packet for shared flash. * * This routines provides an interface to send a request to read the flash - * component shared between the eSPI master and eSPI slaves. + * component shared between the eSPI controller and eSPI targets. * * @param dev Pointer to the device structure for the driver instance. * @param pckt Address of the representation of read flash transaction. * * @retval -ENOTSUP eSPI flash logical channel transactions not supported. - * @retval -EBUSY eSPI flash channel is not ready or disabled by master. - * @retval -EIO General input / output error, failed request to master. + * @retval -EBUSY eSPI flash channel is not ready or disabled by controller. + * @retval -EIO General input / output error, failed request to controller. */ __syscall int espi_read_flash(const struct device *dev, struct espi_flash_packet *pckt); @@ -826,14 +826,14 @@ static inline int z_impl_espi_read_flash(const struct device *dev, * @brief Sends a write request packet for shared flash. * * This routines provides an interface to send a request to write to the flash - * components shared between the eSPI master and eSPI slaves. + * components shared between the eSPI controller and eSPI targets. * * @param dev Pointer to the device structure for the driver instance. * @param pckt Address of the representation of write flash transaction. * * @retval -ENOTSUP eSPI flash logical channel transactions not supported. - * @retval -EBUSY eSPI flash channel is not ready or disabled by master. - * @retval -EIO General input / output error, failed request to master. + * @retval -EBUSY eSPI flash channel is not ready or disabled by controller. + * @retval -EIO General input / output error, failed request to controller. */ __syscall int espi_write_flash(const struct device *dev, struct espi_flash_packet *pckt); @@ -855,14 +855,14 @@ static inline int z_impl_espi_write_flash(const struct device *dev, * @brief Sends a write request packet for shared flash. * * This routines provides an interface to send a request to write to the flash - * components shared between the eSPI master and eSPI slaves. + * components shared between the eSPI controller and eSPI targets. * * @param dev Pointer to the device structure for the driver instance. * @param pckt Address of the representation of write flash transaction. * * @retval -ENOTSUP eSPI flash logical channel transactions not supported. - * @retval -EBUSY eSPI flash channel is not ready or disabled by master. - * @retval -EIO General input / output error, failed request to master. + * @retval -EBUSY eSPI flash channel is not ready or disabled by controller. + * @retval -EIO General input / output error, failed request to controller. */ __syscall int espi_flash_erase(const struct device *dev, struct espi_flash_packet *pckt); diff --git a/samples/drivers/espi/src/main.c b/samples/drivers/espi/src/main.c index ce6cb08c32268e..a51b79776af66f 100644 --- a/samples/drivers/espi/src/main.c +++ b/samples/drivers/espi/src/main.c @@ -881,11 +881,11 @@ int espi_init(void) ret = espi_config(espi_dev, &cfg); if (ret) { - LOG_ERR("Failed to configure eSPI slave channels:%x err: %d", cfg.channel_caps, + LOG_ERR("Failed to configure eSPI target channels:%x err: %d", cfg.channel_caps, ret); return ret; } else { - LOG_INF("eSPI slave configured successfully!"); + LOG_INF("eSPI target configured successfully!"); } LOG_INF("eSPI test - callbacks initialization... "); @@ -1145,20 +1145,20 @@ static int espi_flash_test(uint32_t start_flash_addr, uint8_t blocks) } #endif /* CONFIG_ESPI_FLASH_CHANNEL */ -#ifndef CONFIG_ESPI_AUTOMATIC_BOOT_DONE_ACKNOWLEDGE -static void send_slave_bootdone(void) +#ifndef CONFIG_ESPI_AUTOMATIC_WARNING_ACKNOWLEDGE +static void send_target_bootdone(void) { int ret; uint8_t boot_done; - ret = espi_receive_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, &boot_done); + ret = espi_receive_vwire(espi_dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, &boot_done); LOG_INF("%s boot_done: %d", __func__, boot_done); if (ret) { - LOG_WRN("Fail to retrieve slave boot done"); + LOG_WRN("Fail to retrieve target boot done"); } else if (!boot_done) { - /* SLAVE_BOOT_DONE & SLAVE_LOAD_STS have to be sent together */ - espi_send_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 1); - espi_send_vwire(espi_dev, ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, 1); + /* TARGET_BOOT_DONE & TARGET_LOAD_STS have to be sent together */ + espi_send_vwire(espi_dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 1); + espi_send_vwire(espi_dev, ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 1); } } #endif @@ -1271,9 +1271,9 @@ int espi_test(void) return ret; } -#ifndef CONFIG_ESPI_AUTOMATIC_BOOT_DONE_ACKNOWLEDGE +#ifndef CONFIG_ESPI_AUTOMATIC_WARNING_ACKNOWLEDGE /* When automatic acknowledge is disabled to perform lengthy operations - * in the eSPI slave, need to explicitly send slave boot + * in the eSPI target, need to explicitly send target boot virtual wires */ bool vw_ch_sts; @@ -1285,7 +1285,7 @@ int espi_test(void) k_busy_wait(100); } while (!vw_ch_sts); - send_slave_bootdone(); + send_target_bootdone(); #endif #ifdef CONFIG_ESPI_FLASH_CHANNEL diff --git a/subsys/emul/espi/emul_espi_host.c b/subsys/emul/espi/emul_espi_host.c index 97aaedcb31e757..f1a4a369221717 100644 --- a/subsys/emul/espi/emul_espi_host.c +++ b/subsys/emul/espi/emul_espi_host.c @@ -25,39 +25,40 @@ struct vw_data { /* The level(state) of the virtual wire */ uint8_t level; /* The direction of the virtual wire. Possible values: - * ESPI_MASTER_TO_SLAVE or ESPI_SLAVE_TO_MASTER */ + * ESPI_CONTROLLER_TO_TARGET or ESPI_TARGET_TO_CONTROLLER + */ uint8_t dir; }; /** Declare the default state of virtual wires */ const static struct vw_data vw_state_default[] = { - { ESPI_VWIRE_SIGNAL_SLP_S3, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SLP_S4, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SLP_S5, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SUS_STAT, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_PLTRST, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_OOB_RST_WARN, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_OOB_RST_ACK, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_WAKE, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_PME, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_ERR_FATAL, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_SLV_BOOT_STS, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_SCI, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_SMI, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_RST_CPU_INIT, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_HOST_RST_ACK, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_HOST_RST_WARN, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SUS_ACK, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_DNX_ACK, 0, ESPI_SLAVE_TO_MASTER }, - { ESPI_VWIRE_SIGNAL_SUS_WARN, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SUS_PWRDN_ACK, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SLP_A, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SLP_LAN, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_SLP_WLAN, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_HOST_C10, 0, ESPI_MASTER_TO_SLAVE }, - { ESPI_VWIRE_SIGNAL_DNX_WARN, 0, ESPI_MASTER_TO_SLAVE }, + { ESPI_VWIRE_SIGNAL_SLP_S3, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SLP_S4, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SLP_S5, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SUS_STAT, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_PLTRST, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_OOB_RST_WARN, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_OOB_RST_ACK, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_WAKE, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_PME, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_ERR_FATAL, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_SCI, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_SMI, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_RST_CPU_INIT, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_HOST_RST_ACK, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_HOST_RST_WARN, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SUS_ACK, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_DNX_ACK, 0, ESPI_TARGET_TO_CONTROLLER }, + { ESPI_VWIRE_SIGNAL_SUS_WARN, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SUS_PWRDN_ACK, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SLP_A, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SLP_LAN, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_SLP_WLAN, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_HOST_C10, 0, ESPI_CONTROLLER_TO_TARGET }, + { ESPI_VWIRE_SIGNAL_DNX_WARN, 0, ESPI_CONTROLLER_TO_TARGET }, }; #define NUMBER_OF_VWIRES ARRAY_SIZE(vw_state_default) @@ -131,7 +132,7 @@ static int emul_host_set_vw(const struct emul *target, idx = emul_host_find_index(data, vw); - if (idx < 0 || data->vw_state[idx].dir != ESPI_SLAVE_TO_MASTER) { + if (idx < 0 || data->vw_state[idx].dir != ESPI_TARGET_TO_CONTROLLER) { LOG_ERR("%s: invalid vw: %d", __func__, vw); return -EPERM; } @@ -149,7 +150,7 @@ static int emul_host_get_vw(const struct emul *target, idx = emul_host_find_index(data, vw); - if (idx < 0 || data->vw_state[idx].dir != ESPI_MASTER_TO_SLAVE) { + if (idx < 0 || data->vw_state[idx].dir != ESPI_CONTROLLER_TO_TARGET) { LOG_ERR("%s: invalid vw: %d", __func__, vw); return -EPERM; } @@ -178,7 +179,7 @@ int emul_espi_host_send_vw(const struct device *espi_dev, enum espi_vwire_signal data_host = emul_espi->target->data; idx = emul_host_find_index(data_host, vw); - if (idx < 0 || data_host->vw_state[idx].dir != ESPI_MASTER_TO_SLAVE) { + if (idx < 0 || data_host->vw_state[idx].dir != ESPI_CONTROLLER_TO_TARGET) { LOG_ERR("%s: invalid vw: %d", __func__, vw); return -EPERM; } From 24d6508201ba0ddbab75280de687c9d6f046562f Mon Sep 17 00:00:00 2001 From: Jose Alberto Meza Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0083/1389] doc: eSPI: Update link to eSPI spec Add link to eSPI spec 1.5 Update coding guidelines for eSPI bus Signed-off-by: Jose Alberto Meza --- doc/contribute/coding_guidelines/index.rst | 5 +++-- doc/hardware/peripherals/espi.rst | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/contribute/coding_guidelines/index.rst b/doc/contribute/coding_guidelines/index.rst index 9563cee8919b6c..d502e389eb0f49 100644 --- a/doc/contribute/coding_guidelines/index.rst +++ b/doc/contribute/coding_guidelines/index.rst @@ -1212,8 +1212,8 @@ Related GitHub Issues and Pull Requests are tagged with the `Inclusive Language - * - eSPI - - * ``master / slave`` => TBD - - + - * ``master / slave`` => ``controller / target`` + - Refer to `eSPI Specification`_ for new terminology * - gPTP - * ``master / slave`` => TBD @@ -1254,6 +1254,7 @@ Related GitHub Issues and Pull Requests are tagged with the `Inclusive Language .. _OSHWA Resolution to Redefine SPI Signal Names: https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/ .. _CAN in Automation Inclusive Language news post: https://www.can-cia.org/news/archive/view/?tx_news_pi1%5Bnews%5D=699&tx_news_pi1%5Bday%5D=6&tx_news_pi1%5Bmonth%5D=12&tx_news_pi1%5Byear%5D=2020&cHash=784e79eb438141179386cf7c29ed9438 .. _CAN in Automation Inclusive Language: https://can-newsletter.org/canopen/categories/ +.. _eSPI Specification: https://downloadmirror.intel.com/27055/327432%20espi_base_specification%20R1-5.pdf Rule A.3: Macro name collisions diff --git a/doc/hardware/peripherals/espi.rst b/doc/hardware/peripherals/espi.rst index 62d475da7b97a1..26436e4a2e6e2d 100644 --- a/doc/hardware/peripherals/espi.rst +++ b/doc/hardware/peripherals/espi.rst @@ -8,7 +8,7 @@ Overview The eSPI (enhanced serial peripheral interface) is a serial bus that is based on SPI. It also features a four-wire interface (receive, transmit, clock -and slave select) and three configurations: single IO, dual IO and quad IO. +and target select) and three configurations: single IO, dual IO and quad IO. The technical advancements include lower voltage signal levels (1.8V vs. 3.3V), lower pin count, and the frequency is twice as fast (66MHz vs. 33MHz) @@ -24,4 +24,4 @@ API Reference .. doxygengroup:: espi_interface .. _eSPI interface specification: - https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0_cb.pdf + https://downloadmirror.intel.com/27055/327432%20espi_base_specification%20R1-5.pdf From 538086b398338b3ba95af808062667557ad19c12 Mon Sep 17 00:00:00 2001 From: Jose Alberto Meza Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0084/1389] samples: drivers: espi: Add support for mec172x board Add overlay file for mec172x modular card Signed-off-by: Jose Alberto Meza --- .../espi/boards/mec172xmodular_assy6930.conf | 10 +++ .../boards/mec172xmodular_assy6930.overlay | 75 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 samples/drivers/espi/boards/mec172xmodular_assy6930.conf create mode 100644 samples/drivers/espi/boards/mec172xmodular_assy6930.overlay diff --git a/samples/drivers/espi/boards/mec172xmodular_assy6930.conf b/samples/drivers/espi/boards/mec172xmodular_assy6930.conf new file mode 100644 index 00000000000000..a384c652521062 --- /dev/null +++ b/samples/drivers/espi/boards/mec172xmodular_assy6930.conf @@ -0,0 +1,10 @@ +# eSPI + mec172xevb_assy6906 +CONFIG_ESPI=y +CONFIG_LOG=y +CONFIG_LOG_BUFFER_SIZE=4096 +CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100 +# Disable only for this board to check notifications +CONFIG_ESPI_AUTOMATIC_WARNING_ACKNOWLEDGE=n +# Sample code doesn't handle ACPI host communication +CONFIG_ESPI_PERIPHERAL_HOST_IO=n +# Test SAF flash portal read/erase/write on EVB diff --git a/samples/drivers/espi/boards/mec172xmodular_assy6930.overlay b/samples/drivers/espi/boards/mec172xmodular_assy6930.overlay new file mode 100644 index 00000000000000..f5b7e5483f20e2 --- /dev/null +++ b/samples/drivers/espi/boards/mec172xmodular_assy6930.overlay @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + board_power: resources { + compatible = "microchip,mec172x-board-power"; + /* MCHP_GPIO_012 */ + pwrg-gpios = <&gpio_000_036 10 GPIO_ACTIVE_HIGH>; + /* MCHP_GPIO_0054 */ + rsm-gpios = <&gpio_040_076 12 GPIO_ACTIVE_HIGH>; + }; +}; + + +/* Enable Target to Controller Virtual Wires GPIO 0 - 3 */ +&vw_t2c_gpio_0 { + status = "okay"; + reset-state = "1"; + reset-source = "ESPI_RESET"; +}; + +&vw_t2c_gpio_1 { + status = "okay"; + reset-state = "1"; + reset-source = "ESPI_RESET"; +}; + +&vw_t2c_gpio_2 { + status = "okay"; + reset-state = "1"; + reset-source = "ESPI_RESET"; +}; + +&vw_t2c_gpio_3 { + status = "okay"; + reset-state = "1"; + reset-source = "ESPI_RESET"; +}; + +&spi0 { + status = "okay"; + clock-frequency = <24000000>; + chip-select = <0>; + lines = <4>; +}; + +/* Disable unwanted VWs notifications + * Refer to include/zephyr/drivers/espi.h + */ +&vw_sus_stat_n { + status = "disabled"; +}; + +&vw_smiout_n { + status = "disabled"; +}; + +&vw_nmiout_n { + status = "disabled"; +}; + +&vw_slp_lan_n { + status = "disabled"; +}; + +&vw_slp_wlan_n { + status = "disabled"; +}; + +&vw_host_c10 { + status = "disabled"; +}; From d45dc0261bed9b8882dcdf152690e22ddda30db5 Mon Sep 17 00:00:00 2001 From: Jose Alberto Meza Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0085/1389] doc: Update eSPI sections in migration and release notes Indicate macro and enum changes with respect to new inclusive term in eSPI specification 1.5. Signed-off-by: Jose Alberto Meza --- doc/releases/migration-guide-3.7.rst | 11 +++++++++++ doc/releases/release-notes-3.7.rst | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index a344a3106fe738..5638e40154c89a 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -158,6 +158,17 @@ Controller Area Network (CAN) Display ======= +Enhanced Serial Peripheral Interface (eSPI) +=========================================== + * The macros ``ESPI_SLAVE_TO_MASTER`` and ``ESPI_MASTER_TO_SLAVE`` were renamed to + ``ESPI_TARGET_TO_CONTROLLER`` and ``ESPI_CONTROLLER_TO_TARGET`` respectively to reflect + the new terminology in eSPI 1.5 specification. + * The enum values ``ESPI_VWIRE_SIGNAL_SLV_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE`` and + all ``ESPI_VWIRE_SIGNAL_SLV_GPIO_`` signals were renamed to + ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE`` and + ``ESPI_VWIRE_SIGNAL_TARGET_GPIO_`` respectively to reflect the new terminology + in eSPI 1.5 specification. + Flash ===== diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 814b4847358546..9c3cf6b9de0869 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -167,6 +167,11 @@ Drivers and Sensors * Entropy +* eSPI + + * Renamed eSPI virtual wire direction macros and enum values to match the new terminology in + eSPI 1.5 specification. + * Ethernet * Deperecated eth_mcux driver in favor of the reworked nxp_enet driver. From 673c617a57fcdf0bc094bdaa7f2514a9cfb0763f Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0086/1389] boards: shields: rk055hdmipi4ma0: fix GT911 identifier in RT595 overlay In 42c6f3311be (boards: stop using kscan for LVGL touch input), GT911 node label was renamed for rk055hdmipi4ma0 shield. The node label rename was missed in the RT595 EVK overlay, fix this. Fixes #69302 Signed-off-by: Daniel DeGrasse --- .../boards/mimxrt595_evk_mimxrt595s_cm33.overlay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_mimxrt595s_cm33.overlay b/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_mimxrt595s_cm33.overlay index 04aba30fec012e..bdc2bba1f40eb6 100644 --- a/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_mimxrt595s_cm33.overlay +++ b/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_mimxrt595s_cm33.overlay @@ -13,7 +13,7 @@ }; /* GT911 IRQ GPIO is active low on this board, and needs probing mode */ -&touch_controller_rk055hdmipi4ma0 { +>911_rk055hdmipi4ma0 { irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_LOW>; alt-addr = <0x14>; }; From 117fd16c6827545e5bd0b4db8ceb29dc7943e7fc Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:27 +0200 Subject: [PATCH 0087/1389] drivers: display: display_hx8394: use MIPI LPM during init commands Although not documented in the HX8394 datasheet, it seems that the display fails to initialize if MIPI HS mode is used to send configuration commands. Therefore, we must make sure all initialization commands are sent with the MIPI_DSI_MSG_USE_LPM flag set. Signed-off-by: Daniel DeGrasse --- drivers/display/display_hx8394.c | 137 +++++++++++++++++++------------ 1 file changed, 86 insertions(+), 51 deletions(-) diff --git a/drivers/display/display_hx8394.c b/drivers/display/display_hx8394.c index b14846ae343853..e6e67161d32b9f 100644 --- a/drivers/display/display_hx8394.c +++ b/drivers/display/display_hx8394.c @@ -406,6 +406,37 @@ const uint8_t hx8394_cmd3[] = {0xC6U, 0xEDU}; const uint8_t tear_config[] = {HX8394_SET_TEAR, HX8394_TEAR_VBLANK}; +static ssize_t hx8394_mipi_tx(const struct device *mipi_dev, uint8_t channel, + const void *buf, size_t len) +{ + /* Send MIPI transfers using low power mode */ + struct mipi_dsi_msg msg = { + .tx_buf = buf, + .tx_len = len, + .flags = MIPI_DSI_MSG_USE_LPM, + }; + + switch (len) { + case 0U: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM; + break; + + case 1U: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM; + break; + + case 2U: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM; + break; + + default: + msg.type = MIPI_DSI_GENERIC_LONG_WRITE; + break; + } + + return mipi_dsi_transfer(mipi_dev, channel, &msg); +} + static int hx8394_write(const struct device *dev, const uint16_t x, const uint16_t y, const struct display_buffer_descriptor *desc, @@ -477,7 +508,7 @@ static int hx8394_set_orientation(const struct device *dev, default: return -ENOTSUP; } - return mipi_dsi_generic_write(config->mipi_dsi, config->channel, param, 2); + return hx8394_mipi_tx(config->mipi_dsi, config->channel, param, 2); } static void hx8394_get_capabilities(const struct device *dev, @@ -557,66 +588,66 @@ static int hx8394_init(const struct device *dev) k_sleep(K_MSEC(50)); } /* Enable extended commands */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - enable_extension, sizeof(enable_extension)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + enable_extension, sizeof(enable_extension)); if (ret < 0) { return ret; } /* Set the number of lanes to DSISETUP0 parameter */ setmipi[1] |= (config->num_of_lanes - 1); - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - setmipi, sizeof(setmipi)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + setmipi, sizeof(setmipi)); if (ret < 0) { return ret; } /* Set scan direction */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - address_config, sizeof(address_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + address_config, sizeof(address_config)); if (ret < 0) { return ret; } /* Set voltage and current targets */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - power_config, sizeof(power_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + power_config, sizeof(power_config)); if (ret < 0) { return ret; } /* Setup display line count and front/back porch size */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - line_config, sizeof(line_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + line_config, sizeof(line_config)); if (ret < 0) { return ret; } /* Setup display cycle counts (in counts of TCON CLK) */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - cycle_config, sizeof(cycle_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + cycle_config, sizeof(cycle_config)); if (ret < 0) { return ret; } /* Set group delay values */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - gip0_config, sizeof(gip0_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + gip0_config, sizeof(gip0_config)); if (ret < 0) { return ret; } /* Set group clock selections */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - gip1_config, sizeof(gip1_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + gip1_config, sizeof(gip1_config)); if (ret < 0) { return ret; } /* Set group clock selections for GS mode */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - gip2_config, sizeof(gip2_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + gip2_config, sizeof(gip2_config)); if (ret < 0) { return ret; } @@ -627,15 +658,15 @@ static int hx8394_init(const struct device *dev) */ k_msleep(1); /* Set VCOM voltage config */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - vcom_config, sizeof(vcom_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + vcom_config, sizeof(vcom_config)); if (ret < 0) { return ret; } /* Set manufacturer supplied gamma values */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - gamma_config, sizeof(gamma_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + gamma_config, sizeof(gamma_config)); if (ret < 0) { return ret; } @@ -643,15 +674,15 @@ static int hx8394_init(const struct device *dev) /* This command is not documented in datasheet, but is included * in the display initialization done by MCUXpresso SDK */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - hx8394_cmd1, sizeof(hx8394_cmd1)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + hx8394_cmd1, sizeof(hx8394_cmd1)); if (ret < 0) { return ret; } /* Set panel to BGR mode, and reverse colors */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - panel_config, sizeof(panel_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + panel_config, sizeof(panel_config)); if (ret < 0) { return ret; } @@ -659,8 +690,8 @@ static int hx8394_init(const struct device *dev) /* This command is not documented in datasheet, but is included * in the display initialization done by MCUXpresso SDK */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - hx8394_cmd2, sizeof(hx8394_cmd2)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + hx8394_cmd2, sizeof(hx8394_cmd2)); if (ret < 0) { return ret; } @@ -668,43 +699,43 @@ static int hx8394_init(const struct device *dev) /* Write values to manufacturer register banks */ param[0] = HX8394_SETBANK; param[1] = 0x2; - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - param, 2); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + param, 2); if (ret < 0) { return ret; } - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - hx8394_bank2, sizeof(hx8394_bank2)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + hx8394_bank2, sizeof(hx8394_bank2)); if (ret < 0) { return ret; } param[1] = 0x0; - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - param, 2); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + param, 2); if (ret < 0) { return ret; } /* Select bank 1 */ param[1] = 0x1; - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - param, 2); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + param, 2); if (ret < 0) { return ret; } - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - hx8394_bank1, sizeof(hx8394_bank1)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + hx8394_bank1, sizeof(hx8394_bank1)); if (ret < 0) { return ret; } /* Select bank 0 */ param[1] = 0x0; - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - param, 2); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + param, 2); if (ret < 0) { return ret; } - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - hx8394_bank0, sizeof(hx8394_bank0)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + hx8394_bank0, sizeof(hx8394_bank0)); if (ret < 0) { return ret; } @@ -712,27 +743,31 @@ static int hx8394_init(const struct device *dev) /* This command is not documented in datasheet, but is included * in the display initialization done by MCUXpresso SDK */ - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - hx8394_cmd3, sizeof(hx8394_cmd3)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + hx8394_cmd3, sizeof(hx8394_cmd3)); if (ret < 0) { return ret; } - ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, - tear_config, sizeof(tear_config)); + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + tear_config, sizeof(tear_config)); if (ret < 0) { return ret; } - ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, - MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + param[0] = MIPI_DCS_EXIT_SLEEP_MODE; + + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + param, 1); if (ret < 0) { return ret; } /* We must delay 120ms after exiting sleep mode per datasheet */ k_sleep(K_MSEC(120)); - ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, - MIPI_DCS_SET_DISPLAY_ON, NULL, 0); + + param[0] = MIPI_DCS_SET_DISPLAY_ON; + ret = hx8394_mipi_tx(config->mipi_dsi, config->channel, + param, 1); if (config->bl_gpio.port != NULL) { ret = gpio_pin_configure_dt(&config->bl_gpio, GPIO_OUTPUT_ACTIVE); From 1bcaea9fdf7d2ef747dc03dce557c42a583db159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0088/1389] samples: mgmt: hawkbit: docs: reflect change in reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hawkbit is rebooting automatically after installing a new update, reflect that change in the docs. Signed-off-by: Fin Maaß --- samples/subsys/mgmt/hawkbit/README.rst | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/samples/subsys/mgmt/hawkbit/README.rst b/samples/subsys/mgmt/hawkbit/README.rst index 6c472e5e047dc5..8acad7d7ea48a7 100644 --- a/samples/subsys/mgmt/hawkbit/README.rst +++ b/samples/subsys/mgmt/hawkbit/README.rst @@ -168,24 +168,14 @@ following command: And then wait. The board will ping the server, check if there are any new updates, and then download the update you've just created. If everything goes -fine the message ``Image flashed successfully, you can reboot now`` will be -printed on the terminal. +fine the message ``Update installed`` will be printed on the terminal. -Step 9: Reboot the system -========================= - -In the terminal you used for debugging the board, type the following command: - -.. code-block:: console - - kernel reboot cold - -Your board will reboot and then start with the new image. After rebooting, the +Your board will reboot automatically and then start with the new image. After rebooting, the board will print a different image build time then automatically ping the server -again and the message ``No update available`` will be printed on the terminal. +again and the message ``Image is already updated`` will be printed on the terminal. -Step 10: Clone and build hawkbit with https -=========================================== +Step 9: Clone and build hawkbit with https +========================================== Below steps clone and build the hawkbit with self-signed certificate to support https. @@ -287,7 +277,7 @@ Change authentication security from false to true. java -jar ./hawkbit-runtime/hawkbit-update-server/target/ \ hawkbit-update-server-#version#-SNAPSHOT.jar -Step 11: Build hawkBit HTTPS +Step 10: Build hawkBit HTTPS ============================ * Convert the server.pem file to self_sign.der and place the der file in From 25dc20dcaea354c26c1192516bbd0f87dba5bc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0089/1389] sample: mgmt: hawkbit: sign image by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sign the image by default by using the Kconfig options. Signed-off-by: Fin Maaß --- samples/subsys/mgmt/hawkbit/README.rst | 47 +++++++------------------- samples/subsys/mgmt/hawkbit/prj.conf | 3 ++ 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/samples/subsys/mgmt/hawkbit/README.rst b/samples/subsys/mgmt/hawkbit/README.rst index 8acad7d7ea48a7..969fcc7f5063f9 100644 --- a/samples/subsys/mgmt/hawkbit/README.rst +++ b/samples/subsys/mgmt/hawkbit/README.rst @@ -97,27 +97,13 @@ and port during runtime, you can use the following command: .. _hawkbit_sample_sign: -Step 5: Sign and confirm the first image -======================================== +The firmware will be signed automatically by the build system with the +``root-rsa-2048.pem`` key. The key is located in the MCUboot repository. -From this section onwards you use a binary (``.bin``) image format. - -.. code-block:: console - - west sign -t imgtool -- --key \ - ~/zephyrproject/bootloader/mcuboot/root-rsa-2048.pem --confirm \ - --version 1.0.0 - -The command above creates a signed and confirmed image file called -:file:`zephyr.signed.confirmed.bin` in the build directory. It's important for -the first image to be confirmed as MCUboot isn't able to confirm an image that -is flashed using a hardware tool, and hawkBit will reboot to trigger a firmware -swap if it isn't able to confirm the running image on init. - -Step 6: Flash the first image +Step 5: Flash the first image ============================= -Upload the :file:`zephyr.signed.confirmed.bin` file from Step 5 to image slot-0 +Upload the :file:`zephyr.signed.confirmed.bin` file to image slot-0 of your board. .. code-block:: console @@ -129,22 +115,13 @@ time to the console. After it connects to the internet, in hawkbit server UI, you should see the ``frdm_k64f`` show up in the Targets pane. It's time to upload a firmware binary to the server, and update it using this UI. -Step 7: Building and signing the test image +Step 6: Building and signing the test image =========================================== The easiest way to test the functionality of hawkBit is to repeat step 4 to -build the sample again, so that the build time will be different. Then, similar -to step 5, sign the image and assign it a different version number but without -confirming it like so: - -.. code-block:: console - - west sign -t imgtool -- --key \ - ~/zephyrproject/bootloader/mcuboot/root-rsa-2048.pem \ - --version 1.0.1 +build the sample again, so that the build time will be different. -The command above creates a signed image file called -:file:`zephyr.signed.bin` in the build directory. +This time you need the file :file:`zephyr.signed.bin` from the build directory. Upload the signed image to the server. Click Upload icon in left pane of UI and create a new Software Module with type Apps (``name:hawkbit,version:1.0.1``). @@ -156,7 +133,7 @@ hawkBit software module to the created distribution. Click on Deployment icon in the left pane of UI and assign the ``frdm_k64f_update`` distribution to the target ``frdm_k64f``. -Step 8: Run the update +Step 7: Run the update ====================== Back in the terminal session that you used for debugging the board, type the @@ -174,7 +151,7 @@ Your board will reboot automatically and then start with the new image. After re board will print a different image build time then automatically ping the server again and the message ``Image is already updated`` will be printed on the terminal. -Step 9: Clone and build hawkbit with https +Step 8: Clone and build hawkbit with https ========================================== Below steps clone and build the hawkbit with self-signed certificate @@ -277,8 +254,8 @@ Change authentication security from false to true. java -jar ./hawkbit-runtime/hawkbit-update-server/target/ \ hawkbit-update-server-#version#-SNAPSHOT.jar -Step 10: Build hawkBit HTTPS -============================ +Step 9: Build hawkBit HTTPS +=========================== * Convert the server.pem file to self_sign.der and place the der file in hawkbit/src directory @@ -291,4 +268,4 @@ Step 10: Build hawkBit HTTPS :conf: "prj.conf overlay-tls.conf" :goals: build -Repeat the steps from 5 to 9, to update the device over https. +Repeat the steps from 5 to 7, to update the device over https. diff --git a/samples/subsys/mgmt/hawkbit/prj.conf b/samples/subsys/mgmt/hawkbit/prj.conf index 8feda355f28aef..a47b5275f89fdc 100644 --- a/samples/subsys/mgmt/hawkbit/prj.conf +++ b/samples/subsys/mgmt/hawkbit/prj.conf @@ -15,6 +15,9 @@ CONFIG_DNS_RESOLVER=y CONFIG_JSON_LIBRARY=y CONFIG_BOOTLOADER_MCUBOOT=y CONFIG_SETTINGS=y +CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE=n +CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE=y +CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="./bootloader/mcuboot/root-rsa-2048.pem" #Main Stack Size CONFIG_MAIN_STACK_SIZE=4096 From cc60f8fccf7b9c27bf982abe75100dc96d22b950 Mon Sep 17 00:00:00 2001 From: Romain Pelletant Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0090/1389] dts: st: add stm32c011X6 support Provide support for STM32C011X6 family support Signed-off-by: Romain Pelletant --- dts/arm/st/c0/stm32c011.dtsi | 13 +++++++++++++ dts/arm/st/c0/stm32c011X6.dtsi | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 dts/arm/st/c0/stm32c011.dtsi create mode 100644 dts/arm/st/c0/stm32c011X6.dtsi diff --git a/dts/arm/st/c0/stm32c011.dtsi b/dts/arm/st/c0/stm32c011.dtsi new file mode 100644 index 00000000000000..a31961384780d2 --- /dev/null +++ b/dts/arm/st/c0/stm32c011.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Kickmaker + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32c011", "st,stm32c0", "simple-bus"; + }; +}; diff --git a/dts/arm/st/c0/stm32c011X6.dtsi b/dts/arm/st/c0/stm32c011X6.dtsi new file mode 100644 index 00000000000000..d5be6b7e7d81a6 --- /dev/null +++ b/dts/arm/st/c0/stm32c011X6.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Kickmaker + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(6)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(32)>; + }; + }; + }; +}; From fca5aab42a76bce733ef3ea1ae453d46ae079760 Mon Sep 17 00:00:00 2001 From: Romain Pelletant Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0091/1389] soc: st: add stm32c011xx support Add STM32C011XX familly support Signed-off-by: Romain Pelletant --- soc/st/stm32/soc.yml | 1 + soc/st/stm32/stm32c0x/Kconfig.defconfig.stm32c011xx | 11 +++++++++++ soc/st/stm32/stm32c0x/Kconfig.soc | 5 +++++ 3 files changed, 17 insertions(+) create mode 100644 soc/st/stm32/stm32c0x/Kconfig.defconfig.stm32c011xx diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index 304ab56acfc686..2572f6b0f0c7cd 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -3,6 +3,7 @@ family: series: - name: stm32c0x socs: + - name: stm32c011xx - name: stm32c031xx - name: stm32f0x socs: diff --git a/soc/st/stm32/stm32c0x/Kconfig.defconfig.stm32c011xx b/soc/st/stm32/stm32c0x/Kconfig.defconfig.stm32c011xx new file mode 100644 index 00000000000000..ace25ef8137ac2 --- /dev/null +++ b/soc/st/stm32/stm32c0x/Kconfig.defconfig.stm32c011xx @@ -0,0 +1,11 @@ +# STMicroelectronics STM32C011xx MCU + +# Copyright (c) 2024 Kickmaker +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32C011XX + +config NUM_IRQS + default 29 + +endif # SOC_STM32C011XX diff --git a/soc/st/stm32/stm32c0x/Kconfig.soc b/soc/st/stm32/stm32c0x/Kconfig.soc index c91158abbb15f0..57a833c82f0367 100644 --- a/soc/st/stm32/stm32c0x/Kconfig.soc +++ b/soc/st/stm32/stm32c0x/Kconfig.soc @@ -14,5 +14,10 @@ config SOC_STM32C031XX bool select SOC_SERIES_STM32C0X +config SOC_STM32C011XX + bool + select SOC_SERIES_STM32C0X + config SOC + default "stm32c011xx" if SOC_STM32C011XX default "stm32c031xx" if SOC_STM32C031XX From 14f0e03447901997de28fd0b020994be9aa97b8c Mon Sep 17 00:00:00 2001 From: Romain Pelletant Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0092/1389] boards: st: add stm32c0116_dk board support Add board support for stm32c0116_dk Signed-off-by: Romain Pelletant --- boards/st/stm32c0116_dk/Kconfig.stm32c0116_dk | 5 + boards/st/stm32c0116_dk/board.cmake | 8 + boards/st/stm32c0116_dk/board.yml | 5 + .../stm32c0116_dk/doc/img/stm32c0116_dk.jpg | Bin 0 -> 35202 bytes boards/st/stm32c0116_dk/doc/index.rst | 154 ++++++++++++++++++ boards/st/stm32c0116_dk/stm32c0116_dk.dts | 125 ++++++++++++++ boards/st/stm32c0116_dk/stm32c0116_dk.yaml | 19 +++ .../st/stm32c0116_dk/stm32c0116_dk_defconfig | 19 +++ 8 files changed, 335 insertions(+) create mode 100644 boards/st/stm32c0116_dk/Kconfig.stm32c0116_dk create mode 100644 boards/st/stm32c0116_dk/board.cmake create mode 100644 boards/st/stm32c0116_dk/board.yml create mode 100644 boards/st/stm32c0116_dk/doc/img/stm32c0116_dk.jpg create mode 100644 boards/st/stm32c0116_dk/doc/index.rst create mode 100644 boards/st/stm32c0116_dk/stm32c0116_dk.dts create mode 100644 boards/st/stm32c0116_dk/stm32c0116_dk.yaml create mode 100644 boards/st/stm32c0116_dk/stm32c0116_dk_defconfig diff --git a/boards/st/stm32c0116_dk/Kconfig.stm32c0116_dk b/boards/st/stm32c0116_dk/Kconfig.stm32c0116_dk new file mode 100644 index 00000000000000..5ec2bb6264a2ae --- /dev/null +++ b/boards/st/stm32c0116_dk/Kconfig.stm32c0116_dk @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Kickmaker +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32C0116_DK + select SOC_STM32C011XX diff --git a/boards/st/stm32c0116_dk/board.cmake b/boards/st/stm32c0116_dk/board.cmake new file mode 100644 index 00000000000000..92d0dbb2924d30 --- /dev/null +++ b/boards/st/stm32c0116_dk/board.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Kickmaker +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=STM32C011F6" "--speed=4000") +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/st/stm32c0116_dk/board.yml b/boards/st/stm32c0116_dk/board.yml new file mode 100644 index 00000000000000..1764907618b79d --- /dev/null +++ b/boards/st/stm32c0116_dk/board.yml @@ -0,0 +1,5 @@ +board: + name: stm32c0116_dk + vendor: st + socs: + - name: stm32c011xx diff --git a/boards/st/stm32c0116_dk/doc/img/stm32c0116_dk.jpg b/boards/st/stm32c0116_dk/doc/img/stm32c0116_dk.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bacdc93ad4c567b167f9992b1010824849014f33 GIT binary patch literal 35202 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 +#include + +/ { + model = "STMicroelectronics STM32C0116-DK Discovery board"; + compatible = "st,stm32c011f6-dk"; + + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds: leds { + compatible = "gpio-leds"; + green_led_3: led_3 { + gpios = <&gpiob 6 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm1 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + reset_button: button { + label = "reset button"; + gpios = <&gpiof 2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; + + aliases { + led0 = &green_led_3; + pwm-led0 = &green_pwm_led; + sw0 = &reset_button; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref; + }; +}; + +&clk_hsi { + status = "okay"; +}; + +&rcc { + clocks = <&clk_hsi>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&timers1 { + st,prescaler = <10000>; + status = "okay"; + + pwm1: pwm { + pinctrl-0 = <&tim1_ch3_pb6>; + pinctrl-names = "default"; + status = "okay"; + }; +}; + +&adc1 { + pinctrl-0 = <&adc1_in8_pa8>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&die_temp { + status = "okay"; +}; + +&vref { + status = "okay"; +}; + +&dma1 { + status = "okay"; +}; + +&dmamux1 { + status = "okay"; +}; diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk.yaml b/boards/st/stm32c0116_dk/stm32c0116_dk.yaml new file mode 100644 index 00000000000000..319a90afd74b83 --- /dev/null +++ b/boards/st/stm32c0116_dk/stm32c0116_dk.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Kickmaker +# SPDX-License-Identifier: Apache-2.0 + +identifier: stm32c0116_dk +name: STM32C0116 DK +type: mcu +arch: arm +toolchain: + - zephyr +supported: + - gpio + - counter + - watchdog + - pwm + - adc + - dma +ram: 6 +flash: 32 +vendor: st diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk_defconfig b/boards/st/stm32c0116_dk/stm32c0116_dk_defconfig new file mode 100644 index 00000000000000..247a0d666a5a3b --- /dev/null +++ b/boards/st/stm32c0116_dk/stm32c0116_dk_defconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Kickmaker +# SPDX-License-Identifier: Apache-2.0 + +# Serial Drivers +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# GPIO Controller +CONFIG_GPIO=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# enable pin controller +CONFIG_PINCTRL=y From 438a457932e56c3768f6a89665903baad1753845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0093/1389] arm: fatal: log which IRQn is triggering on spurious IRQs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LOG which IRQn line is triggering on spurious IRQs as this makes it much easier to debug spurious IRQs. The new logs with this patch looks like: os: Unhandled IRQn: 227 os: >>> ZEPHYR FATAL ERROR 1: Unhandled interrupt on CPU 0 os: Current thread: 0x20032c20 (unknown) os: Halting system Signed-off-by: Sebastian Bøe --- arch/arm/core/fatal.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/core/fatal.c b/arch/arm/core/fatal.c index c5adebf8ee7fb8..4364d48d45d574 100644 --- a/arch/arm/core/fatal.c +++ b/arch/arm/core/fatal.c @@ -73,6 +73,16 @@ void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf) esf_dump(esf); } #endif /* CONFIG_EXCEPTION_DEBUG */ + + /* LOG the IRQn that was unhandled */ +#if defined(CONFIG_CPU_CORTEX_M) + if (reason == K_ERR_SPURIOUS_IRQ) { + uint32_t irqn = __get_IPSR() - 16; + + LOG_ERR("Unhandled IRQn: %d", irqn); + } +#endif + z_fatal_error(reason, esf); } From db834affd8c2e110d38c981d9a171a04fc50e32b Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0094/1389] samples: drivers: gnss: boards: adjust mimxrt1062 dts overlay The overlay for the mimxrt1062 boards gnss alias is pointing to the uart node rather than the gnss node. Adjust gnss alias and node naming. Signed-off-by: Bjarki Arge Andreasen --- samples/drivers/gnss/boards/mimxrt1062_fmurt6.overlay | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/drivers/gnss/boards/mimxrt1062_fmurt6.overlay b/samples/drivers/gnss/boards/mimxrt1062_fmurt6.overlay index 37942aed9ba9b1..d4420c4239337b 100644 --- a/samples/drivers/gnss/boards/mimxrt1062_fmurt6.overlay +++ b/samples/drivers/gnss/boards/mimxrt1062_fmurt6.overlay @@ -6,7 +6,7 @@ / { aliases { - gnss = &lpuart2; + gnss = &gnss; }; }; @@ -17,7 +17,7 @@ pinctrl-1 = <&pinmux_lpuart2_sleep>; pinctrl-names = "default", "sleep"; - u_blox_m10: u-blox,m10 { + gnss: u_blox_m10 { status = "okay"; compatible = "u-blox,m10"; uart-baudrate = <115200>; From db9be3016c00b80540fe55992bb7699122d13f33 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0095/1389] drivers: gnss: gnss_lcx6g: replace spinlock with sem Use semaphore instead of spinlock for mutual exclusion. The spinlock is improperly used for mutual exclusion, leading to timeouts and other unintended behavior as ISRs are disabled. Signed-off-by: Bjarki Arge Andreasen --- drivers/gnss/gnss_quectel_lcx6g.c | 55 ++++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/gnss/gnss_quectel_lcx6g.c b/drivers/gnss/gnss_quectel_lcx6g.c index 6d632f147bffdd..d3ac854ae96631 100644 --- a/drivers/gnss/gnss_quectel_lcx6g.c +++ b/drivers/gnss/gnss_quectel_lcx6g.c @@ -74,7 +74,7 @@ struct quectel_lcx6g_data { enum gnss_navigation_mode navigation_mode_response; }; - struct k_spinlock lock; + struct k_sem lock; k_timeout_t pm_timeout; }; @@ -160,6 +160,20 @@ static int quectel_lcx6g_configure_pps(const struct device *dev) return modem_chat_run_script(&data->chat, &data->dynamic_script); } +static void quectel_lcx6g_lock(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + + (void)k_sem_take(&data->lock, K_FOREVER); +} + +static void quectel_lcx6g_unlock(const struct device *dev) +{ + struct quectel_lcx6g_data *data = dev->data; + + k_sem_give(&data->lock); +} + static void quectel_lcx6g_pm_changed(const struct device *dev) { struct quectel_lcx6g_data *data = dev->data; @@ -254,11 +268,9 @@ static int quectel_lcx6g_turn_off(const struct device *dev) static int quectel_lcx6g_pm_action(const struct device *dev, enum pm_device_action action) { - struct quectel_lcx6g_data *data = dev->data; - k_spinlock_key_t key; int ret = -ENOTSUP; - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); switch (action) { case PM_DEVICE_ACTION_SUSPEND: @@ -284,7 +296,7 @@ static int quectel_lcx6g_pm_action(const struct device *dev, enum pm_device_acti quectel_lcx6g_pm_changed(dev); - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return ret; } #endif /* CONFIG_PM_DEVICE */ @@ -292,14 +304,13 @@ static int quectel_lcx6g_pm_action(const struct device *dev, enum pm_device_acti static int quectel_lcx6g_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) { struct quectel_lcx6g_data *data = dev->data; - k_spinlock_key_t key; int ret; if (fix_interval_ms < 100 || fix_interval_ms > 1000) { return -EINVAL; } - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), "PAIR050,%u", fix_interval_ms); @@ -323,7 +334,7 @@ static int quectel_lcx6g_set_fix_rate(const struct device *dev, uint32_t fix_int } unlock_return: - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return ret; } @@ -347,10 +358,9 @@ static void quectel_lcx6g_get_fix_rate_callback(struct modem_chat *chat, char ** static int quectel_lcx6g_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) { struct quectel_lcx6g_data *data = dev->data; - k_spinlock_key_t key; int ret; - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), "PAIR051"); @@ -373,7 +383,7 @@ static int quectel_lcx6g_get_fix_rate(const struct device *dev, uint32_t *fix_in *fix_interval_ms = data->fix_rate_response; unlock_return: - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return 0; } @@ -381,7 +391,6 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, enum gnss_navigation_mode mode) { struct quectel_lcx6g_data *data = dev->data; - k_spinlock_key_t key; uint8_t navigation_mode = 0; int ret; @@ -403,7 +412,7 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, break; } - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), "PAIR080,%u", navigation_mode); @@ -427,7 +436,7 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, } unlock_return: - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return ret; } @@ -468,10 +477,9 @@ static int quectel_lcx6g_get_navigation_mode(const struct device *dev, enum gnss_navigation_mode *mode) { struct quectel_lcx6g_data *data = dev->data; - k_spinlock_key_t key; int ret; - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), "PAIR081"); @@ -494,7 +502,7 @@ static int quectel_lcx6g_get_navigation_mode(const struct device *dev, *mode = data->navigation_mode_response; unlock_return: - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return ret; } @@ -502,7 +510,6 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst { struct quectel_lcx6g_data *data = dev->data; gnss_systems_t supported_systems; - k_spinlock_key_t key; int ret; supported_systems = (GNSS_SYSTEM_GPS | GNSS_SYSTEM_GLONASS | GNSS_SYSTEM_GALILEO | @@ -512,7 +519,7 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst return -EINVAL; } - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), "PAIR066,%u,%u,%u,%u,%u,0", @@ -562,7 +569,7 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst } unlock_return: - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return ret; } @@ -603,10 +610,9 @@ static void quectel_lcx6g_get_sbas_status_callback(struct modem_chat *chat, char static int quectel_lcx6g_get_enabled_systems(const struct device *dev, gnss_systems_t *systems) { struct quectel_lcx6g_data *data = dev->data; - k_spinlock_key_t key; int ret; - key = k_spin_lock(&data->lock); + quectel_lcx6g_lock(dev); ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), "PAIR067"); @@ -647,7 +653,7 @@ static int quectel_lcx6g_get_enabled_systems(const struct device *dev, gnss_syst *systems = data->enabled_systems_response; unlock_return: - k_spin_unlock(&data->lock, key); + quectel_lcx6g_unlock(dev); return ret; } @@ -746,8 +752,11 @@ static void quectel_lcx6g_init_dynamic_script(const struct device *dev) static int quectel_lcx6g_init(const struct device *dev) { + struct quectel_lcx6g_data *data = dev->data; int ret; + k_sem_init(&data->lock, 1, 1); + ret = quectel_lcx6g_init_nmea0183_match(dev); if (ret < 0) { return ret; From 10cad5ffa2c8f4afdb704fe0f6342b860107a773 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0096/1389] drivers: gnss: gnss_publish: Use sem for locking The gnss_publish incorrectly uses a spinlock for mutual exclusion when publishing data and satellites. Update it to use a binary semaphore. Signed-off-by: Bjarki Arge Andreasen --- drivers/gnss/gnss_publish.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gnss/gnss_publish.c b/drivers/gnss/gnss_publish.c index 7ddfa5e09fe059..309c8560dd1f63 100644 --- a/drivers/gnss/gnss_publish.c +++ b/drivers/gnss/gnss_publish.c @@ -8,29 +8,33 @@ #include #include -static struct k_spinlock lock; +static K_SEM_DEFINE(semlock, 1, 1); void gnss_publish_data(const struct device *dev, const struct gnss_data *data) { - K_SPINLOCK(&lock) { - STRUCT_SECTION_FOREACH(gnss_data_callback, callback) { - if (callback->dev == NULL || callback->dev == dev) { - callback->callback(dev, data); - } + (void)k_sem_take(&semlock, K_FOREVER); + + STRUCT_SECTION_FOREACH(gnss_data_callback, callback) { + if (callback->dev == NULL || callback->dev == dev) { + callback->callback(dev, data); } } + + k_sem_give(&semlock); } #if CONFIG_GNSS_SATELLITES void gnss_publish_satellites(const struct device *dev, const struct gnss_satellite *satellites, uint16_t size) { - K_SPINLOCK(&lock) { - STRUCT_SECTION_FOREACH(gnss_satellites_callback, callback) { - if (callback->dev == NULL || callback->dev == dev) { - callback->callback(dev, satellites, size); - } + (void)k_sem_take(&semlock, K_FOREVER); + + STRUCT_SECTION_FOREACH(gnss_satellites_callback, callback) { + if (callback->dev == NULL || callback->dev == dev) { + callback->callback(dev, satellites, size); } } + + k_sem_give(&semlock); } #endif From b821e6029a311b16f99f43a989176bd2121fa05c Mon Sep 17 00:00:00 2001 From: Jeferson Fernando Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0097/1389] lorawan: add channels mask configuration. Add channels mask configuration for LoRaWAN, creating a request for LoRaMAC. This change is needed because using LoRaWAN with ABP activation without configuring channels mask will provide no acceptable channels on data transmit, causing data loss. Signed-off-by: Jeferson Fernando --- include/zephyr/lorawan/lorawan.h | 31 ++++++++++++++++ subsys/lorawan/lorawan.c | 63 +++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/include/zephyr/lorawan/lorawan.h b/include/zephyr/lorawan/lorawan.h index 4ce1605237a698..058c4cbabc7034 100644 --- a/include/zephyr/lorawan/lorawan.h +++ b/include/zephyr/lorawan/lorawan.h @@ -41,6 +41,22 @@ enum lorawan_act_type { LORAWAN_ACT_ABP, /**< Activation by Personalization (ABP) */ }; +/** + * @brief LoRaWAN channels mask sizes. + */ +enum lorawan_channels_mask_size { + LORAWAN_CHANNELS_MASK_SIZE_AS923 = 1, /**< Region AS923 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_AU915 = 6, /**< Region AU915 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_CN470 = 6, /**< Region CN470 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_CN779 = 1, /**< Region CN779 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_EU433 = 1, /**< Region EU433 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_EU868 = 1, /**< Region EU868 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_KR920 = 1, /**< Region KR920 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_IN865 = 1, /**< Region IN865 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_US915 = 6, /**< Region US915 mask size */ + LORAWAN_CHANNELS_MASK_SIZE_RU864 = 1, /**< Region RU864 mask size */ +}; + /** * @brief LoRaWAN datarate types. */ @@ -295,6 +311,21 @@ int lorawan_set_conf_msg_tries(uint8_t tries); */ void lorawan_enable_adr(bool enable); +/** + * @brief Set the channels mask. + * + * Change the default channels mask. When mask is not changed, all the channels + * can be used for data transmission. Some Network Servers don't use all the channels, + * in this case, the channels mask must be provided. + * + * @param channels_mask Buffer with channels mask to be used. + * @param channels_mask_size Size of channels mask buffer. + * + * @retval 0 successful + * @retval -EINVAL channels mask or channels mask size is wrong + */ +int lorawan_set_channels_mask(uint16_t *channels_mask, size_t channels_mask_size); + /** * @brief Set the default data rate * diff --git a/subsys/lorawan/lorawan.c b/subsys/lorawan/lorawan.c index 56731dfc4542dc..2213c0dccf409e 100644 --- a/subsys/lorawan/lorawan.c +++ b/subsys/lorawan/lorawan.c @@ -16,25 +16,35 @@ #include "nvm/lorawan_nvm.h" #ifdef CONFIG_LORAMAC_REGION_AS923 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_AS923 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_AS923 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_AS923 #elif CONFIG_LORAMAC_REGION_AU915 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_AU915 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_AU915 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_AU915 #elif CONFIG_LORAMAC_REGION_CN470 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_CN470 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_CN470 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_CN470 #elif CONFIG_LORAMAC_REGION_CN779 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_CN779 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_CN779 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_CN779 #elif CONFIG_LORAMAC_REGION_EU433 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_EU433 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_EU433 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_EU433 #elif CONFIG_LORAMAC_REGION_EU868 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_EU868 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_EU868 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_EU868 #elif CONFIG_LORAMAC_REGION_KR920 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_KR920 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_KR920 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_KR920 #elif CONFIG_LORAMAC_REGION_IN865 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_IN865 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_IN865 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_IN865 #elif CONFIG_LORAMAC_REGION_US915 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_US915 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_US915 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_US915 #elif CONFIG_LORAMAC_REGION_RU864 -#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_RU864 +#define DEFAULT_LORAWAN_REGION LORAMAC_REGION_RU864 +#define DEFAULT_LORAWAN_CHANNELS_MASK_SIZE LORAWAN_CHANNELS_MASK_SIZE_RU864 #else #error "At least one LoRaWAN region should be selected" #endif @@ -72,6 +82,9 @@ static LoRaMacEventInfoStatus_t last_mlme_indication_status; static LoRaMacRegion_t selected_region = DEFAULT_LORAWAN_REGION; +static enum lorawan_channels_mask_size region_channels_mask_size = + DEFAULT_LORAWAN_CHANNELS_MASK_SIZE; + static lorawan_battery_level_cb_t battery_level_cb; static lorawan_dr_changed_cb_t dr_changed_cb; @@ -292,60 +305,70 @@ int lorawan_set_region(enum lorawan_region region) #if defined(CONFIG_LORAMAC_REGION_AS923) case LORAWAN_REGION_AS923: selected_region = LORAMAC_REGION_AS923; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_AS923; break; #endif #if defined(CONFIG_LORAMAC_REGION_AU915) case LORAWAN_REGION_AU915: selected_region = LORAMAC_REGION_AU915; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_AU915; break; #endif #if defined(CONFIG_LORAMAC_REGION_CN470) case LORAWAN_REGION_CN470: selected_region = LORAMAC_REGION_CN470; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_CN470; break; #endif #if defined(CONFIG_LORAMAC_REGION_CN779) case LORAWAN_REGION_CN779: selected_region = LORAMAC_REGION_CN779; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_CN779; break; #endif #if defined(CONFIG_LORAMAC_REGION_EU433) case LORAWAN_REGION_EU433: selected_region = LORAMAC_REGION_EU433; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_EU433; break; #endif #if defined(CONFIG_LORAMAC_REGION_EU868) case LORAWAN_REGION_EU868: selected_region = LORAMAC_REGION_EU868; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_EU868; break; #endif #if defined(CONFIG_LORAMAC_REGION_KR920) case LORAWAN_REGION_KR920: selected_region = LORAMAC_REGION_KR920; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_KR920; break; #endif #if defined(CONFIG_LORAMAC_REGION_IN865) case LORAWAN_REGION_IN865: selected_region = LORAMAC_REGION_IN865; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_IN865; break; #endif #if defined(CONFIG_LORAMAC_REGION_US915) case LORAWAN_REGION_US915: selected_region = LORAMAC_REGION_US915; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_US915; break; #endif #if defined(CONFIG_LORAMAC_REGION_RU864) case LORAWAN_REGION_RU864: selected_region = LORAMAC_REGION_RU864; + region_channels_mask_size = LORAWAN_CHANNELS_MASK_SIZE_RU864; break; #endif @@ -472,6 +495,26 @@ int lorawan_set_class(enum lorawan_class dev_class) return 0; } +int lorawan_set_channels_mask(uint16_t *channels_mask, size_t channels_mask_size) +{ + MibRequestConfirm_t mib_req; + + if ((channels_mask == NULL) || (channels_mask_size != region_channels_mask_size)) { + return -EINVAL; + } + + /* Notify MAC layer of the requested channel mask. */ + mib_req.Type = MIB_CHANNELS_MASK; + mib_req.Param.ChannelsMask = channels_mask; + + if (LoRaMacMibSetRequestConfirm(&mib_req) != LORAMAC_STATUS_OK) { + /* Channels mask is invalid for this region. */ + return -EINVAL; + } + + return 0; +} + int lorawan_set_datarate(enum lorawan_datarate dr) { MibRequestConfirm_t mib_req; From 46c742f22950a15f38b1f648293f8d6963dd889c Mon Sep 17 00:00:00 2001 From: Jeferson Fernando Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0098/1389] tests: subsys: lorawan: add channels mask configuration tests Checks the behavior of configuration of channels mask for LoRaWAN. Are passed wrong masks sizes as argument, NULL pointer instead channels mask buffer and the right case to validate the expected returns. Signed-off-by: Jeferson Fernando --- .../lorawan/channels_mask/CMakeLists.txt | 8 ++ tests/subsys/lorawan/channels_mask/prj.conf | 11 +++ tests/subsys/lorawan/channels_mask/src/main.c | 77 +++++++++++++++++++ .../lorawan/channels_mask/testcase.yaml | 6 ++ 4 files changed, 102 insertions(+) create mode 100644 tests/subsys/lorawan/channels_mask/CMakeLists.txt create mode 100644 tests/subsys/lorawan/channels_mask/prj.conf create mode 100644 tests/subsys/lorawan/channels_mask/src/main.c create mode 100644 tests/subsys/lorawan/channels_mask/testcase.yaml diff --git a/tests/subsys/lorawan/channels_mask/CMakeLists.txt b/tests/subsys/lorawan/channels_mask/CMakeLists.txt new file mode 100644 index 00000000000000..22b6b5b4d8e0e6 --- /dev/null +++ b/tests/subsys/lorawan/channels_mask/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lorawan_channels_mask_test) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/lorawan/channels_mask/prj.conf b/tests/subsys/lorawan/channels_mask/prj.conf new file mode 100644 index 00000000000000..8b45467c41098c --- /dev/null +++ b/tests/subsys/lorawan/channels_mask/prj.conf @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +CONFIG_ZTEST=y +CONFIG_ASSERT=y +CONFIG_SPI=y +CONFIG_GPIO=y +CONFIG_LORA=y +CONFIG_LORAWAN=y +CONFIG_LORAMAC_REGION_AS923=y +CONFIG_LORAMAC_REGION_AU915=y +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 diff --git a/tests/subsys/lorawan/channels_mask/src/main.c b/tests/subsys/lorawan/channels_mask/src/main.c new file mode 100644 index 00000000000000..cd72b800dad94d --- /dev/null +++ b/tests/subsys/lorawan/channels_mask/src/main.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Jeferson Fernando + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +/** + * @brief Test channels mask with size 1 + * + * This test will request the channels mask changes, passing valid + * and invalid arguments and checking when it's successful or returns error + * + */ +ZTEST(channels_mask, test_mask_size_1) +{ + int err = 0; + uint16_t channels_mask[LORAWAN_CHANNELS_MASK_SIZE_AS923] = {0xffff}; + + /* Test the function when a region with mask size 1 is being used */ + err = lorawan_set_region(LORAWAN_REGION_AS923); + zassert_equal(err, 0, "Could not set region"); + + err = lorawan_start(); + zassert_equal(err, 0, "Could not start stack"); + + /* Configure channels mask with expected parameters */ + err = lorawan_set_channels_mask(channels_mask, LORAWAN_CHANNELS_MASK_SIZE_AS923); + zassert_equal(err, 0, "Denied right channels mask configuration"); + + /* Configure channels mask with unexpected channels mask size */ + err = lorawan_set_channels_mask(channels_mask, LORAWAN_CHANNELS_MASK_SIZE_AU915); + zassert_equal(err, -EINVAL, "Accepted an unexpected mask size for the selected region"); + + /* Configure channels mask with pointer to NULL */ + err = lorawan_set_channels_mask(NULL, LORAWAN_CHANNELS_MASK_SIZE_AS923); + zassert_equal(err, -EINVAL, "Accepted a pointer to NULL"); +} + +/** + * @brief Test channels mask with size 6 + * + * This test will request the channels mask changes, passing valid + * and invalid arguments and checking when it's successful or returns error + * + */ +ZTEST(channels_mask, test_mask_size_6) +{ + int err = 0; + uint16_t channels_mask[LORAWAN_CHANNELS_MASK_SIZE_AU915] = {0}; + + /* Test the function when a region with mask size 6 is being used */ + err = lorawan_set_region(LORAWAN_REGION_AU915); + zassert_equal(err, 0, "Could not set region"); + + err = lorawan_start(); + zassert_equal(err, 0, "Could not start stack"); + + /* Configure channels mask with expected parameters */ + err = lorawan_set_channels_mask(channels_mask, LORAWAN_CHANNELS_MASK_SIZE_AU915); + zassert_equal(err, 0, "Denied right channels mask configuration"); + + /* Configure channels mask with unexpected channels mask size */ + err = lorawan_set_channels_mask(channels_mask, LORAWAN_CHANNELS_MASK_SIZE_AS923); + zassert_equal(err, -EINVAL, "Accepted an unexpected mask size for the selected region"); + + /* Configure channels mask with pointer to NULL */ + err = lorawan_set_channels_mask(NULL, LORAWAN_CHANNELS_MASK_SIZE_AU915); + zassert_equal(err, -EINVAL, "Accepted a pointer to NULL"); +} + +ZTEST_SUITE(channels_mask, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/lorawan/channels_mask/testcase.yaml b/tests/subsys/lorawan/channels_mask/testcase.yaml new file mode 100644 index 00000000000000..7290e16c92b31e --- /dev/null +++ b/tests/subsys/lorawan/channels_mask/testcase.yaml @@ -0,0 +1,6 @@ +tests: + lorawan.channels_mask.set_channels_mask: + tags: lorawan + depends_on: lora + integration_platforms: + - b_l072z_lrwan1 From cbe1b15a6760c1b38e38d8863f5eb77b50676b6e Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0099/1389] devicetree: Add DT/DT_INST_CHILD_NUM and DT/DT_INST_CHILD_NUM_STATUS_OKAY Add a generated macro for the number of child nodes of a given node. Add a generated macro for the number of child nodes of a given node which children's status are "okay". Signed-off-by: Swift Tian --- include/zephyr/devicetree.h | 42 +++++++++++++++++++++++++++++++++++++ scripts/dts/gen_defines.py | 9 ++++++++ 2 files changed, 51 insertions(+) diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index 7255d7981fa13e..eb28dea874aca1 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -551,6 +551,25 @@ */ #define DT_NODE_CHILD_IDX(node_id) DT_CAT(node_id, _CHILD_IDX) +/** + * @brief Get the number of child nodes of a given node + * + * @param node_id a node identifier + * @return Number of child nodes + */ +#define DT_CHILD_NUM(node_id) DT_CAT(node_id, _CHILD_NUM) + + +/** + * @brief Get the number of child nodes of a given node + * which child nodes' status are okay + * + * @param node_id a node identifier + * @return Number of child nodes which status are okay + */ +#define DT_CHILD_NUM_STATUS_OKAY(node_id) \ + DT_CAT(node_id, _CHILD_NUM_STATUS_OKAY) + /** * @brief Do @p node_id1 and @p node_id2 refer to the same node? * @@ -3442,6 +3461,29 @@ #define DT_INST_CHILD(inst, child) \ DT_CHILD(DT_DRV_INST(inst), child) +/** + * @brief Get the number of child nodes of a given node + * + * This is equivalent to @see + * DT_CHILD_NUM(DT_DRV_INST(inst)). + * + * @param inst Devicetree instance number + * @return Number of child nodes + */ +#define DT_INST_CHILD_NUM(inst) DT_CHILD_NUM(DT_DRV_INST(inst)) + +/** + * @brief Get the number of child nodes of a given node + * + * This is equivalent to @see + * DT_CHILD_NUM_STATUS_OKAY(DT_DRV_INST(inst)). + * + * @param inst Devicetree instance number + * @return Number of child nodes which status are okay + */ +#define DT_INST_CHILD_NUM_STATUS_OKAY(inst) \ + DT_CHILD_NUM_STATUS_OKAY(DT_DRV_INST(inst)) + /** * @brief Call @p fn on all child nodes of DT_DRV_INST(inst). * diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index b23a4cb76fe2b5..eb350b0483b70f 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -524,6 +524,15 @@ def write_children(node): out_comment("Helper macros for child nodes of this node.") + out_dt_define(f"{node.z_path_id}_CHILD_NUM", len(node.children)) + + ok_nodes_num = 0 + for child in node.children.values(): + if child.status == "okay": + ok_nodes_num = ok_nodes_num + 1 + + out_dt_define(f"{node.z_path_id}_CHILD_NUM_STATUS_OKAY", ok_nodes_num) + out_dt_define(f"{node.z_path_id}_FOREACH_CHILD(fn)", " ".join(f"fn(DT_{child.z_path_id})" for child in node.children.values())) From 6091432394fa7a44bcb9261755d6a98086c9b374 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0100/1389] tests: devicetree: Add a test test_child_nodes_number The test uses DT_CHILD_NUM and DT_INST_CHILD_NUM to get the number of child nodes of a given node from generated macro. The test uses DT_CHILD_NUM_STATUS_OKAY and DT_INST_CHILD_NUM_STATUS_OKAY to get the number of child nodes of a given node which children's status are "okay" from generated macro. Signed-off-by: Swift Tian --- tests/lib/devicetree/api/src/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 340ff1edbf60f4..c57a280670faba 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -2214,6 +2214,16 @@ ZTEST(devicetree_api, test_child_nodes_list_varg) #undef TEST_FUNC } +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT vnd_child_bindings +ZTEST(devicetree_api, test_child_nodes_number) +{ + zassert_equal(DT_CHILD_NUM(TEST_CHILDREN), 3, ""); + zassert_equal(DT_INST_CHILD_NUM(0), 3, ""); + zassert_equal(DT_CHILD_NUM_STATUS_OKAY(TEST_CHILDREN), 2, ""); + zassert_equal(DT_INST_CHILD_NUM_STATUS_OKAY(0), 2, ""); +} + ZTEST(devicetree_api, test_great_grandchild) { zassert_equal(DT_PROP(DT_NODELABEL(test_ggc), ggc_prop), 42, ""); From 58e76784b4e47330a09cd962487b15c67d8d9523 Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0101/1389] Kernel: Fix comment for doc build. Add an asterisk to make the comment for `k_poll_signal_reset()` appear in documentation and move an @brief down by one line. Signed-off-by: Glenn Andrews --- include/zephyr/kernel.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 943d7dc89b759b..56471770a7cdfa 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -5321,7 +5321,8 @@ struct k_heap { void k_heap_init(struct k_heap *h, void *mem, size_t bytes) __attribute_nonnull(1); -/** @brief Allocate aligned memory from a k_heap +/** + * @brief Allocate aligned memory from a k_heap * * Behaves in all ways like k_heap_alloc(), except that the returned * memory (if available) will have a starting address in memory which @@ -5783,7 +5784,7 @@ __syscall int k_poll(struct k_poll_event *events, int num_events, __syscall void k_poll_signal_init(struct k_poll_signal *sig); -/* +/** * @brief Reset a poll signal object's state to unsignaled. * * @param sig A poll signal object From c3a33a0ca2427c23af1a93b28d50ead7529b4d1f Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0102/1389] arch: arm: cortex-m: Change character used to mark immediate operand Change the character used to indicate immediate operands from '$' to '#' to resolve an "invalid instruction" error when building with clang. For arm, binutils allows either '#' or '$' to indicate immediate operands. clang seems to accept '$' for arm in other instances (my build accepts 'subs r0, r0, $0x02', for example), but in this case it produces an error that this is an invalid instruction due to the "$0x02" operand. Given clang's inconsistent behavior, I'm guessing this is a bug in clang somewhere, but: 1. '#' for immediate operands seems to be more standard for arm in general and seems to be what is used throughout the rest of Zephyr's arm asm code. 2. Switching out '$' for '#' shouldn't negatively impact other toolchains. As such, switch out the character used to unblock clang builds until this can be fixed in clang. Signed-off-by: Jonathon Penix --- arch/arm/core/cortex_m/irq_relay.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/core/cortex_m/irq_relay.S b/arch/arm/core/cortex_m/irq_relay.S index 229282c7650a88..1b2aafe505ae0f 100644 --- a/arch/arm/core/cortex_m/irq_relay.S +++ b/arch/arm/core/cortex_m/irq_relay.S @@ -31,7 +31,7 @@ GDATA(z_main_stack) SECTION_FUNC(TEXT, __vector_relay_handler) mrs r0, ipsr; - lsls r0, r0, $0x02; + lsls r0, r0, #0x02; ldr r1, =_vector_table_pointer; ldr r1, [r1]; From 4cc1488d3595a6d4c2dba707d48ea896e05d3061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:28 +0200 Subject: [PATCH 0103/1389] drivers: gpio: fix bug with Px15 pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix condition in pin number check so that PA15, PB15, etc. can be properly accessed.. Co-authored-by: Денис Signed-off-by: Benjamin Cabé --- drivers/gpio/gpio_numaker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio_numaker.c b/drivers/gpio/gpio_numaker.c index 2c7515f2981e4e..3a1c8ad8eeefd4 100644 --- a/drivers/gpio/gpio_numaker.c +++ b/drivers/gpio/gpio_numaker.c @@ -48,7 +48,7 @@ static int gpio_numaker_configure(const struct device *dev, gpio_pin_t pin, gpio ARG_UNUSED(data); /* Check for an invalid pin number */ - if (pin >= 15) { + if (pin > 15) { return -EINVAL; } From f78f7c034c55b56f270b86737a2a3364b2eb08cb Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0104/1389] device.h: fix unbalanced initializer: ({ .pm_base = (pm_),)} Close parentheses and braces in the reverse order they are opened. Fixes commit f91d4731af4e ("pm: use braces for .pm_base inside anonymous union initializer") I have no idea how no compiler caught this!? I tested very carefully with two different gcc versions and one clang version and generated binaries are strictly identical before and after this commit. Fix the code anyway because C macros are painful enough to debug already, so no need to add more confusion. Signed-off-by: Marc Herbert --- include/zephyr/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/device.h b/include/zephyr/device.h index 27086227143a6d..d2f2244cc0b8f0 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -934,7 +934,7 @@ __syscall int device_init(const struct device *dev); .state = (state_), \ .data = (data_), \ IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ - IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),)}) /**/ \ + IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \ } /** From 7441b7497e442b44ebc753e52741795627072a24 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0105/1389] drivers: ncp5623: check led_info for all LEDs With the current code, when three separate monochrome LEDs are defined in DT, only the information from the first LED is checked during driver initialization. This patch fixes the code to verify the information of each LED. Signed-off-by: Simon Guinot --- drivers/led/ncp5623.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/led/ncp5623.c b/drivers/led/ncp5623.c index 0fd0f128d37bcc..b197ab898421ad 100644 --- a/drivers/led/ncp5623.c +++ b/drivers/led/ncp5623.c @@ -156,7 +156,7 @@ static int ncp5623_led_init(const struct device *dev) } } else if (config->num_leds <= 3) { /* three single-channel LEDs */ for (i = 0; i < config->num_leds; i++) { - led_info = ncp5623_led_to_info(config, 0); + led_info = ncp5623_led_to_info(config, i); if (!led_info) { return -ENODEV; From cc5f464729cb5cd0f74c632fdea113d2fd4cbb79 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0106/1389] lib: os: coding guidelines: add explicit cast to void - added explicit cast to void when returned value is expectedly ignored Signed-off-by: frei tycho --- lib/os/sem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/os/sem.c b/lib/os/sem.c index b01ead58e507e1..b7676c929c6c49 100644 --- a/lib/os/sem.c +++ b/lib/os/sem.c @@ -53,7 +53,7 @@ int sys_sem_init(struct sys_sem *sem, unsigned int initial_count, return -EINVAL; } - atomic_set(&sem->futex.val, initial_count); + (void)atomic_set(&sem->futex.val, initial_count); sem->limit = limit; return 0; From 601f07e9977a96646b0e9003b89ea7a2268efdd6 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0107/1389] drivers: i2s: stm32: use length from i2s_write The length parameter from `i2s_write` is not used correctly by i2s_ll_stm32.c. E.g. `i2s_write(dev, block, 0)` would work. Use the length from `i2s_write` in `dma_reload` to fix the issue. Signed-off-by: Jeppe Odgaard --- drivers/i2s/i2s_ll_stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index bf06d5f4df705a..b289ddabe750d7 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -633,7 +633,7 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg, #else (void *)LL_SPI_DMA_GetRegAddr(cfg->i2s), #endif - stream->cfg.block_size); + mem_block_size); if (ret < 0) { LOG_DBG("Failed to start TX DMA transfer: %d", ret); goto tx_disable; From c045cd7c38e00e69141155817924fe276b7f229c Mon Sep 17 00:00:00 2001 From: Mikhail Skobov Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0108/1389] drivers: i2c: i2c_ll_stm32_v1 In rare cases, the I2C driver runs the N==2 logic for I2C receives when N>2. This change breaks early when handling the last 2 bytes for transactions with N>2 Signed-off-by: Mikhail Skobov --- drivers/i2c/i2c_ll_stm32_v1.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/i2c/i2c_ll_stm32_v1.c b/drivers/i2c/i2c_ll_stm32_v1.c index ff63ee399131d3..e4346726384405 100644 --- a/drivers/i2c/i2c_ll_stm32_v1.c +++ b/drivers/i2c/i2c_ll_stm32_v1.c @@ -359,6 +359,14 @@ static inline void handle_rxne(const struct device *dev) k_sem_give(&data->device_sync_sem); break; case 2: + /* + * 2-byte reception for N > 3 has already set the NACK + * bit, and must not set the POS bit. See pg. 854 in + * the F4 reference manual (RM0090). + */ + if (data->current.msg->len > 2) { + break; + } LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK); LL_I2C_EnableBitPOS(i2c); __fallthrough; From f672c5df5716cd83a423e94b28bd346b4d3f5900 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0109/1389] boards: nordic: nrf54h20dk: Update memory map Move global RAM0x regions to align with the documentation. Signed-off-by: Grzegorz Swiderski --- .../nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 68c0d5cd990912..91899e2cf86b68 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -6,16 +6,16 @@ / { reserved-memory { - cpuapp_ram0x_region: memory@2f000000 { + cpuapp_ram0x_region: memory@2f010000 { compatible = "nordic,owned-memory"; - reg = <0x2f000000 DT_SIZE_K(260)>; + reg = <0x2f010000 DT_SIZE_K(260)>; status = "disabled"; perm-read; perm-write; perm-secure; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0x2f000000 0x41000>; + ranges = <0x0 0x2f010000 0x41000>; cpusec_cpuapp_ipc_shm: memory@0 { reg = <0x0 DT_SIZE_K(2)>; @@ -30,16 +30,16 @@ }; }; - cpurad_ram0x_region: memory@2f041000 { + cpurad_ram0x_region: memory@2f051000 { compatible = "nordic,owned-memory"; - reg = <0x2f041000 DT_SIZE_K(4)>; + reg = <0x2f051000 DT_SIZE_K(4)>; status = "disabled"; perm-read; perm-write; perm-secure; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0x2f041000 0x1000>; + ranges = <0x0 0x2f051000 0x1000>; cpusec_cpurad_ipc_shm: memory@0 { reg = <0x0 DT_SIZE_K(2)>; From 6b855ab386aa88cb68ddb9efbc0d296b8be3a35d Mon Sep 17 00:00:00 2001 From: Wei-Tai Lee Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0110/1389] driver: hwinfo: andes: add missing Kconfig dependency Add Kconfig dependency to the Andes hwinfo driver. Signed-off-by: Wei-Tai Lee --- drivers/hwinfo/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index 467a36ad8afeb4..703201410dec53 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -189,6 +189,7 @@ config HWINFO_ANDES bool "Andes system ID" default y depends on SOC_FAMILY_ANDES_V5 + depends on SYSCON help Enable Andes hwinfo driver From 56eb12051844f3f736ad3cd24d3d8cadc0211f7d Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0111/1389] Bluetooth: Host: Fix auto-connect/sync establishment on Coded PHY As documented in bt_le_scan_update(), the host may start scanning automatically for various reasons. Until now scanning was only done on 1M PHY, making it impossible to use auto-connect/sync establishment if the advertiser was using Coded PHY as its primary PHY. Auto-connection would never work. Sync establishment would work if the scanner was started by the application. This commit fixes this by instructing the controller to scan on both 1M and Coded PHY if the controller supports Coded PHY. The application may see increased power consumption as a result of this change as the controller may now spend 2*scan_window listening for advertising packets. Signed-off-by: Rubin Gerritsen --- subsys/bluetooth/host/scan.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index 9957d818309ee6..4d4233895acd58 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -289,7 +289,7 @@ static int start_le_scan_legacy(uint8_t scan_type, uint16_t interval, uint16_t w return 0; } -static int start_passive_scan(bool fast_scan) +static int start_host_initiated_scan(bool fast_scan) { uint16_t interval, window; @@ -303,13 +303,19 @@ static int start_passive_scan(bool fast_scan) if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - struct bt_hci_ext_scan_phy scan; + struct bt_hci_ext_scan_phy scan_phy_params; - scan.type = BT_HCI_LE_SCAN_PASSIVE; - scan.interval = sys_cpu_to_le16(interval); - scan.window = sys_cpu_to_le16(window); + scan_phy_params.type = BT_HCI_LE_SCAN_PASSIVE; + scan_phy_params.interval = sys_cpu_to_le16(interval); + scan_phy_params.window = sys_cpu_to_le16(window); + + /* Scan on 1M + Coded if the controller supports it*/ + if (BT_FEAT_LE_PHY_CODED(bt_dev.le.features)) { + return start_le_scan_ext(&scan_phy_params, &scan_phy_params, 0); + } else { + return start_le_scan_ext(&scan_phy_params, NULL, 0); + } - return start_le_scan_ext(&scan, NULL, 0); } return start_le_scan_legacy(BT_HCI_LE_SCAN_PASSIVE, interval, window); @@ -352,14 +358,14 @@ int bt_le_scan_update(bool fast_scan) bt_conn_unref(conn); /* Start/Restart the scanner */ - return start_passive_scan(fast_scan); + return start_host_initiated_scan(fast_scan); } } #if defined(CONFIG_BT_PER_ADV_SYNC) if (get_pending_per_adv_sync()) { /* Start/Restart the scanner. */ - return start_passive_scan(fast_scan); + return start_host_initiated_scan(fast_scan); } #endif From 4c147b1a217e8c95474c44aef099f3cf9d238a5b Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0112/1389] tests: Bluetooth: Increase coverage for sync establishment We didn't have test coverage for the scenario where the host starts scanning automatically. Signed-off-by: Rubin Gerritsen --- .../host/adv/periodic/src/per_adv_syncer.c | 36 +++++++++++++++++++ .../tests_scripts/per_adv_app_not_scanning.sh | 26 ++++++++++++++ 2 files changed, 62 insertions(+) create mode 100755 tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh diff --git a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c index 274a6ca4cec540..df126e3ae25390 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c +++ b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c @@ -253,6 +253,33 @@ static void main_per_adv_syncer(void) PASS("Periodic advertising syncer passed\n"); } +static void main_per_adv_syncer_app_not_scanning(void) +{ + int err; + struct bt_le_per_adv_sync *sync = NULL; + + common_init(); + start_scan(); + + printk("Waiting for periodic advertising...\n"); + WAIT_FOR_FLAG(flag_per_adv); + printk("Found periodic advertising.\n"); + + printk("Stopping scan\n"); + err = bt_le_scan_stop(); + if (err != 0) { + FAIL("Failed to stop scan: %d", err); + return; + } + + create_pa_sync(&sync); + + printk("Waiting for periodic sync lost...\n"); + WAIT_FOR_FLAG(flag_per_adv_sync_lost); + + PASS("Periodic advertising syncer passed\n"); +} + static void main_per_adv_conn_syncer(void) { struct bt_le_per_adv_sync *sync = NULL; @@ -341,6 +368,15 @@ static const struct bst_test_instance per_adv_syncer[] = { .test_tick_f = test_tick, .test_main_f = main_per_adv_syncer }, + { + .test_id = "per_adv_syncer_app_not_scanning", + .test_descr = "Basic periodic advertising sync test but where " + "the app stopped scanning before creating sync." + "Expect the host to start scanning automatically.", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = main_per_adv_syncer_app_not_scanning + }, { .test_id = "per_adv_conn_syncer", .test_descr = "Periodic advertising sync test, but where there " diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh new file mode 100755 index 00000000000000..7362b53d4a7420 --- /dev/null +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Periodic advertising sync test where the host starts scanning +# automatically because the application didn't start it. + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="per_adv_not_scanning" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=0 \ + -testid=per_adv_advertiser -rs=23 + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ + -testid=per_adv_syncer_app_not_scanning -rs=6 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs From f675b2a1e5e4c8c98083e60c3054a7d7811f308c Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0113/1389] tests: Bluetooth: Add coverage for Coded PHY sync establishment Adds test coverage for the case where the host starts the scanner automatically upon sync creation. This test covers there bug where we previously did not start scanning on Coded PHY. Signed-off-by: Rubin Gerritsen --- tests/bsim/bluetooth/host/adv/compile.sh | 1 + .../host/adv/periodic/prj_coded.conf | 15 +++++ .../adv/periodic/src/per_adv_advertiser.c | 59 +++++++++++++++++++ .../host/adv/periodic/src/per_adv_syncer.c | 5 +- .../per_adv_app_not_scanning_coded.sh | 27 +++++++++ 5 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/bsim/bluetooth/host/adv/periodic/prj_coded.conf create mode 100755 tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh diff --git a/tests/bsim/bluetooth/host/adv/compile.sh b/tests/bsim/bluetooth/host/adv/compile.sh index 1729acb5062b66..c17c1395d177de 100755 --- a/tests/bsim/bluetooth/host/adv/compile.sh +++ b/tests/bsim/bluetooth/host/adv/compile.sh @@ -20,6 +20,7 @@ app=tests/bsim/bluetooth/host/adv/extended conf_file=prj_advertiser.conf compile app=tests/bsim/bluetooth/host/adv/extended conf_file=prj_scanner.conf compile app=tests/bsim/bluetooth/host/adv/periodic compile app=tests/bsim/bluetooth/host/adv/periodic conf_file=prj_long_data.conf compile +app=tests/bsim/bluetooth/host/adv/periodic conf_file=prj_coded.conf compile app=tests/bsim/bluetooth/host/adv/encrypted/css_sample_data compile app=tests/bsim/bluetooth/host/adv/encrypted/ead_sample compile app=tests/bsim/bluetooth/host/adv/long_ad compile diff --git a/tests/bsim/bluetooth/host/adv/periodic/prj_coded.conf b/tests/bsim/bluetooth/host/adv/periodic/prj_coded.conf new file mode 100644 index 00000000000000..50c4c33e08a123 --- /dev/null +++ b/tests/bsim/bluetooth/host/adv/periodic/prj_coded.conf @@ -0,0 +1,15 @@ +CONFIG_BT=y +CONFIG_BT_DEVICE_NAME="test_per_adv" +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_SMP=y +CONFIG_BT_PRIVACY=y + +CONFIG_BT_EXT_ADV=y +CONFIG_BT_EXT_ADV_MAX_ADV_SET=2 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ADV_AUX_SET=2 +CONFIG_BT_CTLR_ADV_DATA_BUF_MAX=2 +CONFIG_BT_CTLR_PHY_CODED=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y diff --git a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c index 560b20183bf690..d6b7df63cb9576 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c +++ b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c @@ -106,6 +106,30 @@ static void create_per_adv_set(struct bt_le_ext_adv **adv) printk("done.\n"); } +#if defined(CONFIG_BT_CTLR_PHY_CODED) +static void create_per_adv_set_coded(struct bt_le_ext_adv **adv) +{ + int err; + + printk("Creating coded PHY extended advertising set..."); + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CODED_NCONN, NULL, adv); + if (err) { + printk("Failed to create advertising set: %d\n", err); + return; + } + printk("done.\n"); + + printk("Setting periodic advertising parameters..."); + err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT); + if (err) { + printk("Failed to set periodic advertising parameters: %d\n", + err); + return; + } + printk("done.\n"); +} +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + static void create_conn_adv_set(struct bt_le_ext_adv **adv) { int err; @@ -228,6 +252,31 @@ static void main_per_adv_advertiser(void) PASS("Periodic advertiser passed\n"); } +#if defined(CONFIG_BT_CTLR_PHY_CODED) +static void main_per_adv_advertiser_coded(void) +{ + struct bt_le_ext_adv *per_adv; + + common_init(); + + create_per_adv_set_coded(&per_adv); + + start_per_adv_set(per_adv); + start_ext_adv_set(per_adv); + + /* Advertise for a bit */ + k_sleep(K_SECONDS(10)); + + stop_per_adv_set(per_adv); + stop_ext_adv_set(per_adv); + + delete_adv_set(per_adv); + per_adv = NULL; + + PASS("Periodic advertiser coded PHY passed\n"); +} +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + static void main_per_adv_conn_advertiser(void) { struct bt_le_ext_adv *conn_adv; @@ -329,6 +378,16 @@ static const struct bst_test_instance per_adv_advertiser[] = { .test_tick_f = test_tick, .test_main_f = main_per_adv_advertiser }, +#if defined(CONFIG_BT_CTLR_PHY_CODED) + { + .test_id = "per_adv_advertiser_coded_phy", + .test_descr = "Basic periodic advertising test on Coded PHY. " + "Advertiser and periodic advertiser uses Coded PHY", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = main_per_adv_advertiser_coded + }, +#endif /* CONFIG_BT_CTLR_PHY_CODED */ { .test_id = "per_adv_conn_advertiser", .test_descr = "Periodic advertising test with concurrent ACL " diff --git a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c index df126e3ae25390..9c0ad747195233 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c +++ b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c @@ -190,7 +190,10 @@ static void start_scan(void) int err; printk("Start scanning..."); - err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); + + err = bt_le_scan_start(IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) ? + BT_LE_SCAN_CODED_ACTIVE : BT_LE_SCAN_ACTIVE, + NULL); if (err) { FAIL("Failed to start scan: %d\n", err); return; diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh new file mode 100755 index 00000000000000..005bd6baf031c7 --- /dev/null +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Periodic advertising sync test where the host starts scanning +# automatically because the application didn't start it. +# The advertiser is using Coded PHY as primary PHY. + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="per_adv_app_not_scanning_coded" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_coded_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=0 \ + -testid=per_adv_advertiser_coded_phy -rs=23 + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_coded_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ + -testid=per_adv_syncer_app_not_scanning -rs=6 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs From 2145dfa57ef379e79b5a2246cd7381e6f3a683e9 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0114/1389] tests: Bluetooth: per_adv_syncer -> per_adv_sync This ensures the naming convention matches the APIs that are tested. Signed-off-by: Rubin Gerritsen --- .../host/adv/periodic/CMakeLists.txt | 2 +- .../bluetooth/host/adv/periodic/src/main.c | 4 +- .../adv/periodic/src/per_adv_advertiser.c | 2 +- .../src/{per_adv_syncer.c => per_adv_sync.c} | 50 +++++++++---------- .../adv/periodic/tests_scripts/per_adv.sh | 2 +- .../tests_scripts/per_adv_app_not_scanning.sh | 2 +- .../per_adv_app_not_scanning_coded.sh | 2 +- .../periodic/tests_scripts/per_adv_conn.sh | 2 +- .../tests_scripts/per_adv_conn_privacy.sh | 2 +- .../tests_scripts/per_adv_long_data.sh | 2 +- 10 files changed, 35 insertions(+), 35 deletions(-) rename tests/bsim/bluetooth/host/adv/periodic/src/{per_adv_syncer.c => per_adv_sync.c} (88%) diff --git a/tests/bsim/bluetooth/host/adv/periodic/CMakeLists.txt b/tests/bsim/bluetooth/host/adv/periodic/CMakeLists.txt index ebf037dffceff3..85b2a61c9db5c7 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/CMakeLists.txt +++ b/tests/bsim/bluetooth/host/adv/periodic/CMakeLists.txt @@ -9,7 +9,7 @@ target_sources(app PRIVATE src/common.c src/main.c src/per_adv_advertiser.c - src/per_adv_syncer.c + src/per_adv_sync.c ) zephyr_include_directories( diff --git a/tests/bsim/bluetooth/host/adv/periodic/src/main.c b/tests/bsim/bluetooth/host/adv/periodic/src/main.c index a71ffa91d0124f..a2465921d5a189 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/src/main.c +++ b/tests/bsim/bluetooth/host/adv/periodic/src/main.c @@ -6,11 +6,11 @@ #include "bstests.h" -extern struct bst_test_list *test_per_adv_syncer(struct bst_test_list *tests); +extern struct bst_test_list *test_per_adv_sync(struct bst_test_list *tests); extern struct bst_test_list *test_per_adv_advertiser(struct bst_test_list *tests); bst_test_install_t test_installers[] = { - test_per_adv_syncer, + test_per_adv_sync, test_per_adv_advertiser, NULL }; diff --git a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c index d6b7df63cb9576..3808ec6ba30a76 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c +++ b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_advertiser.c @@ -407,7 +407,7 @@ static const struct bst_test_instance per_adv_advertiser[] = { { .test_id = "per_adv_long_data_advertiser", .test_descr = "Periodic advertising test with a longer data length. " - "To test the syncers reassembly of large data packets", + "To test the reassembly of large data packets", .test_post_init_f = test_init, .test_tick_f = test_tick, .test_main_f = main_per_adv_long_data_advertiser diff --git a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_sync.c similarity index 88% rename from tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c rename to tests/bsim/bluetooth/host/adv/periodic/src/per_adv_sync.c index 9c0ad747195233..c2ff633d23dc25 100644 --- a/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_syncer.c +++ b/tests/bsim/bluetooth/host/adv/periodic/src/per_adv_sync.c @@ -237,7 +237,7 @@ static void start_bonding(void) printk("done.\n"); } -static void main_per_adv_syncer(void) +static void main_per_adv_sync(void) { struct bt_le_per_adv_sync *sync = NULL; @@ -253,10 +253,10 @@ static void main_per_adv_syncer(void) printk("Waiting for periodic sync lost...\n"); WAIT_FOR_FLAG(flag_per_adv_sync_lost); - PASS("Periodic advertising syncer passed\n"); + PASS("Periodic advertising sync passed\n"); } -static void main_per_adv_syncer_app_not_scanning(void) +static void main_per_adv_sync_app_not_scanning(void) { int err; struct bt_le_per_adv_sync *sync = NULL; @@ -280,10 +280,10 @@ static void main_per_adv_syncer_app_not_scanning(void) printk("Waiting for periodic sync lost...\n"); WAIT_FOR_FLAG(flag_per_adv_sync_lost); - PASS("Periodic advertising syncer passed\n"); + PASS("Periodic advertising sync passed\n"); } -static void main_per_adv_conn_syncer(void) +static void main_per_adv_conn_sync(void) { struct bt_le_per_adv_sync *sync = NULL; @@ -305,10 +305,10 @@ static void main_per_adv_conn_syncer(void) printk("Waiting for periodic sync lost...\n"); WAIT_FOR_FLAG(flag_per_adv_sync_lost); - PASS("Periodic advertising syncer passed\n"); + PASS("Periodic advertising sync passed\n"); } -static void main_per_adv_conn_privacy_syncer(void) +static void main_per_adv_conn_privacy_sync(void) { struct bt_le_per_adv_sync *sync = NULL; @@ -336,10 +336,10 @@ static void main_per_adv_conn_privacy_syncer(void) printk("Waiting for periodic sync lost...\n"); WAIT_FOR_FLAG(flag_per_adv_sync_lost); - PASS("Periodic advertising syncer passed\n"); + PASS("Periodic advertising sync passed\n"); } -static void main_per_adv_long_data_syncer(void) +static void main_per_adv_long_data_sync(void) { #if (CONFIG_BT_PER_ADV_SYNC_BUF_SIZE > 0) struct bt_le_per_adv_sync *sync = NULL; @@ -359,58 +359,58 @@ static void main_per_adv_long_data_syncer(void) printk("Waiting for periodic sync lost...\n"); WAIT_FOR_FLAG(flag_per_adv_sync_lost); #endif - PASS("Periodic advertising long data syncer passed\n"); + PASS("Periodic advertising long data sync passed\n"); } -static const struct bst_test_instance per_adv_syncer[] = { +static const struct bst_test_instance per_adv_sync[] = { { - .test_id = "per_adv_syncer", + .test_id = "per_adv_sync", .test_descr = "Basic periodic advertising sync test. " "Will just sync to a periodic advertiser.", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = main_per_adv_syncer + .test_main_f = main_per_adv_sync }, { - .test_id = "per_adv_syncer_app_not_scanning", + .test_id = "per_adv_sync_app_not_scanning", .test_descr = "Basic periodic advertising sync test but where " "the app stopped scanning before creating sync." "Expect the host to start scanning automatically.", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = main_per_adv_syncer_app_not_scanning + .test_main_f = main_per_adv_sync_app_not_scanning }, { - .test_id = "per_adv_conn_syncer", + .test_id = "per_adv_conn_sync", .test_descr = "Periodic advertising sync test, but where there " "is a connection between the advertiser and the " - "syncer.", + "synchronized device.", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = main_per_adv_conn_syncer + .test_main_f = main_per_adv_conn_sync }, { - .test_id = "per_adv_conn_privacy_syncer", + .test_id = "per_adv_conn_privacy_sync", .test_descr = "Periodic advertising sync test, but where " - "advertiser and syncer are bonded and using " + "advertiser and synchronized device are bonded and using " "privacy", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = main_per_adv_conn_privacy_syncer + .test_main_f = main_per_adv_conn_privacy_sync }, { - .test_id = "per_adv_long_data_syncer", + .test_id = "per_adv_long_data_sync", .test_descr = "Periodic advertising sync test with larger " "data length. Test is used to verify that " "reassembly of long data is handeled correctly.", .test_post_init_f = test_init, .test_tick_f = test_tick, - .test_main_f = main_per_adv_long_data_syncer + .test_main_f = main_per_adv_long_data_sync }, BSTEST_END_MARKER }; -struct bst_test_list *test_per_adv_syncer(struct bst_test_list *tests) +struct bst_test_list *test_per_adv_sync(struct bst_test_list *tests) { - return bst_add_tests(tests, per_adv_syncer); + return bst_add_tests(tests, per_adv_sync); } diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv.sh index 4e88aa57cc540e..a7b8d99b654890 100755 --- a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv.sh +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv.sh @@ -18,7 +18,7 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ - -testid=per_adv_syncer -rs=6 + -testid=per_adv_sync -rs=6 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=20e6 $@ diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh index 7362b53d4a7420..7176929cb2d0b6 100755 --- a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning.sh @@ -18,7 +18,7 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ - -testid=per_adv_syncer_app_not_scanning -rs=6 + -testid=per_adv_sync_app_not_scanning -rs=6 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=20e6 $@ diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh index 005bd6baf031c7..31fd0195dddf70 100755 --- a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_app_not_scanning_coded.sh @@ -19,7 +19,7 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_coded_conf \ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_coded_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ - -testid=per_adv_syncer_app_not_scanning -rs=6 + -testid=per_adv_sync_app_not_scanning -rs=6 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=20e6 $@ diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn.sh index 9c4823538f6d61..a459c91e450aca 100755 --- a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn.sh +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn.sh @@ -18,7 +18,7 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ - -testid=per_adv_conn_syncer -rs=6 + -testid=per_adv_conn_sync -rs=6 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=20e6 $@ diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn_privacy.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn_privacy.sh index a8d2cdcd31d304..1fe7b38d61ca79 100755 --- a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn_privacy.sh +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_conn_privacy.sh @@ -18,7 +18,7 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ - -testid=per_adv_conn_privacy_syncer -rs=6 + -testid=per_adv_conn_privacy_sync -rs=6 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=20e6 $@ diff --git a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_long_data.sh b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_long_data.sh index 53ef8e9cbf76ce..b660ba2598fb6d 100755 --- a/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_long_data.sh +++ b/tests/bsim/bluetooth/host/adv/periodic/tests_scripts/per_adv_long_data.sh @@ -18,7 +18,7 @@ Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_long_data_co Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_adv_periodic_prj_long_data_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ - -testid=per_adv_long_data_syncer -rs=6 + -testid=per_adv_long_data_sync -rs=6 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=20e6 $@ From da0624b1a0cd61185d63e68a524e517f61e9b34e Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0115/1389] include: mgmt: ec_host_cmd: Remove __subsystem tag Remove the subsystem tag from a backend API. Signed-off-by: Pieter De Gendt --- include/zephyr/mgmt/ec_host_cmd/backend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/mgmt/ec_host_cmd/backend.h b/include/zephyr/mgmt/ec_host_cmd/backend.h index ed61e0e33c2f56..66f04e97868f4d 100644 --- a/include/zephyr/mgmt/ec_host_cmd/backend.h +++ b/include/zephyr/mgmt/ec_host_cmd/backend.h @@ -103,7 +103,7 @@ typedef int (*ec_host_cmd_backend_api_init)(const struct ec_host_cmd_backend *ba */ typedef int (*ec_host_cmd_backend_api_send)(const struct ec_host_cmd_backend *backend); -__subsystem struct ec_host_cmd_backend_api { +struct ec_host_cmd_backend_api { ec_host_cmd_backend_api_init init; ec_host_cmd_backend_api_send send; }; From 0073c759d57135c3a7bc6e08f9eb430799a78496 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0116/1389] drivers: sensor: Rename emul_sensor_backend_api to emul_sensor_driver_api Structs with a __subsystem tag are required to have a _driver_api suffix. Signed-off-by: Pieter De Gendt --- drivers/sensor/amd_sb_tsi/sb_tsi_emul.c | 2 +- drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c | 4 ++-- drivers/sensor/bosch/bma4xx/bma4xx_emul.c | 4 ++-- drivers/sensor/bosch/bmi160/emul_bmi160.c | 2 +- drivers/sensor/f75303/f75303_emul.c | 2 +- drivers/sensor/tdk/icm42688/icm42688_emul.c | 4 ++-- include/zephyr/drivers/emul_sensor.h | 10 +++++----- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c index 1c12942c876ec9..f33e5cd9134f85 100644 --- a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c +++ b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c @@ -140,7 +140,7 @@ static const struct i2c_emul_api sb_tsi_emul_api_i2c = { .transfer = sb_tsi_emul_transfer_i2c, }; -static const struct emul_sensor_backend_api sb_tsi_emul_api_sensor = { +static const struct emul_sensor_driver_api sb_tsi_emul_api_sensor = { .set_channel = sb_tsi_emul_set_channel, .get_sample_range = sb_tsi_emul_get_sample_range, }; diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c index adb237e1256c48..db541b8b4fb4b5 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c @@ -208,7 +208,7 @@ static const struct i2c_emul_api akm09918c_emul_api_i2c = { .transfer = akm09918c_emul_transfer_i2c, }; -static const struct emul_sensor_backend_api akm09918c_emul_sensor_backend_api = { +static const struct emul_sensor_driver_api akm09918c_emul_sensor_driver_api = { .set_channel = akm09918c_emul_backend_set_channel, .get_sample_range = akm09918c_emul_backend_get_sample_range, }; @@ -218,6 +218,6 @@ static const struct emul_sensor_backend_api akm09918c_emul_sensor_backend_api = struct akm09918c_emul_data akm09918c_emul_data_##n; \ EMUL_DT_INST_DEFINE(n, akm09918c_emul_init, &akm09918c_emul_data_##n, \ &akm09918c_emul_cfg_##n, &akm09918c_emul_api_i2c, \ - &akm09918c_emul_sensor_backend_api) + &akm09918c_emul_sensor_driver_api) DT_INST_FOREACH_STATUS_OKAY(AKM09918C_EMUL) diff --git a/drivers/sensor/bosch/bma4xx/bma4xx_emul.c b/drivers/sensor/bosch/bma4xx/bma4xx_emul.c index b5c96d29817175..efc4012e29c560 100644 --- a/drivers/sensor/bosch/bma4xx/bma4xx_emul.c +++ b/drivers/sensor/bosch/bma4xx/bma4xx_emul.c @@ -306,7 +306,7 @@ static int bma4xx_emul_backend_get_sample_range(const struct emul *target, enum return 0; } -static const struct emul_sensor_backend_api bma4xx_emul_sensor_backend_api = { +static const struct emul_sensor_driver_api bma4xx_emul_sensor_driver_api = { .set_channel = bma4xx_emul_backend_set_channel, .get_sample_range = bma4xx_emul_backend_get_sample_range, }; @@ -319,6 +319,6 @@ static struct i2c_emul_api bma4xx_emul_api_i2c = { static struct bma4xx_emul_data bma4xx_emul_data_##n = {}; \ static const struct bma4xx_emul_cfg bma4xx_emul_cfg_##n = {}; \ EMUL_DT_INST_DEFINE(n, bma4xx_emul_init, &bma4xx_emul_data_##n, &bma4xx_emul_cfg_##n, \ - &bma4xx_emul_api_i2c, &bma4xx_emul_sensor_backend_api); + &bma4xx_emul_api_i2c, &bma4xx_emul_sensor_driver_api); DT_INST_FOREACH_STATUS_OKAY(INIT_BMA4XX) diff --git a/drivers/sensor/bosch/bmi160/emul_bmi160.c b/drivers/sensor/bosch/bmi160/emul_bmi160.c index 3ed71790fbedd2..38c74a98813d1f 100644 --- a/drivers/sensor/bosch/bmi160/emul_bmi160.c +++ b/drivers/sensor/bosch/bmi160/emul_bmi160.c @@ -569,7 +569,7 @@ static int bmi160_emul_backend_get_attribute_metadata(const struct emul *target, } } -static const struct emul_sensor_backend_api backend_api = { +static const struct emul_sensor_driver_api backend_api = { .set_channel = bmi160_emul_backend_set_channel, .get_sample_range = bmi160_emul_backend_get_sample_range, .set_attribute = bmi160_emul_backend_set_attribute, diff --git a/drivers/sensor/f75303/f75303_emul.c b/drivers/sensor/f75303/f75303_emul.c index 5bab9cd429466e..7e906af5f04d70 100644 --- a/drivers/sensor/f75303/f75303_emul.c +++ b/drivers/sensor/f75303/f75303_emul.c @@ -160,7 +160,7 @@ static const struct i2c_emul_api f75303_emul_api_i2c = { .transfer = f75303_emul_transfer_i2c, }; -static const struct emul_sensor_backend_api f75303_emul_api_sensor = { +static const struct emul_sensor_driver_api f75303_emul_api_sensor = { .set_channel = f75303_emul_set_channel, .get_sample_range = f75303_emul_get_sample_range, }; diff --git a/drivers/sensor/tdk/icm42688/icm42688_emul.c b/drivers/sensor/tdk/icm42688/icm42688_emul.c index 732af64289bdd5..5bf60aa4fd12cd 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_emul.c +++ b/drivers/sensor/tdk/icm42688/icm42688_emul.c @@ -402,14 +402,14 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen return 0; } -static const struct emul_sensor_backend_api icm42688_emul_sensor_backend_api = { +static const struct emul_sensor_driver_api icm42688_emul_sensor_driver_api = { .set_channel = icm42688_emul_backend_set_channel, .get_sample_range = icm42688_emul_backend_get_sample_range, }; #define ICM42688_EMUL_DEFINE(n, api) \ EMUL_DT_INST_DEFINE(n, icm42688_emul_init, &icm42688_emul_data_##n, \ - &icm42688_emul_cfg_##n, &api, &icm42688_emul_sensor_backend_api) + &icm42688_emul_cfg_##n, &api, &icm42688_emul_sensor_driver_api) #define ICM42688_EMUL_SPI(n) \ static struct icm42688_emul_data icm42688_emul_data_##n; \ diff --git a/include/zephyr/drivers/emul_sensor.h b/include/zephyr/drivers/emul_sensor.h index 30345cc6a0bc22..9bbbd8d30525ac 100644 --- a/include/zephyr/drivers/emul_sensor.h +++ b/include/zephyr/drivers/emul_sensor.h @@ -25,7 +25,7 @@ /** * @brief Collection of function pointers implementing a common backend API for sensor emulators */ -__subsystem struct emul_sensor_backend_api { +__subsystem struct emul_sensor_driver_api { /** Sets a given fractional value for a given sensor channel. */ int (*set_channel)(const struct emul *target, enum sensor_channel ch, const q31_t *value, int8_t shift); @@ -75,7 +75,7 @@ static inline int emul_sensor_backend_set_channel(const struct emul *target, enu return -ENOTSUP; } - struct emul_sensor_backend_api *api = (struct emul_sensor_backend_api *)target->backend_api; + struct emul_sensor_driver_api *api = (struct emul_sensor_driver_api *)target->backend_api; if (api->set_channel) { return api->set_channel(target, ch, value, shift); @@ -108,7 +108,7 @@ static inline int emul_sensor_backend_get_sample_range(const struct emul *target return -ENOTSUP; } - struct emul_sensor_backend_api *api = (struct emul_sensor_backend_api *)target->backend_api; + struct emul_sensor_driver_api *api = (struct emul_sensor_driver_api *)target->backend_api; if (api->get_sample_range) { return api->get_sample_range(target, ch, lower, upper, epsilon, shift); @@ -135,7 +135,7 @@ static inline int emul_sensor_backend_set_attribute(const struct emul *target, return -ENOTSUP; } - struct emul_sensor_backend_api *api = (struct emul_sensor_backend_api *)target->backend_api; + struct emul_sensor_driver_api *api = (struct emul_sensor_driver_api *)target->backend_api; if (api->set_attribute == NULL) { return -ENOTSUP; @@ -170,7 +170,7 @@ static inline int emul_sensor_backend_get_attribute_metadata(const struct emul * return -ENOTSUP; } - struct emul_sensor_backend_api *api = (struct emul_sensor_backend_api *)target->backend_api; + struct emul_sensor_driver_api *api = (struct emul_sensor_driver_api *)target->backend_api; if (api->get_attribute_metadata == NULL) { return -ENOTSUP; From 4abafc229a8e2921f489b3977885b75b94508be7 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0117/1389] drivers: usbc_ppc: Rename usbc_ppc_drv to usbc_ppc_driver_api Structs with a __subsystem tag are required to have a _driver_api suffix. Signed-off-by: Pieter De Gendt --- drivers/usb_c/ppc/nxp_nx20p3483.c | 2 +- include/zephyr/drivers/usb_c/usbc_ppc.h | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/usb_c/ppc/nxp_nx20p3483.c b/drivers/usb_c/ppc/nxp_nx20p3483.c index 8b6a2fe914d8e3..35d1db70798106 100644 --- a/drivers/usb_c/ppc/nxp_nx20p3483.c +++ b/drivers/usb_c/ppc/nxp_nx20p3483.c @@ -229,7 +229,7 @@ static int nx20p3483_dump_regs(const struct device *dev) return 0; } -static struct usbc_ppc_drv nx20p3483_driver_api = { +static struct usbc_ppc_driver_api nx20p3483_driver_api = { .is_dead_battery_mode = nx20p3483_is_dead_battery_mode, .exit_dead_battery_mode = nx20p3483_exit_dead_battery_mode, .is_vbus_source = nx20p3483_is_vbus_source, diff --git a/include/zephyr/drivers/usb_c/usbc_ppc.h b/include/zephyr/drivers/usb_c/usbc_ppc.h index c8f76c9227f75f..6d7f2440f5a227 100644 --- a/include/zephyr/drivers/usb_c/usbc_ppc.h +++ b/include/zephyr/drivers/usb_c/usbc_ppc.h @@ -50,7 +50,7 @@ enum usbc_ppc_event { typedef void (*usbc_ppc_event_cb_t)(const struct device *dev, void *data, enum usbc_ppc_event ev); /** Structure with pointers to the functions implemented by driver */ -__subsystem struct usbc_ppc_drv { +__subsystem struct usbc_ppc_driver_api { int (*is_dead_battery_mode)(const struct device *dev); int (*exit_dead_battery_mode)(const struct device *dev); int (*is_vbus_source)(const struct device *dev); @@ -78,7 +78,7 @@ __subsystem struct usbc_ppc_drv { */ static inline int ppc_is_dead_battery_mode(const struct device *dev) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->is_dead_battery_mode == NULL) { return -ENOSYS; @@ -101,7 +101,7 @@ static inline int ppc_is_dead_battery_mode(const struct device *dev) */ static inline int ppc_exit_dead_battery_mode(const struct device *dev) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->exit_dead_battery_mode == NULL) { return -ENOSYS; @@ -121,7 +121,7 @@ static inline int ppc_exit_dead_battery_mode(const struct device *dev) */ static inline int ppc_is_vbus_source(const struct device *dev) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->is_vbus_source == NULL) { return -ENOSYS; @@ -141,7 +141,7 @@ static inline int ppc_is_vbus_source(const struct device *dev) */ static inline int ppc_is_vbus_sink(const struct device *dev) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->is_vbus_sink == NULL) { return -ENOSYS; @@ -161,7 +161,7 @@ static inline int ppc_is_vbus_sink(const struct device *dev) */ static inline int ppc_set_snk_ctrl(const struct device *dev, bool enable) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->set_snk_ctrl == NULL) { return -ENOSYS; @@ -181,7 +181,7 @@ static inline int ppc_set_snk_ctrl(const struct device *dev, bool enable) */ static inline int ppc_set_src_ctrl(const struct device *dev, bool enable) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->set_src_ctrl == NULL) { return -ENOSYS; @@ -201,7 +201,7 @@ static inline int ppc_set_src_ctrl(const struct device *dev, bool enable) */ static inline int ppc_set_vbus_discharge(const struct device *dev, bool enable) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->set_vbus_discharge == NULL) { return -ENOSYS; @@ -221,7 +221,7 @@ static inline int ppc_set_vbus_discharge(const struct device *dev, bool enable) */ static inline int ppc_is_vbus_present(const struct device *dev) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->is_vbus_present == NULL) { return -ENOSYS; @@ -242,7 +242,7 @@ static inline int ppc_is_vbus_present(const struct device *dev) static inline int ppc_set_event_handler(const struct device *dev, usbc_ppc_event_cb_t handler, void *data) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->set_event_handler == NULL) { return -ENOSYS; @@ -261,7 +261,7 @@ static inline int ppc_set_event_handler(const struct device *dev, */ static inline int ppc_dump_regs(const struct device *dev) { - const struct usbc_ppc_drv *api = (const struct usbc_ppc_drv *)dev->api; + const struct usbc_ppc_driver_api *api = (const struct usbc_ppc_driver_api *)dev->api; if (api->dump_regs == NULL) { return -ENOSYS; From bded460db7a1aa5491dc1867da1809adc3a3bb8b Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:29 +0200 Subject: [PATCH 0118/1389] drivers: bbram: Rename emul_bbram_backend_api to emul_bbram_driver_api Structs with a __subsystem tag are required to have a _driver_api suffix. Signed-off-by: Pieter De Gendt --- drivers/bbram/bbram_it8xxx2_emul.c | 2 +- drivers/bbram/bbram_microchip_mcp7940n_emul.c | 2 +- drivers/bbram/bbram_npcx_emul.c | 2 +- include/zephyr/drivers/emul_bbram.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/bbram/bbram_it8xxx2_emul.c b/drivers/bbram/bbram_it8xxx2_emul.c index 901a09835f1f85..fea04112c0dbf6 100644 --- a/drivers/bbram/bbram_it8xxx2_emul.c +++ b/drivers/bbram/bbram_it8xxx2_emul.c @@ -45,7 +45,7 @@ static int it8xxx2_emul_backend_get_data(const struct emul *target, size_t offse return 0; } -static const struct emul_bbram_backend_api it8xxx2_emul_backend_api = { +static const struct emul_bbram_driver_api it8xxx2_emul_backend_api = { .set_data = it8xxx2_emul_backend_set_data, .get_data = it8xxx2_emul_backend_get_data, }; diff --git a/drivers/bbram/bbram_microchip_mcp7940n_emul.c b/drivers/bbram/bbram_microchip_mcp7940n_emul.c index 56a84825948897..d1206c42a1684f 100644 --- a/drivers/bbram/bbram_microchip_mcp7940n_emul.c +++ b/drivers/bbram/bbram_microchip_mcp7940n_emul.c @@ -135,7 +135,7 @@ static int mcp7940n_emul_backend_get_data(const struct emul *target, size_t offs return 0; } -static const struct emul_bbram_backend_api mcp7940n_emul_backend_api = { +static const struct emul_bbram_driver_api mcp7940n_emul_backend_api = { .set_data = mcp7940n_emul_backend_set_data, .get_data = mcp7940n_emul_backend_get_data, }; diff --git a/drivers/bbram/bbram_npcx_emul.c b/drivers/bbram/bbram_npcx_emul.c index 799e158eefd066..354c7e8bb8fa89 100644 --- a/drivers/bbram/bbram_npcx_emul.c +++ b/drivers/bbram/bbram_npcx_emul.c @@ -45,7 +45,7 @@ static int npcx_emul_backend_get_data(const struct emul *target, size_t offset, return 0; } -static const struct emul_bbram_backend_api npcx_emul_backend_api = { +static const struct emul_bbram_driver_api npcx_emul_backend_api = { .set_data = npcx_emul_backend_set_data, .get_data = npcx_emul_backend_get_data, }; diff --git a/include/zephyr/drivers/emul_bbram.h b/include/zephyr/drivers/emul_bbram.h index 441f101c934a96..ee9edab88468c8 100644 --- a/include/zephyr/drivers/emul_bbram.h +++ b/include/zephyr/drivers/emul_bbram.h @@ -23,7 +23,7 @@ * These are for internal use only, so skip these in public documentation. */ -__subsystem struct emul_bbram_backend_api { +__subsystem struct emul_bbram_driver_api { /** Sets the data */ int (*set_data)(const struct emul *target, size_t offset, size_t count, const uint8_t *data); @@ -53,7 +53,7 @@ static inline int emul_bbram_backend_set_data(const struct emul *target, size_t return -ENOTSUP; } - struct emul_bbram_backend_api *api = (struct emul_bbram_backend_api *)target->backend_api; + struct emul_bbram_driver_api *api = (struct emul_bbram_driver_api *)target->backend_api; if (api->set_data == NULL) { return -ENOTSUP; @@ -80,7 +80,7 @@ static inline int emul_bbram_backend_get_data(const struct emul *target, size_t return -ENOTSUP; } - struct emul_bbram_backend_api *api = (struct emul_bbram_backend_api *)target->backend_api; + struct emul_bbram_driver_api *api = (struct emul_bbram_driver_api *)target->backend_api; if (api->get_data == NULL) { return -ENOTSUP; From 72ffe2c5f1647c6bddb5a955351d0977ff5b6d00 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0119/1389] include: drivers: Add missing __subsystem tags Add __subsystem tags to driver API structs. Signed-off-by: Pieter De Gendt --- include/zephyr/drivers/clock_control.h | 2 +- include/zephyr/drivers/display.h | 2 +- include/zephyr/drivers/i2c.h | 2 +- include/zephyr/drivers/i3c/target_device.h | 2 +- include/zephyr/drivers/interrupt_controller/intel_vtd.h | 2 +- include/zephyr/drivers/led_strip.h | 2 +- include/zephyr/drivers/lora.h | 2 +- include/zephyr/drivers/pcie/endpoint/pcie_ep.h | 2 +- include/zephyr/drivers/usb_c/usbc_vbus.h | 2 +- include/zephyr/drivers/video.h | 2 +- include/zephyr/shared_irq.h | 3 ++- 11 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/zephyr/drivers/clock_control.h b/include/zephyr/drivers/clock_control.h index d0806163769718..27d65fe3079255 100644 --- a/include/zephyr/drivers/clock_control.h +++ b/include/zephyr/drivers/clock_control.h @@ -99,7 +99,7 @@ typedef int (*clock_control_configure_fn)(const struct device *dev, clock_control_subsys_t sys, void *data); -struct clock_control_driver_api { +__subsystem struct clock_control_driver_api { clock_control on; clock_control off; clock_control_async_on_fn async_on; diff --git a/include/zephyr/drivers/display.h b/include/zephyr/drivers/display.h index 854c728148ae18..067d441d4551b4 100644 --- a/include/zephyr/drivers/display.h +++ b/include/zephyr/drivers/display.h @@ -217,7 +217,7 @@ typedef int (*display_set_orientation_api)(const struct device *dev, * @brief Display driver API * API which a display driver should expose */ -struct display_driver_api { +__subsystem struct display_driver_api { display_blanking_on_api blanking_on; display_blanking_off_api blanking_off; display_write_api write; diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h index 6135fbf1390945..04b7d02ce15d86 100644 --- a/include/zephyr/drivers/i2c.h +++ b/include/zephyr/drivers/i2c.h @@ -259,7 +259,7 @@ __subsystem struct i2c_driver_api { typedef int (*i2c_target_api_register_t)(const struct device *dev); typedef int (*i2c_target_api_unregister_t)(const struct device *dev); -struct i2c_target_driver_api { +__subsystem struct i2c_target_driver_api { i2c_target_api_register_t driver_register; i2c_target_api_unregister_t driver_unregister; }; diff --git a/include/zephyr/drivers/i3c/target_device.h b/include/zephyr/drivers/i3c/target_device.h index ca699814078a42..1f4df8409ad169 100644 --- a/include/zephyr/drivers/i3c/target_device.h +++ b/include/zephyr/drivers/i3c/target_device.h @@ -211,7 +211,7 @@ struct i3c_target_callbacks { int (*stop_cb)(struct i3c_target_config *config); }; -struct i3c_target_driver_api { +__subsystem struct i3c_target_driver_api { int (*driver_register)(const struct device *dev); int (*driver_unregister)(const struct device *dev); }; diff --git a/include/zephyr/drivers/interrupt_controller/intel_vtd.h b/include/zephyr/drivers/interrupt_controller/intel_vtd.h index 5e6044d829e561..b91834c74a8448 100644 --- a/include/zephyr/drivers/interrupt_controller/intel_vtd.h +++ b/include/zephyr/drivers/interrupt_controller/intel_vtd.h @@ -45,7 +45,7 @@ typedef void (*vtd_set_irte_msi_f)(const struct device *dev, typedef bool (*vtd_irte_is_msi_f)(const struct device *dev, uint8_t irte_idx); -struct vtd_driver_api { +__subsystem struct vtd_driver_api { vtd_alloc_entries_f allocate_entries; vtd_remap_msi_f remap_msi; vtd_remap_f remap; diff --git a/include/zephyr/drivers/led_strip.h b/include/zephyr/drivers/led_strip.h index 210af850aed9d5..b9c7a81407baae 100644 --- a/include/zephyr/drivers/led_strip.h +++ b/include/zephyr/drivers/led_strip.h @@ -76,7 +76,7 @@ typedef int (*led_api_update_channels)(const struct device *dev, * * This is the mandatory API any LED strip driver needs to expose. */ -struct led_strip_driver_api { +__subsystem struct led_strip_driver_api { led_api_update_rgb update_rgb; led_api_update_channels update_channels; }; diff --git a/include/zephyr/drivers/lora.h b/include/zephyr/drivers/lora.h index a96ca8854962ee..90706595a806a5 100644 --- a/include/zephyr/drivers/lora.h +++ b/include/zephyr/drivers/lora.h @@ -179,7 +179,7 @@ typedef int (*lora_api_recv_async)(const struct device *dev, lora_recv_cb cb); typedef int (*lora_api_test_cw)(const struct device *dev, uint32_t frequency, int8_t tx_power, uint16_t duration); -struct lora_driver_api { +__subsystem struct lora_driver_api { lora_api_config config; lora_api_send send; lora_api_send_async send_async; diff --git a/include/zephyr/drivers/pcie/endpoint/pcie_ep.h b/include/zephyr/drivers/pcie/endpoint/pcie_ep.h index 43f201ec7b9194..ca4316a667279b 100644 --- a/include/zephyr/drivers/pcie/endpoint/pcie_ep.h +++ b/include/zephyr/drivers/pcie/endpoint/pcie_ep.h @@ -56,7 +56,7 @@ enum pcie_reset { typedef void (*pcie_ep_reset_callback_t)(void *arg); -struct pcie_ep_driver_api { +__subsystem struct pcie_ep_driver_api { int (*conf_read)(const struct device *dev, uint32_t offset, uint32_t *data); void (*conf_write)(const struct device *dev, uint32_t offset, diff --git a/include/zephyr/drivers/usb_c/usbc_vbus.h b/include/zephyr/drivers/usb_c/usbc_vbus.h index eb159d7c509edb..a5421bf9389f2c 100644 --- a/include/zephyr/drivers/usb_c/usbc_vbus.h +++ b/include/zephyr/drivers/usb_c/usbc_vbus.h @@ -32,7 +32,7 @@ extern "C" { #endif -struct usbc_vbus_driver_api { +__subsystem struct usbc_vbus_driver_api { bool (*check_level)(const struct device *dev, enum tc_vbus_level level); int (*measure)(const struct device *dev, int *vbus_meas); int (*discharge)(const struct device *dev, bool enable); diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index 191efbecc1e64c..85f08920119fa7 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -249,7 +249,7 @@ typedef int (*video_api_set_signal_t)(const struct device *dev, enum video_endpoint_id ep, struct k_poll_signal *signal); -struct video_driver_api { +__subsystem struct video_driver_api { /* mandatory callbacks */ video_api_set_format_t set_format; video_api_get_format_t get_format; diff --git a/include/zephyr/shared_irq.h b/include/zephyr/shared_irq.h index 575ef119d3a488..e5ffdf1edd8f75 100644 --- a/include/zephyr/shared_irq.h +++ b/include/zephyr/shared_irq.h @@ -9,6 +9,7 @@ #ifndef ZEPHYR_INCLUDE_SHARED_IRQ_H_ #define ZEPHYR_INCLUDE_SHARED_IRQ_H_ +#include #ifdef __cplusplus extern "C" { @@ -25,7 +26,7 @@ typedef int (*shared_irq_enable_t)(const struct device *dev, typedef int (*shared_irq_disable_t)(const struct device *dev, const struct device *isr_dev); -struct shared_irq_driver_api { +__subsystem struct shared_irq_driver_api { shared_irq_register_t isr_register; shared_irq_enable_t enable; shared_irq_disable_t disable; From d9d0696a5cbe728b817c3de1f9b58b37268acf5c Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0120/1389] scripts: build: gen_kobject_list.py check _driver_api suffix Raise an exceptionif _driver_api suffix is missing from subsystem name. Signed-off-by: Pieter De Gendt --- scripts/build/gen_kobject_list.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/build/gen_kobject_list.py b/scripts/build/gen_kobject_list.py index ebcba21c1a66e6..1d60c0df0fc9df 100755 --- a/scripts/build/gen_kobject_list.py +++ b/scripts/build/gen_kobject_list.py @@ -138,6 +138,9 @@ def kobject_to_enum(kobj): net_sockets = [ ] def subsystem_to_enum(subsys): + if not subsys.endswith("_driver_api"): + raise Exception("__subsystem is missing _driver_api suffix: (%s)" % subsys) + return "K_OBJ_DRIVER_" + subsys[:-11].upper() # --- debug stuff --- From db85f6989e45047b98bfa520ae170ef1263b9279 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0121/1389] doc: migration-guide-3.7: Add driver API renamed structs Add a migration entry for some of the driver API structs that have been renamed. Signed-off-by: Pieter De Gendt --- doc/releases/migration-guide-3.7.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 5638e40154c89a..23610b68ee02d1 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -106,6 +106,13 @@ Device Drivers and Devicetree }; }; +* Some of the driver API structs have been rename to have the required ``_driver_api`` suffix. + The following types have been renamed: + + * ``emul_sensor_backend_api`` to :c:struct:`emul_sensor_driver_api` + * ``emul_bbram_backend_api`` to :c:struct:`emul_bbram_driver_api` + * ``usbc_ppc_drv`` to :c:struct:`usbc_ppc_driver_api` + Analog-to-Digital Converter (ADC) ================================= From bac9bd3d7800eca9db171affaa7d51b26e245a50 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0122/1389] modules: mbedtls: remove default-enabling of hash algorithms Do not enable hash algorithms except SHA-256 by default. This unnecessarily inflates the final code size even if not all the enabled hash algorithms are actually used. SHA-256 is (for now) kept enabled by default because many configurations across the code base assume that there is some hash algorithm available without needing to enable it. Signed-off-by: Tomi Fontanilles --- modules/mbedtls/Kconfig.tls-generic | 7 +------ modules/mbedtls/configs/config-tls-generic.h | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 3f48996fcd5976..d75abd64be2f00 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -215,17 +215,14 @@ config MBEDTLS_HASH_ALL_ENABLED select MBEDTLS_HASH_SHA512_ENABLED config MBEDTLS_HASH_SHA256_ENABLED - bool "SHA256 hash" - default y if !NET_L2_OPENTHREAD + bool "SHA224 and SHA256 hashes" config MBEDTLS_HASH_SHA384_ENABLED bool "SHA384 hash" - default y if !NET_L2_OPENTHREAD select MBEDTLS_HASH_SHA512_ENABLED config MBEDTLS_HASH_SHA512_ENABLED bool "SHA512 hash" - default y if !NET_L2_OPENTHREAD comment "Supported cipher modes" @@ -320,11 +317,9 @@ config MBEDTLS_MAC_MD4_ENABLED config MBEDTLS_MAC_MD5_ENABLED bool "MD5 hash algorithm" - default y if !NET_L2_OPENTHREAD config MBEDTLS_MAC_SHA1_ENABLED bool "SHA1 hash algorithm" - default y if !NET_L2_OPENTHREAD config MBEDTLS_MAC_SHA256_ENABLED bool "SHA-224 and SHA-256 hash algorithms" diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index b852e42818fe40..18be5b4119ebb1 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -394,7 +394,7 @@ #define MBEDTLS_X509_CRT_PARSE_C #endif -#if defined (CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT) && \ +#if defined(CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT) && \ defined(MBEDTLS_X509_CRT_PARSE_C) #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_BASE64_C From b49770f73e9e234d3dfdb6bce6ba0f8fd9942e80 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0123/1389] drivers: crypto: mbedtls: fix dependency Explicitly enable SHA-512 now that it is not enabled by default anymore. Signed-off-by: Tomi Fontanilles --- drivers/crypto/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5342441038e66f..451a524c810fc4 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -52,6 +52,7 @@ config CRYPTO_MBEDTLS_SHIM bool "MbedTLS shim driver [EXPERIMENTAL]" select MBEDTLS select MBEDTLS_ENABLE_HEAP + select MBEDTLS_MAC_SHA512_ENABLED select EXPERIMENTAL help Enable mbedTLS shim layer compliant with crypto APIs. You will need From 5afb4930667f830208fcf603e4286af87edd9ea9 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0124/1389] samples: tfm_integration: psa_crypto: improve the MbedTLS configuration Move supported configuration items from the custom MbedTLS user configuration file over to the Kconfig overlay. The correct macros are then defined by the MbedTLS module according to the values of the Kconfig options. Signed-off-by: Tomi Fontanilles --- samples/tfm_integration/psa_crypto/prj.conf | 6 ++++++ .../psa_crypto/src/tls_config/user-tls-conf.h | 14 -------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index 97df0796411280..a7ac8db8f2e149 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -28,6 +28,12 @@ CONFIG_MBEDTLS_HEAP_SIZE=32768 CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_MBEDTLS_ENTROPY_ENABLED=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECDSA_C=y + # JSON CONFIG_JSON_LIBRARY=y diff --git a/samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h b/samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h index 26b649033194d0..fa6d4cc6756679 100644 --- a/samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h +++ b/samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h @@ -4,21 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define MBEDTLS_USE_PSA_CRYPTO -#define MBEDTLS_PSA_CRYPTO_C - -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_TEST_NULL_ENTROPY - -#define MBEDTLS_ECP_C -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECDSA_C - #define MBEDTLS_X509_CSR_WRITE_C #define MBEDTLS_X509_CREATE_C #define MBEDTLS_PEM_WRITE_C #define MBEDTLS_BASE64_C -#define MBEDTLS_OID_C -#define MBEDTLS_ASN1_WRITE_C -#define MBEDTLS_PK_WRITE_C -#define MBEDTLS_PK_C From d2f330262ab928149f5fad9348be7848feaf29ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Amundsen?= Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0125/1389] sysbuild: cmake: fix incorrect function name in error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The name in the error message does not match the function name. Signed-off-by: Håkon Amundsen --- share/sysbuild/cmake/modules/sysbuild_extensions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake index 3f3d409922a24c..ce0af2fe7b3392 100644 --- a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake @@ -597,7 +597,7 @@ function(sysbuild_cache_set) return() elseif(VARS_REMOVE_DUPLICATES AND NOT VARS_APPEND) message(FATAL_ERROR - "sysbuild_set(VAR APPEND REMOVE_DUPLICATES ...) missing required APPEND option") + "sysbuild_cache_set(VAR APPEND REMOVE_DUPLICATES ...) missing required APPEND option") endif() get_property(var_type CACHE ${VARS_VAR} PROPERTY TYPE) From 01f917ee09fb64c3e47cf300889365e5e16eabea Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0126/1389] coding guidelines: comply with MISRA C:2012 Rule 17.7 in arch - added explicit cast to void when returned value is expectedly ignored Signed-off-by: frei tycho --- arch/x86/core/x86_mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index e67ce67ae21cdc..c8735f43dd9251 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -1433,8 +1433,8 @@ int arch_buffer_validate(void *addr, size_t size, int write) int ret = 0; /* addr/size arbitrary, fix this up into an aligned region */ - k_mem_region_align((uintptr_t *)&virt, &aligned_size, - (uintptr_t)addr, size, CONFIG_MMU_PAGE_SIZE); + (void)k_mem_region_align((uintptr_t *)&virt, &aligned_size, + (uintptr_t)addr, size, CONFIG_MMU_PAGE_SIZE); for (size_t offset = 0; offset < aligned_size; offset += CONFIG_MMU_PAGE_SIZE) { From a4b0a89cd825731254b421d57027061c5dcf5817 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0127/1389] i2c: Add Kconfig HAS_I2C_RTIO This config should be selected by any driver that supports the RTIO interface and can then be checked on by things like tests or drivers that subsequently require the feature exist. Signed-off-by: Tom Burdick --- drivers/i2c/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 6c687b53184c97..e9dee81207ff85 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -54,8 +54,15 @@ config I2C_CALLBACK help API and implementations of i2c_transfer_cb. +config HAS_I2C_RTIO + bool + help + This option must be selected by I2C controller drivers that optionally implement the RTIO + interface. + config I2C_RTIO bool "I2C RTIO API" + depends on HAS_I2C_RTIO select RTIO help API and implementations of I2C for RTIO From 186df73c0648c7cdd0383b7cb8ec98651efd97f1 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0128/1389] i2c: sam twihs driver supports rtio select HAS_I2C_RTIO when sam twihs is selected Signed-off-by: Tom Burdick --- drivers/i2c/Kconfig.sam_twihs | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/Kconfig.sam_twihs b/drivers/i2c/Kconfig.sam_twihs index 5f1daa6f4c462b..ee3a29487523d1 100644 --- a/drivers/i2c/Kconfig.sam_twihs +++ b/drivers/i2c/Kconfig.sam_twihs @@ -7,5 +7,6 @@ config I2C_SAM_TWIHS bool "Atmel SAM (TWIHS) I2C driver" default y depends on DT_HAS_ATMEL_SAM_I2C_TWIHS_ENABLED + select HAS_I2C_RTIO help Enable Atmel SAM MCU Family (TWIHS) I2C bus driver. From 6a55ce968827b03752ba49f9acc66246c54175bf Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0129/1389] i2c: LPI2C selects HAS_I2C_RTIO LPI2C from NXP supports the RTIO interface and therefore now selects the HAS_I2C_RTIO Kconfig. Signed-off-by: Tom Burdick --- drivers/i2c/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index e9dee81207ff85..8af4bbbeb8b3e6 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -174,6 +174,7 @@ config I2C_MCUX_LPI2C default y depends on DT_HAS_NXP_IMX_LPI2C_ENABLED depends on CLOCK_CONTROL + select HAS_I2C_RTIO select PINCTRL help Enable the mcux LPI2C driver. From ce653a53a0c54d78954284e85335379ea344d67f Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0130/1389] i2c: RAM test updates to support power management It's important we test the power management flows when testing i2c Signed-off-by: Tom Burdick --- tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c | 14 +++++++++++++- tests/drivers/i2c/i2c_ram/testcase.yaml | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c b/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c index 5b9dbb77ce381a..739e9809ff3029 100644 --- a/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c +++ b/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -73,6 +74,17 @@ static void i2c_ram_before(void *f) rx_cmd[1] = (addr) & 0xFF; addr += ARRAY_SIZE(tx_data) - TX_DATA_OFFSET; memset(rx_data, 0, ARRAY_SIZE(rx_data)); + +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_runtime_get(i2c_dev); +#endif +} + +static void i2c_ram_after(void *f) +{ +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_runtime_put(i2c_dev); +#endif } ZTEST(i2c_ram, test_ram_transfer) @@ -294,4 +306,4 @@ ZTEST(i2c_ram, test_ram_rtio_isr) #endif /* CONFIG_I2C_RTIO */ -ZTEST_SUITE(i2c_ram, NULL, i2c_ram_setup, i2c_ram_before, NULL, NULL); +ZTEST_SUITE(i2c_ram, NULL, i2c_ram_setup, i2c_ram_before, i2c_ram_after, NULL); diff --git a/tests/drivers/i2c/i2c_ram/testcase.yaml b/tests/drivers/i2c/i2c_ram/testcase.yaml index 3bed6b96a871fe..69b1180091de7c 100644 --- a/tests/drivers/i2c/i2c_ram/testcase.yaml +++ b/tests/drivers/i2c/i2c_ram/testcase.yaml @@ -11,5 +11,19 @@ tests: - drivers - i2c drivers.i2c.ram.rtio: + filter: CONFIG_HAS_I2C_RTIO extra_configs: - CONFIG_I2C_RTIO=y + drivers.i2c.ram.pm: + filter: CONFIG_HAS_PM + extra_configs: + - CONFIG_PM=y + - CONFIG_PM_DEVICE=y + - CONFIG_PM_DEVICE_RUNTIME=y + drivers.i2c.ram.pm.rtio: + filter: CONFIG_HAS_PM and CONFIG_HAS_I2C_RTIO + extra_configs: + - CONFIG_PM=y + - CONFIG_PM_DEVICE=y + - CONFIG_PM_DEVICE_RUNTIME=y + - CONFIG_I2C_RTIO=y From 89221e373d03244912206b31e84eb97eb1db6f02 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0131/1389] i2c: Fix filtering on alias for i2c-ram Was previously looking for i2c_ram which is incorrect, the alias was always i2c-ram. Signed-off-by: Tom Burdick --- tests/drivers/i2c/i2c_ram/testcase.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drivers/i2c/i2c_ram/testcase.yaml b/tests/drivers/i2c/i2c_ram/testcase.yaml index 69b1180091de7c..d1257778cc3fda 100644 --- a/tests/drivers/i2c/i2c_ram/testcase.yaml +++ b/tests/drivers/i2c/i2c_ram/testcase.yaml @@ -3,7 +3,7 @@ common: tags: - drivers - i2c - filter: dt_alias_exists("i2c_ram") + filter: dt_alias_exists("i2c-ram") tests: drivers.i2c.ram: depends_on: i2c From 19eb2a3e75781055178d7b0afd2125db487c3a5d Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0132/1389] Bluetooth: OTS: Fix calling obj_created callback with NULL conn Callback was always called with NULL conn. Now it is called with proper pointer or NULL conforming to description. Signed-off-by: Szymon Janc --- subsys/bluetooth/services/ots/ots.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/services/ots/ots.c b/subsys/bluetooth/services/ots/ots.c index 8a45929ad279b0..e2c4e90db13594 100644 --- a/subsys/bluetooth/services/ots/ots.c +++ b/subsys/bluetooth/services/ots/ots.c @@ -318,7 +318,7 @@ int bt_ots_obj_add_internal(struct bt_ots *ots, struct bt_conn *conn, (void)memset(&created_desc, 0, sizeof(created_desc)); if (ots->cb->obj_created) { - err = ots->cb->obj_created(ots, NULL, new_obj->id, param, &created_desc); + err = ots->cb->obj_created(ots, conn, new_obj->id, param, &created_desc); if (err) { (void)bt_gatt_ots_obj_manager_obj_delete(new_obj); From f28a2a0fa9369fa5f5900f9186b6984a4a6a1552 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0133/1389] drivers: timer: tsc: retrieve clock frequency of system timer at runtime add support for retrieve clock frequency (HW clock cycle per sec) of system timer at runtime by reading cpu clock via cpuid Signed-off-by: Najumon B.A --- drivers/timer/apic_tsc.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 59b0017375c3db..2b8d5873242b8f 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -8,12 +8,18 @@ #include #include #include +#include #define IA32_TSC_DEADLINE_MSR 0x6e0 #define IA32_TSC_ADJUST_MSR 0x03b +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME +static uint64_t CYC_PER_TICK; +extern int z_clock_hw_cycles_per_sec; +#else #define CYC_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \ / (uint64_t) CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#endif struct apic_timer_lvt { uint8_t vector : 8; @@ -158,9 +164,11 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t * static int sys_clock_driver_init(void) { -#ifdef CONFIG_ASSERT +#if defined(CONFIG_ASSERT) || defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) uint32_t eax, ebx, ecx, edx; +#endif +#ifdef CONFIG_ASSERT eax = 1; ecx = 0; cpuid(&eax, &ebx, &ecx, &edx); __ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support"); @@ -174,6 +182,23 @@ static int sys_clock_driver_init(void) __ASSERT((ebx & BIT(1)) != 0, "No TSC_ADJUST MSR support"); #endif +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + int tsc_freq; + + eax = 0; + ebx = 0; + ecx = 0; + if (!__get_cpuid(0x15, &eax, &ebx, &ecx, &edx)) { + __ASSERT(false, "error cpuid leaf 0x15\n"); + } + + __ASSERT((ebx != 0) && (ecx != 0), "No TSC/core crystal clock ratio is enumerated"); + + tsc_freq = (uint32_t)((ecx * (uint64_t)ebx) / eax); + z_clock_hw_cycles_per_sec = tsc_freq; + CYC_PER_TICK = tsc_freq/CONFIG_SYS_CLOCK_TICKS_PER_SEC; +#endif + clear_tsc_adjust(); /* Timer interrupt number is runtime-fetched, so can't use From 2f221caf59c91e3b95798b95319c6211610dba19 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Sun, 26 May 2024 22:38:30 +0200 Subject: [PATCH 0134/1389] kernel: retrieve system timer clock frequency at runtime or static update kernel timeout logic based on retrieve system timer clock frequency at runtime or static way based on Kconfig TIMER_READS_ITS_FREQUENCY_AT_RUNTIME Signed-off-by: Najumon B.A --- include/zephyr/sys_clock.h | 8 ++++---- kernel/Kconfig | 1 + kernel/timeout.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/zephyr/sys_clock.h b/include/zephyr/sys_clock.h index e43b539fb8f54b..eab5df34d077fc 100644 --- a/include/zephyr/sys_clock.h +++ b/include/zephyr/sys_clock.h @@ -146,9 +146,9 @@ typedef struct { /** @endcond */ -#if defined(CONFIG_SYS_CLOCK_EXISTS) && \ - (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0) -#error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!" +#if defined(CONFIG_SYS_CLOCK_EXISTS) && !defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) +BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC != 0, + "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!"); #endif @@ -164,7 +164,7 @@ typedef struct { * @{ */ -#ifdef CONFIG_SYS_CLOCK_EXISTS +#if defined(CONFIG_SYS_CLOCK_EXISTS) && !defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) || \ (MSEC_PER_SEC % CONFIG_SYS_CLOCK_TICKS_PER_SEC) || \ diff --git a/kernel/Kconfig b/kernel/Kconfig index af51267edbf1fc..c237a5af48a765 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -799,6 +799,7 @@ config SYS_CLOCK_TICKS_PER_SEC config SYS_CLOCK_HW_CYCLES_PER_SEC int "System clock's h/w timer frequency" + depends on !TIMER_READS_ITS_FREQUENCY_AT_RUNTIME help This option specifies the frequency of the hardware timer used for the system clock (in Hz). This option is set by the SOC's or board's Kconfig file diff --git a/kernel/timeout.c b/kernel/timeout.c index 8c727e204f91b7..55ba6dd3d2f8ff 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -25,7 +25,7 @@ static struct k_spinlock timeout_lock; static int announce_remaining; #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) -int z_clock_hw_cycles_per_sec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; +int z_clock_hw_cycles_per_sec; #ifdef CONFIG_USERSPACE static inline int z_vrfy_sys_clock_hw_cycles_per_sec_runtime_get(void) From f85b0165c2ea6843b1e8b780f38d8e0fb1bfd658 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0135/1389] board: x86: enable system timer clock frequency at run time add support for retrieve runtime clock frequency (HW clock cycle per sec) for APIC TSC timer for various Intel platforms Signed-off-by: Najumon B.A --- boards/acrn/acrn/acrn_defconfig | 2 +- boards/acrn/acrn/acrn_ehl_crb_defconfig | 2 +- boards/intel/adl/intel_adl_crb_defconfig | 1 + boards/intel/adl/intel_adl_rvp_defconfig | 1 + boards/intel/ehl/intel_ehl_crb_defconfig | 1 + boards/intel/rpl/intel_rpl_p_crb_defconfig | 1 + boards/intel/rpl/intel_rpl_s_crb_defconfig | 1 + boards/up-bridge-the-gap/up_squared/up_squared_defconfig | 4 +--- .../up_squared_pro_7000/up_squared_pro_7000_defconfig | 1 + 9 files changed, 9 insertions(+), 5 deletions(-) diff --git a/boards/acrn/acrn/acrn_defconfig b/boards/acrn/acrn/acrn_defconfig index 0ec5c2b256459f..fe9d1e974a2284 100644 --- a/boards/acrn/acrn/acrn_defconfig +++ b/boards/acrn/acrn/acrn_defconfig @@ -9,8 +9,8 @@ CONFIG_X2APIC=y CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=25000000 CONFIG_BUILD_OUTPUT_BIN=y CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=n CONFIG_KERNEL_VM_SIZE=0x1000000 CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/acrn/acrn/acrn_ehl_crb_defconfig b/boards/acrn/acrn/acrn_ehl_crb_defconfig index f7b256d2c8482a..eca92a16244aa0 100644 --- a/boards/acrn/acrn/acrn_ehl_crb_defconfig +++ b/boards/acrn/acrn/acrn_ehl_crb_defconfig @@ -9,7 +9,6 @@ CONFIG_PCIE=y CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1900000000 CONFIG_BUILD_OUTPUT_BIN=y CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=n CONFIG_KERNEL_VM_SIZE=0x1000000 @@ -17,3 +16,4 @@ CONFIG_BUILD_NO_GAP_FILL=y CONFIG_APIC_TSC_DEADLINE_TIMER=y CONFIG_APIC_TIMER_IRQ_PRIORITY=1 CONFIG_SMP=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/adl/intel_adl_crb_defconfig b/boards/intel/adl/intel_adl_crb_defconfig index fb9be2a4994a30..bb46638e17dd16 100644 --- a/boards/intel/adl/intel_adl_crb_defconfig +++ b/boards/intel/adl/intel_adl_crb_defconfig @@ -10,3 +10,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/adl/intel_adl_rvp_defconfig b/boards/intel/adl/intel_adl_rvp_defconfig index fb9be2a4994a30..bb46638e17dd16 100644 --- a/boards/intel/adl/intel_adl_rvp_defconfig +++ b/boards/intel/adl/intel_adl_rvp_defconfig @@ -10,3 +10,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/ehl/intel_ehl_crb_defconfig b/boards/intel/ehl/intel_ehl_crb_defconfig index ba1c681c4cf9de..9eac9a18020b51 100644 --- a/boards/intel/ehl/intel_ehl_crb_defconfig +++ b/boards/intel/ehl/intel_ehl_crb_defconfig @@ -10,3 +10,4 @@ CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y CONFIG_PCIE_PRT=n +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/rpl/intel_rpl_p_crb_defconfig b/boards/intel/rpl/intel_rpl_p_crb_defconfig index c94efc744f68c4..939e226a7cd724 100644 --- a/boards/intel/rpl/intel_rpl_p_crb_defconfig +++ b/boards/intel/rpl/intel_rpl_p_crb_defconfig @@ -11,3 +11,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/rpl/intel_rpl_s_crb_defconfig b/boards/intel/rpl/intel_rpl_s_crb_defconfig index c94efc744f68c4..939e226a7cd724 100644 --- a/boards/intel/rpl/intel_rpl_s_crb_defconfig +++ b/boards/intel/rpl/intel_rpl_s_crb_defconfig @@ -11,3 +11,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/up-bridge-the-gap/up_squared/up_squared_defconfig b/boards/up-bridge-the-gap/up_squared/up_squared_defconfig index 608e32cdef02b2..f236ba13a52871 100644 --- a/boards/up-bridge-the-gap/up_squared/up_squared_defconfig +++ b/boards/up-bridge-the-gap/up_squared/up_squared_defconfig @@ -10,6 +10,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y - -CONFIG_APIC_TSC_DEADLINE_TIMER=n -CONFIG_HPET_TIMER=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig b/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig index fb9be2a4994a30..bb46638e17dd16 100644 --- a/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig +++ b/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig @@ -10,3 +10,4 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y From 803c66d0e439f8ba9510c636542fd20e831b6e06 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0136/1389] tests: kernel: update test case with sys_clock_hw_cycles_per_sec update test case with sys_clock_hw_cycles_per_sec() api to retrieve system clock frequency (HW cycle per sec) at runtime or statically Signed-off-by: Najumon B.A --- tests/kernel/common/src/boot_delay.c | 2 +- tests/kernel/threads/no-multithreading/src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/kernel/common/src/boot_delay.c b/tests/kernel/common/src/boot_delay.c index 7d4e44630fac84..21f9411aaff3f3 100644 --- a/tests/kernel/common/src/boot_delay.c +++ b/tests/kernel/common/src/boot_delay.c @@ -18,7 +18,7 @@ */ ZTEST(boot_delay, test_bootdelay) { - if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 1000000000) { + if (sys_clock_hw_cycles_per_sec() > 1000000000) { /* Systems with very fast counters (like the x86 TSC) * and long firmware startup (often 10+ seconds on a * EFI PC!) can easily roll this over during startup, diff --git a/tests/kernel/threads/no-multithreading/src/main.c b/tests/kernel/threads/no-multithreading/src/main.c index c4e54b064bc006..0e2db9ec81736d 100644 --- a/tests/kernel/threads/no-multithreading/src/main.c +++ b/tests/kernel/threads/no-multithreading/src/main.c @@ -11,7 +11,7 @@ ZTEST(no_multithreading, test_k_busy_wait) { int64_t now = k_uptime_get(); - uint32_t watchdog = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + uint32_t watchdog = sys_clock_hw_cycles_per_sec(); while (k_uptime_get() != now) { /* Wait until uptime progresses */ From 58a115d1807475ed2a7164323fd1f11000f6fa6d Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0137/1389] Bluetooth: conn: check `k_work_submit()` retcode We still don't know how to handle it but at least it's checked now. Signed-off-by: Jonathan Rico --- subsys/bluetooth/host/conn.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 4006696b736db6..76686ce996569e 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -387,6 +387,7 @@ static void wait_for_tx_work(struct bt_conn *conn) tx_notify(conn); } else { struct k_work_sync sync; + int err; /* API docs mention undefined behavior if syncing on work item * from wq execution context. @@ -394,9 +395,12 @@ static void wait_for_tx_work(struct bt_conn *conn) __ASSERT_NO_MSG(k_current_get() != k_work_queue_thread_get(&k_sys_work_q)); - k_work_submit(&conn->tx_complete_work); + err = k_work_submit(&conn->tx_complete_work); + __ASSERT(err >= 0, "couldn't submit (err %d)", err); + k_work_flush(&conn->tx_complete_work, &sync); } + LOG_DBG("done"); #else ARG_UNUSED(conn); #endif /* CONFIG_BT_CONN_TX */ From 6880dbacff89098be4c27cf6184390df141481f2 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0138/1389] Bluetooth: ATT: add debug log for timeout override Nice to know the stack's ain't having none of your timeouts. Signed-off-by: Jonathan Rico --- subsys/bluetooth/host/att.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 6c73960d979771..0efeccd76da6b9 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -3808,6 +3808,7 @@ struct bt_att_req *bt_att_req_alloc(k_timeout_t timeout) /* No req will be fulfilled while blocking on the bt_recv thread. * Blocking would cause deadlock. */ + LOG_DBG("Timeout discarded. No blocking on bt_recv thread."); timeout = K_NO_WAIT; } From 21640174483c7673372ab50cfc2fd56db18a41b5 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0139/1389] Bluetooth: Fix spelling in some public header files Fixes a few spelling mistakes Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/bluetooth.h | 2 +- include/zephyr/bluetooth/l2cap.h | 2 +- include/zephyr/bluetooth/uuid.h | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index d1621e86bdd517..364514fc343cd4 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -1530,7 +1530,7 @@ struct bt_le_per_adv_sync_recv_info { /** The value of the event counter where the subevent indication was received. */ uint16_t periodic_event_counter; - /** The subevent where the subevend indication was received. */ + /** The subevent where the subevent indication was received. */ uint8_t subevent; #endif /* CONFIG_BT_PER_ADV_SYNC_RSP */ }; diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index ae63c818dd8dd1..02bb706f870689 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -171,7 +171,7 @@ struct bt_l2cap_le_chan { * * If the application has set an alloc_buf channel callback for the * channel to support receiving segmented L2CAP SDUs the application - * should inititalize the MTU of the Receiving Endpoint. Otherwise the + * should initialize the MTU of the Receiving Endpoint. Otherwise the * MTU of the receiving endpoint will be initialized to * @ref BT_L2CAP_SDU_RX_MTU by the stack. * diff --git a/include/zephyr/bluetooth/uuid.h b/include/zephyr/bluetooth/uuid.h index 16943f89e6338f..f430fc7edf5bfa 100644 --- a/include/zephyr/bluetooth/uuid.h +++ b/include/zephyr/bluetooth/uuid.h @@ -432,7 +432,7 @@ struct bt_uuid_128 { #define BT_UUID_CSC \ BT_UUID_DECLARE_16(BT_UUID_CSC_VAL) /** - * @brief Cyclicg Power Service UUID value + * @brief Cycling Power Service UUID value */ #define BT_UUID_CPS_VAL 0x1818 /** @@ -620,7 +620,7 @@ struct bt_uuid_128 { */ #define BT_UUID_ECS_VAL 0x183c /** - * @brief Energency Configuration Service + * @brief Emergency Configuration Service */ #define BT_UUID_ECS \ BT_UUID_DECLARE_16(BT_UUID_ECS_VAL) @@ -1003,11 +1003,11 @@ struct bt_uuid_128 { #define BT_UUID_GAP_APPEARANCE \ BT_UUID_DECLARE_16(BT_UUID_GAP_APPEARANCE_VAL) /** - * @brief GAP Characteristic Peripheal Privacy Flag UUID value + * @brief GAP Characteristic Peripheral Privacy Flag UUID value */ #define BT_UUID_GAP_PPF_VAL 0x2a02 /** - * @brief GAP Characteristic Peripheal Privacy Flag + * @brief GAP Characteristic Peripheral Privacy Flag */ #define BT_UUID_GAP_PPF \ BT_UUID_DECLARE_16(BT_UUID_GAP_PPF_VAL) @@ -3546,7 +3546,7 @@ struct bt_uuid_128 { */ #define BT_UUID_GATT_RCCP_VAL 0x2b1f /** - * @brief GATT Characteristic Reconnection Configurationn Control Point + * @brief GATT Characteristic Reconnection Configuration Control Point */ #define BT_UUID_GATT_RCCP \ BT_UUID_DECLARE_16(BT_UUID_GATT_RCCP_VAL) @@ -3569,11 +3569,11 @@ struct bt_uuid_128 { #define BT_UUID_GATT_IDD_S \ BT_UUID_DECLARE_16(BT_UUID_GATT_IDD_S_VAL) /** - * @brief GATT Characteristic IDD Announciation Status UUID Value + * @brief GATT Characteristic IDD Annunciation Status UUID Value */ #define BT_UUID_GATT_IDD_AS_VAL 0x2b22 /** - * @brief GATT Characteristic IDD Announciation Status + * @brief GATT Characteristic IDD Annunciation Status */ #define BT_UUID_GATT_IDD_AS \ BT_UUID_DECLARE_16(BT_UUID_GATT_IDD_AS_VAL) @@ -3857,7 +3857,7 @@ struct bt_uuid_128 { #define BT_UUID_GATT_SLP_AID \ BT_UUID_DECLARE_16(BT_UUID_GATT_SLP_AID_VAL) /** - * @brief GATT Characteristic Sleep Actiity Summary Data UUID Value + * @brief GATT Characteristic Sleep Activity Summary Data UUID Value */ #define BT_UUID_GATT_SLP_ASD_VAL 0x2b42 /** From 12e39bfeb9bc623e44885dc34e738a16242e9e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0140/1389] tests: drivers: watchdog: Add negative test cases for Watchdog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend test coverage by adding tests that check invalid use of the Watchdog API. Signed-off-by: Sebastian Głąb --- .../watchdog/wdt_error_cases/CMakeLists.txt | 9 + .../watchdog/wdt_error_cases/README.txt | 79 ++ .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 9 + .../drivers/watchdog/wdt_error_cases/prj.conf | 3 + .../watchdog/wdt_error_cases/src/main.c | 960 ++++++++++++++++++ .../watchdog/wdt_error_cases/testcase.yaml | 13 + 6 files changed, 1073 insertions(+) create mode 100644 tests/drivers/watchdog/wdt_error_cases/CMakeLists.txt create mode 100644 tests/drivers/watchdog/wdt_error_cases/README.txt create mode 100644 tests/drivers/watchdog/wdt_error_cases/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/watchdog/wdt_error_cases/prj.conf create mode 100644 tests/drivers/watchdog/wdt_error_cases/src/main.c create mode 100644 tests/drivers/watchdog/wdt_error_cases/testcase.yaml diff --git a/tests/drivers/watchdog/wdt_error_cases/CMakeLists.txt b/tests/drivers/watchdog/wdt_error_cases/CMakeLists.txt new file mode 100644 index 00000000000000..12c8c39535d7ab --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(wdt_error_cases) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/watchdog/wdt_error_cases/README.txt b/tests/drivers/watchdog/wdt_error_cases/README.txt new file mode 100644 index 00000000000000..fcf9173ee93f58 --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/README.txt @@ -0,0 +1,79 @@ +This test suite contains negative test cases for the Watchdog driver. +Test scenarios validate that invalid use of the watchdog driver +returns error code as described in the API documentation +(or Assertion Fail as explained below). + +Ideally, the driver shall be fully compliant with the documentation. +However, it may happen that invalid function call results in +Assertion Fail instead of error code. +Since, main goal is to detect (and report) invalid use of the driver, +both error code and assertion fail set test result as passed. +See for example test_02_wdt_setup_before_setting_timeouts where +ztest_set_assert_valid(true); +is used to catch assertion fail. + +These tests were written to increase test coverage for the Watchdog driver. +Since, coverage data is stored in the RAM, it is lost when watchdog fires. +Therefore, in all test cases watchdog shall NOT expire. +Use other sample to verify positive scenario for the watchdog driver. + +These tests were prepared on a target that had a bug in the wdt_disable() +implementation. As a temporary remedy, order of tests was imposed. +Since, tests are executed alphabetically, order was set by starting +each test name with f.e. 'test_08b_...'. + + +Tests are based on the watchdog API documentation available here: +https://docs.zephyrproject.org/latest/hardware/peripherals/watchdog.html + + +Follow these guidelines when enabling test execution on a new target. + +1. Although, code defines WDT_DISABLE_SUPPORTED but it was tested on a + target that supports disabling the watchdog. + Multiple tests call wdt_setup() which starts the watchdog. + Every test assumes that watchdog is disabled at startup. + As a result, executing this test suite on a target that doesn't + support wdt_disable() may require changes to the code. + When target supports wdt_disable() then extend WDT_TEST_FLAGS with: + #define WDT_TEST_FLAGS (... | WDT_DISABLE_SUPPORTED) + +2. There are three watchdog flags that can be passed to wdt_install_timeout(): + - WDT_FLAG_RESET_NONE - when watchdog expires, it's callback is serviced but + reset doesn't occur. + - WDT_FLAG_RESET_CPU_CORE - when watchdog expires, only one core is reset, while + other cores are not affected. + - WDT_FLAG_RESET_SOC - when watchdog expires, target as "a whole" is reset. + Support for these flags varies between vendors and products. + a) List all supported flags in + #define WDT_TEST_FLAGS (... | WDT_FLAG_RESET_NONE_SUPPORTED | + WDT_FLAG_RESET_CPU_CORE_SUPPORTED | + WDT_FLAG_RESET_SOC_SUPPORTED) + b) Set supported flag in + #define DEFAULT_FLAGS (WDT_FLAG_RESET_SOC) + This define will be used in wdt_install_timeout() "correct" test step. + +3. These tests assume that watchdog driver supports multiple timeouts. Set + #define MAX_INSTALLABLE_TIMEOUTS (8) + +4. When all watchdog timeouts must have exactly the same watchdog timeout value + then extend WDT_TEST_FLAGS with: + #define WDT_TEST_FLAGS (... | WDT_FLAG_ONLY_ONE_TIMEOUT_VALUE_SUPPORTED) + +5. Set maximal allowed watchdog timeout value, f.e.: + #define WDT_WINDOW_MAX_ALLOWED (0xFFFFFFFFU) + Also, test assumes that minimal allowed watchdog timeout value must be zero. + +6. There are two watchdog options that can be passed to wdt_setup(): + - WDT_OPT_PAUSE_IN_SLEEP; + - WDT_OPT_PAUSE_HALTED_BY_DBG. + Support for these options varies between vendors and products. + a) List all supported options in + #define WDT_TEST_FLAGS (... | WDT_OPT_PAUSE_IN_SLEEP_SUPPORTED | + WDT_OPT_PAUSE_HALTED_BY_DBG_SUPPORTED) + b) Set supported option(s) in + #define DEFAULT_OPTIONS (WDT_OPT_PAUSE_IN_SLEEP | WDT_OPT_PAUSE_HALTED_BY_DBG) + This define will be used in wdt_setup() "correct" test step. + +7. When wdt_feed() can stall, extend WDT_TEST_FLAGS with: + #define WDT_TEST_FLAGS (... | WDT_FEED_CAN_STALL) diff --git a/tests/drivers/watchdog/wdt_error_cases/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..8d3dce3b380057 --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt31 { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_error_cases/prj.conf b/tests/drivers/watchdog/wdt_error_cases/prj.conf new file mode 100644 index 00000000000000..be8069f78b4605 --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/prj.conf @@ -0,0 +1,3 @@ +CONFIG_ZTEST=y +CONFIG_ZTEST_ASSERT_HOOK=y +CONFIG_WATCHDOG=y diff --git a/tests/drivers/watchdog/wdt_error_cases/src/main.c b/tests/drivers/watchdog/wdt_error_cases/src/main.c new file mode 100644 index 00000000000000..fc453ba3b321c4 --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/src/main.c @@ -0,0 +1,960 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* + * To use this test, either the devicetree's /aliases must have a + * 'watchdog0' property, or one of the following watchdog compatibles + * must have an enabled node. + */ +#if DT_NODE_HAS_STATUS(DT_ALIAS(watchdog0), okay) +#define WDT_NODE DT_ALIAS(watchdog0) +#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_wdt) +#define WDT_NODE DT_INST(0, nordic_nrf_wdt) +#elif DT_HAS_COMPAT_STATUS_OKAY(zephyr_counter_watchdog) +#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_counter_watchdog) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#define NOINIT_SECTION ".dtcm_noinit.test_wdt" +#else +#define NOINIT_SECTION ".noinit.test_wdt" +#endif + +/* Bit fields used to select tests to be run on the target */ +#define WDT_DISABLE_SUPPORTED BIT(0) +#define WDT_FLAG_RESET_NONE_SUPPORTED BIT(1) +#define WDT_FLAG_RESET_CPU_CORE_SUPPORTED BIT(2) +#define WDT_FLAG_RESET_SOC_SUPPORTED BIT(3) +#define WDT_FLAG_ONLY_ONE_TIMEOUT_VALUE_SUPPORTED BIT(4) +#define WDT_OPT_PAUSE_IN_SLEEP_SUPPORTED BIT(5) +#define WDT_OPT_PAUSE_HALTED_BY_DBG_SUPPORTED BIT(6) +#define WDT_FEED_CAN_STALL BIT(7) + +/* Common for all targets: */ +#define DEFAULT_WINDOW_MAX (500U) +#define DEFAULT_WINDOW_MIN (0U) + +/* Align tests to the specific target: */ +#if defined(CONFIG_SOC_NRF54L15) +#define WDT_TEST_FLAGS \ + (WDT_DISABLE_SUPPORTED | WDT_FLAG_RESET_SOC_SUPPORTED | \ + WDT_FLAG_ONLY_ONE_TIMEOUT_VALUE_SUPPORTED | WDT_OPT_PAUSE_IN_SLEEP_SUPPORTED | \ + WDT_OPT_PAUSE_HALTED_BY_DBG_SUPPORTED) +#define DEFAULT_FLAGS (WDT_FLAG_RESET_SOC) +#define MAX_INSTALLABLE_TIMEOUTS (8) +#define WDT_WINDOW_MAX_ALLOWED (0x07CFFFFFU) +#define DEFAULT_OPTIONS (WDT_OPT_PAUSE_IN_SLEEP | WDT_OPT_PAUSE_HALTED_BY_DBG) +#else +/* By default run most of the error checks. + * See Readme.txt on how to align test scope for the specific target. + */ +#define WDT_TEST_FLAGS \ + (WDT_DISABLE_SUPPORTED | WDT_FLAG_RESET_SOC_SUPPORTED | \ + WDT_FLAG_ONLY_ONE_TIMEOUT_VALUE_SUPPORTED) +#define DEFAULT_FLAGS (WDT_FLAG_RESET_SOC) +#define MAX_INSTALLABLE_TIMEOUTS (8) +#define WDT_WINDOW_MAX_ALLOWED (0xFFFFFFFFU) +#define DEFAULT_OPTIONS (WDT_OPT_PAUSE_IN_SLEEP) +#endif + +static const struct device *const wdt = DEVICE_DT_GET(WDT_NODE); +static struct wdt_timeout_cfg m_cfg_wdt0; + +/* Following variables are incremented in WDT callbacks + * to indicate whether interrupt was fired or not. + */ +volatile uint32_t m_test_06b_value __attribute__((section(NOINIT_SECTION))); +#define TEST_06B_TAG (0x12345678U) +volatile uint32_t m_test_08b_value __attribute__((section(NOINIT_SECTION))); +#define TEST_08B_TAG (0x23456789U) +volatile uint32_t m_test_08d_A_value __attribute__((section(NOINIT_SECTION))); +#define TEST_08D_A_TAG (0x3456789AU) +volatile uint32_t m_test_08d_B_value __attribute__((section(NOINIT_SECTION))); +#define TEST_08D_B_TAG (0x456789ABU) + +static void wdt_test_06b_cb(const struct device *wdt_dev, int channel_id) +{ + ARG_UNUSED(wdt_dev); + ARG_UNUSED(channel_id); + m_test_06b_value = TEST_06B_TAG; +} + +static void wdt_test_08b_cb(const struct device *wdt_dev, int channel_id) +{ + ARG_UNUSED(wdt_dev); + ARG_UNUSED(channel_id); + m_test_08b_value = TEST_08B_TAG; +} + +static void wdt_test_08d_A_cb(const struct device *wdt_dev, int channel_id) +{ + ARG_UNUSED(wdt_dev); + ARG_UNUSED(channel_id); + m_test_08d_A_value = TEST_08D_A_TAG; +} + +static void wdt_test_08d_B_cb(const struct device *wdt_dev, int channel_id) +{ + ARG_UNUSED(wdt_dev); + ARG_UNUSED(channel_id); + m_test_08d_B_value = TEST_08D_B_TAG; +} + +/** + * @brief wdt_disable() negative test + * + * Confirm that wdt_disable() returns + * -EFAULT when watchdog instance is not enabled. + * + */ +ZTEST(wdt_coverage, test_01_wdt_disable_before_wdt_setup) +{ + int ret; + + if (!(WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED)) { + /* Skip this test because wdt_disable() is NOT supported. */ + ztest_test_skip(); + } + + /* Call wdt_disable before enabling wdt */ + ret = wdt_disable(wdt); + zassert_true(ret == -EFAULT, + "Calling wdt_disable before watchdog was started should return -EFAULT (-14), " + "got unexpected value of %d", + ret); +} + +/** + * @brief wdt_setup() negative test + * + * Confirm that wdt_setup() returns error value or ASSERTION FAIL + * when it's called before wdt_install_timeouts(). + * + */ +ZTEST(wdt_coverage, test_02_wdt_setup_before_setting_timeouts) +{ + int ret; + + /* Call wdt_setup before wdt_install_timeouts() */ + ztest_set_assert_valid(true); + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret < 0, + "Calling wdt_setup before installing timeouts should fail, got unexpected " + "value of %d", + ret); +} + +/** + * @brief wdt_feed() negative test + * + * Confirm that wdt_feed() returns error value + * when it's called before wdt_setup(). + * Test scenario where none of timeout channels is configured. + * + */ +ZTEST(wdt_coverage, test_03_wdt_feed_before_wdt_setup_channel_not_configured) +{ + int ret; + + /* Call wdt_feed() before wdt_setup() (channel wasn't configured) */ + ret = wdt_feed(wdt, 0); + zassert_true(ret == -EINVAL, + "wdt_feed() shall return error value when called before wdt_setup(), got " + "unexpected value of %d", + ret); +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns + * -ENOTSUP when flag WDT_FLAG_RESET_NONE is not supported + * + */ +ZTEST(wdt_coverage, test_04a_wdt_install_timeout_WDT_FLAG_RESET_NONE_not_supported) +{ + int ret; + + if (WDT_TEST_FLAGS & WDT_FLAG_RESET_NONE_SUPPORTED) { + /* Skip this test because WDT_FLAG_RESET_NONE is supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = WDT_FLAG_RESET_NONE; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -ENOTSUP, + "WDT_FLAG_RESET_NONE is not supported on this target and should fail, got " + "unexpected value of %d", + ret); +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns + * -ENOTSUP when flag WDT_FLAG_RESET_CPU_CORE is not supported + * + */ +ZTEST(wdt_coverage, test_04b_wdt_install_timeout_WDT_FLAG_RESET_CPU_CORE_not_supported) +{ + int ret; + + if (WDT_TEST_FLAGS & WDT_FLAG_RESET_CPU_CORE_SUPPORTED) { + /* Skip this test because WDT_FLAG_RESET_CPU_CORE is supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = WDT_FLAG_RESET_CPU_CORE; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -ENOTSUP, + "WDT_FLAG_RESET_CPU_CORE is not supported on this target and should fail, got " + "unexpected value of %d", + ret); +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns + * -ENOTSUP when flag WDT_FLAG_RESET_SOC is not supported + * + */ +ZTEST(wdt_coverage, test_04c_wdt_install_timeout_WDT_FLAG_RESET_SOC_not_supported) +{ + int ret; + + if (WDT_TEST_FLAGS & WDT_FLAG_RESET_SOC_SUPPORTED) { + /* Skip this test because WDT_FLAG_RESET_SOC is supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -ENOTSUP, + "WDT_FLAG_RESET_SOC is not supported on this target and should fail, got " + "unexpected value of %d", + ret); +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns + * -EINVAL when window timeout is out of possible range + * + */ +ZTEST(wdt_coverage, test_04w_wdt_install_timeout_with_invalid_window) +{ + int ret; + + /* set defaults */ + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + /* ----------------- window.min + * Check that window.min can't be different than 0 + */ + m_cfg_wdt0.window.min = 1U; + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -EINVAL, + "Calling wdt_install_timeout with window.min = 1 should return -EINVAL (-22), " + "got unexpected value of %d", + ret); + + /* Set default window.min */ + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + /* ----------------- window.max + * Check that window.max can't be equal to 0 + */ + m_cfg_wdt0.window.max = 0U; + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -EINVAL, + "Calling wdt_install_timeout with window.max = 0 should return -EINVAL (-22), " + "got unexpected value of %d", + ret); + + /* Check that window.max can't exceed maximum allowed value */ + m_cfg_wdt0.window.max = WDT_WINDOW_MAX_ALLOWED + 1; + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -EINVAL, + "Calling wdt_install_timeout with window.max = %d should return -EINVAL " + "(-22), got unexpected value of %d", + WDT_WINDOW_MAX_ALLOWED + 1, ret); +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns + * -EINVAL when watchdog supports only one timeout value + * for all timeouts and the supplied timeout window differs + * from windows for alarms installed so far. + * + */ +ZTEST(wdt_coverage, test_04wm_wdt_install_timeout_with_multiple_timeout_values) +{ + int ret; + + if (!(WDT_TEST_FLAGS & WDT_FLAG_ONLY_ONE_TIMEOUT_VALUE_SUPPORTED)) { + /* Skip this test because timeouts with different values are supported */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + /* Call wdt_install_timeout again with different window */ + m_cfg_wdt0.window.max = WDT_WINDOW_MAX_ALLOWED >> 1; + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -EINVAL, + "wdt_install_timeout should return -EINVAL (-22), got unexpected value of %d", + ret); +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns ASSERTION FAIL or + * -EBUSY when called after the watchdog instance has been already setup. + * + */ +ZTEST(wdt_coverage, test_05_wdt_install_timeout_after_wdt_setup) +{ + int ret; + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + + /* Call wdt_install_timeout again to test invalid use */ + ztest_set_assert_valid(true); + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -EBUSY, + "Calling wdt_install_timeout after wdt_setup should return -EBUSY (-16), got " + "unexpected value of %d", + ret); + + /* Assumption: wdt_disable() is called after this test */ +} + +/** + * @brief wdt_setup() negative test + * + * Confirm that wdt_setup() returns + * -ENOTSUP when option WDT_OPT_PAUSE_IN_SLEEP is not supported + * + */ +ZTEST(wdt_coverage, test_06a_wdt_setup_WDT_OPT_PAUSE_IN_SLEEP_not_supported) +{ + int ret; + + if (WDT_TEST_FLAGS & WDT_OPT_PAUSE_IN_SLEEP_SUPPORTED) { + /* Skip this test because WDT_OPT_PAUSE_IN_SLEEP is supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, WDT_OPT_PAUSE_IN_SLEEP); + zassert_true(ret == -ENOTSUP, + "WDT_OPT_PAUSE_IN_SLEEP is not supported on this target and should fail, got " + "unexpected value of %d", + ret); + + ret = wdt_setup(wdt, WDT_OPT_PAUSE_IN_SLEEP | WDT_OPT_PAUSE_HALTED_BY_DBG); + zassert_true(ret == -ENOTSUP, + "WDT_OPT_PAUSE_IN_SLEEP is not supported on this target and should fail, got " + "unexpected value of %d", + ret); +} + +/** + * @brief Test that wdt_setup(device, WDT_OPT_PAUSE_IN_SLEEP) works as expected + * + * Confirm that when WDT_OPT_PAUSE_IN_SLEEP is set, + * watchdog will not fire when thread is sleeping. + * + */ +ZTEST(wdt_coverage, test_06b_wdt_setup_WDT_OPT_PAUSE_IN_SLEEP_functional) +{ + int ret; + + if (!(WDT_TEST_FLAGS & WDT_OPT_PAUSE_IN_SLEEP_SUPPORTED)) { + /* Skip this test because WDT_OPT_PAUSE_IN_SLEEP can NOT be used. */ + ztest_test_skip(); + } + + /* When test fails, watchdog sets m_test_06b_value to TEST_06B_TAG in WDT callback + * wdt_test_06b_cb. Then, target is reset. Check value of m_test_06b_value to prevent reset + * loop on this test. + */ + if (m_test_06b_value == TEST_06B_TAG) { + m_test_06b_value = 0U; + zassert_true(false, "Watchod has fired while it shouldn't"); + } + + /* Clear flag that is set when the watchdog fires */ + m_test_06b_value = 0U; + + m_cfg_wdt0.callback = wdt_test_06b_cb; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + /* Set timeout window to ~500 ms */ + m_cfg_wdt0.window.max = 500U; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, WDT_OPT_PAUSE_IN_SLEEP); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + TC_PRINT("Test has failed if there is reset after this line\n"); + + /* Sleep for longer time than watchdog timeout */ + k_sleep(K_SECONDS(1)); + + /* m_test_06b_value is set to TEST_06B_TAG in WDT callback */ + zassert_equal(m_test_06b_value, 0, "Watchod has fired while it shouldn't"); + + /* Assumption: wdt_disable() is called after each test */ +} + +/** + * @brief wdt_setup() negative test + * + * Confirm that wdt_setup() returns + * -ENOTSUP when option WDT_OPT_PAUSE_HALTED_BY_DBG is not supported + * + */ +ZTEST(wdt_coverage, test_06c_wdt_setup_WDT_OPT_PAUSE_HALTED_BY_DBG_not_supported) +{ + int ret; + + if (WDT_TEST_FLAGS & WDT_OPT_PAUSE_HALTED_BY_DBG_SUPPORTED) { + /* Skip this test because WDT_OPT_PAUSE_HALTED_BY_DBG is supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG); + zassert_true(ret == -ENOTSUP, + "WDT_OPT_PAUSE_HALTED_BY_DBG is not supported on this target and should fail, " + "got unexpected value of %d", + ret); + + ret = wdt_setup(wdt, WDT_OPT_PAUSE_IN_SLEEP | WDT_OPT_PAUSE_HALTED_BY_DBG); + zassert_true(ret == -ENOTSUP, + "WDT_OPT_PAUSE_HALTED_BY_DBG is not supported on this target and should fail, " + "got unexpected value of %d", + ret); +} + +/** + * @brief wdt_setup() corner case + * + * Confirm that wdt_setup() returns + * 0 - success, when no option is provided + * + */ +ZTEST(wdt_coverage, test_06d_wdt_setup_without_any_OPT) +{ + int ret; + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, 0x0); + zassert_true(ret == 0, "Got unexpected value of %d, while expected is 0", ret); +} + +/** + * @brief wdt_setup() negative test + * + * Confirm that wdt_setup() returns + * -EBUSY when watchdog instance has been already setup. + * + */ +ZTEST(wdt_coverage, test_07_wdt_setup_already_done) +{ + int ret; + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + + /* Call wdt_setup again to test invalid use */ + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == -EBUSY, + "Calling wdt_setup for the second time should return -EBUSY (-16), got " + "unexpected value of %d", + ret); + + /* Assumption: wdt_disable() is called after this test */ +} + +/** + * @brief wdt_setup() negative test + * + * Confirm that wdt_disable() returns + * -EPERM when watchdog can not be disabled directly by application code. + * + */ +ZTEST(wdt_coverage, test_08a_wdt_disable_not_supported) +{ + int ret; + + if (WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED) { + /* Skip this test because wdt_disable() is supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + /* Assumption - test suite execution finishes before WDT timeout will fire */ + m_cfg_wdt0.window.max = WDT_WINDOW_MAX_ALLOWED; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + + /* Call wdt_disable to test not allowed use */ + ret = wdt_disable(wdt); + zassert_true(ret == -EPERM, + "Disabling WDT is not supported on this target and should return -EPERM (-1), " + "got unexpected value of %d", + ret); +} + +/** + * @brief Test that wdt_disable() stops watchdog + * + * Confirm that wdt_disable() prevents previously configured + * watchdog from resetting the core. + * + */ +ZTEST(wdt_coverage, test_08b_wdt_disable_check_not_firing) +{ + int ret; + + if (!(WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED)) { + /* Skip this test because wdt_disable() is NOT supported. */ + ztest_test_skip(); + } + + /* When test fails, watchdog sets m_test_08b_value to TEST_08B_TAG in WDT callback + * wdt_test_08b_cb. Then, target is reset. Check value of m_test_08b_value to prevent reset + * loop on this test. + */ + if (m_test_08b_value == TEST_08B_TAG) { + m_test_08b_value = 0U; + zassert_true(false, "Watchod has fired while it shouldn't"); + } + + /* Clear flag that is set when the watchdog fires */ + m_test_08b_value = 0U; + + m_cfg_wdt0.callback = wdt_test_08b_cb; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + /* Set timeout window to ~500 ms */ + m_cfg_wdt0.window.max = 500U; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + TC_PRINT("Test has failed if there is reset after this line\n"); + + /* Wait for 450 ms, then disable the watchdog + * Don't change to k_sleep() because use of WDT_OPT_PAUSE_IN_SLEEP + * will break test scenario. + */ + k_busy_wait(450000); + ret = wdt_disable(wdt); + zassert_true(ret == 0, "Watchdog disable error, got unexpected value of %d", ret); + + /* Wait a bit more to see if watchdog fires + * Don't change to k_sleep() because use of WDT_OPT_PAUSE_IN_SLEEP + * will break test scenario. + */ + k_busy_wait(300000); + + /* m_test_08b_value is set to TEST_08B_TAG in WDT callback */ + zassert_equal(m_test_08b_value, 0, "Watchod has fired while it shouldn't"); +} + +/** + * @brief Test that after wdt_disable() timeouts can be reconfigured + * + * Confirm that after wdt_disable() it is possible to configure + * timeout channel that was configured previously. + * + */ +ZTEST(wdt_coverage, test_08c_wdt_disable_check_timeouts_reusable) +{ + int ret, id1, id2; + + if (!(WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED)) { + /* Skip this test because wdt_disable() is NOT supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + id1 = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(id1 >= 0, "Watchdog install error, got unexpected value of %d", id1); + TC_PRINT("Configured WDT channel %d\n", id1); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + + ret = wdt_disable(wdt); + zassert_true(ret == 0, "Watchdog disable error, got unexpected value of %d", ret); + + id2 = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(id2 >= 0, "Watchdog install error, got unexpected value of %d", id2); + TC_PRINT("Configured WDT channel %d\n", id2); + + /* test that timeout channel id2 is NOT greater than previously returned channel id1 */ + zassert_true(id2 <= id1, + "First usable timeout channel after wdt_disable() is %d, expected number no " + "greater than %d", + id2, id1); +} + +/** + * @brief Test that after wdt_disable() uninstalled timeouts don't have to be feed + * + * Confirm that wdt_disable() uninstalls all timeouts. + * When new timeout is configured, only this one has to be feed. + * + */ +ZTEST(wdt_coverage, test_08d_wdt_disable_check_timeouts_uninstalled) +{ + int ret, id_A, id_B, i; + + if (!(WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED)) { + /* Skip this test because wdt_disable() is NOT supported. */ + ztest_test_skip(); + } + + /* m_test_08d_A_value is set to TEST_08D_A_TAG in callback wdt_test_08d_A_cb */ + if (m_test_08d_A_value == TEST_08D_A_TAG) { + m_test_08d_A_value = 0U; + zassert_true(false, "Timeout A has fired while it shouldn't"); + } + + /* m_test_08d_B_value is set to TEST_08D_B_TAG in callback wdt_test_08d_B_cb */ + if (m_test_08d_B_value == TEST_08D_B_TAG) { + m_test_08d_B_value = 0U; + zassert_true(false, "Timeout B has fired while it shouldn't"); + } + + /* Clear flags that are set when the watchdog fires */ + m_test_08d_A_value = 0U; + m_test_08d_B_value = 0U; + + /* Configure Timeout A */ + m_cfg_wdt0.callback = wdt_test_08d_A_cb; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + /* Set timeout window to ~500 ms */ + m_cfg_wdt0.window.max = 500U; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + id_A = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(id_A >= 0, "Watchdog install error, got unexpected value of %d", id_A); + TC_PRINT("Configured WDT channel %d\n", id_A); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + + ret = wdt_disable(wdt); + zassert_true(ret == 0, "Watchdog disable error, got unexpected value of %d", ret); + + /* Configure Timeout B */ + m_cfg_wdt0.callback = wdt_test_08d_B_cb; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + /* Set timeout window to ~500 ms */ + m_cfg_wdt0.window.max = 500U; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + id_B = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(id_B >= 0, "Watchdog install error, got unexpected value of %d", id_B); + TC_PRINT("Configured WDT channel %d\n", id_B); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + TC_PRINT("Test has failed if there is reset after this line\n"); + + /* Confirm that only Timeout B has to be feed */ + for (i = 0; i < 4; i++) { + k_busy_wait(450000); + wdt_feed(wdt, id_B); + } + + ret = wdt_disable(wdt); + zassert_true(ret == 0, "Watchdog disable error, got unexpected value of %d", ret); + + /* m_test_08d_A_value is set to TEST_08D_A_TAG in callback wdt_test_08d_A_cb */ + zassert_equal(m_test_08d_A_value, 0, "Timeout A has fired while it shouldn't"); + + /* m_test_08d_B_value is set to TEST_08D_B_TAG in callback wdt_test_08d_B_cb */ + zassert_equal(m_test_08d_B_value, 0, "Timeout B has fired while it shouldn't"); +} + +/** + * @brief wdt_feed() negative test + * + * Confirm that wdt_feed() returns error or ASSERTION FAIL + * when it's called before wdt_setup(). + * Test scenario where timeout channel is configured. + * + */ +ZTEST(wdt_coverage, test_09a_wdt_feed_before_wdt_setup_channel_configured) +{ + int ret, ch_id; + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ch_id = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ch_id >= 0, "Watchdog install error, got unexpected value of %d", ch_id); + TC_PRINT("Configured WDT channel %d\n", ch_id); + + /* Call wdt_feed() before wdt_setup() (channel was configured) */ + ztest_set_assert_valid(true); + ret = wdt_feed(wdt, ch_id); + zassert_true(ret < 0, + "wdt_feed() shall return error value when called before wdt_setup(), got " + "unexpected value of %d", + ret); +} + +/** + * @brief wdt_feed() negative test + * + * Confirm that wdt_feed() returns + * -EINVAL when there is no installed timeout for supplied channel. + * + */ +ZTEST(wdt_coverage, test_09b_wdt_feed_invalid_channel) +{ + int ret, ch_id, ch_invalid; + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ch_id = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ch_id >= 0, "Watchdog install error, got unexpected value of %d", ch_id); + TC_PRINT("Configured WDT channel %d\n", ch_id); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + TC_PRINT("Test has failed if there is reset after this line\n"); + + /* Call wdt_feed() on not configured channel */ + ch_invalid = ch_id + 2; + ret = wdt_feed(wdt, ch_invalid); + zassert_true(ret == -EINVAL, + "wdt_feed(%d) shall return -EINVAL (-22), got unexpected value of %d", + ch_invalid, ret); + + /* Call wdt_feed() on not configured channel */ + ch_invalid = ch_id + 1; + ret = wdt_feed(wdt, ch_invalid); + zassert_true(ret == -EINVAL, + "wdt_feed(%d) shall return -EINVAL (-22), got unexpected value of %d", + ch_invalid, ret); + + /* Call wdt_feed() on invalid channel (no such channel) */ + ret = wdt_feed(wdt, -1); + zassert_true(ret == -EINVAL, + "wdt_feed(-1) shall return -EINVAL (-22), got unexpected value of %d", ret); + + /* Call wdt_feed() on invalid channel (no such channel) */ + ret = wdt_feed(wdt, MAX_INSTALLABLE_TIMEOUTS); + zassert_true(ret == -EINVAL, + "wdt_feed(%d) shall return -EINVAL (-22), got unexpected value of %d", + MAX_INSTALLABLE_TIMEOUTS, ret); + + /* Assumption: wdt_disable() is called after each test */ +} + +/** + * @brief wdt_feed() negative test + * + * Confirm that wdt_feed() returns + * -EAGAIN when completing the feed operation would stall the caller, for example + * due to an in-progress watchdog operation such as a previous wdt_feed() call. + * + */ +ZTEST(wdt_coverage, test_09c_wdt_feed_stall) +{ + int ret, ch_id, i; + + if (!(WDT_TEST_FLAGS & WDT_FEED_CAN_STALL)) { + /* Skip this test because wdt_feed() can NOT stall. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ch_id = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ch_id >= 0, "Watchdog install error, got unexpected value of %d", ch_id); + TC_PRINT("Configured WDT channel %d\n", ch_id); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + TC_PRINT("Test has failed if there is reset after this line\n"); + + for (i = 0; i < 5; i++) { + ret = wdt_feed(wdt, ch_id); + if (i == 0) { + zassert_true(ret == 0, "wdt_feed error, got unexpected value of %d", ret); + } else { + zassert_true( + ret == -EAGAIN, + "wdt_feed shall return -EAGAIN (-11), got unexpected value of %d", + ret); + } + } +} + +/** + * @brief wdt_install_timeout() negative test + * + * Confirm that wdt_install_timeout() returns + * -ENOMEM when no more timeouts can be installed. + * + */ +ZTEST(wdt_coverage, test_10_wdt_install_timeout_max_number_of_timeouts) +{ + int i, ret; + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + for (i = 0; i < MAX_INSTALLABLE_TIMEOUTS; i++) { + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + /* Assumption - timeouts are counted from 0 to (MAX_INSTALLABLE_TIMEOUTS - 1) */ + zassert_true(ret < MAX_INSTALLABLE_TIMEOUTS, + "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + } + + /* Call wdt_install_timeout again to test if error value is returned */ + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret == -ENOMEM, + "wdt_install_timeout shall return -ENOMEM (-12), got unexpected value of %d", + ret); +} + +static void *suite_setup(void) +{ + TC_PRINT("Test executed on %s\n", CONFIG_BOARD_TARGET); + TC_PRINT("===================================================================\n"); + + return NULL; +} + +static void before_test(void *not_used) +{ + ARG_UNUSED(not_used); + int ret_val; + + ret_val = device_is_ready(wdt); + zassert_true(ret_val, "WDT device is not ready, got unexpected value of %d", ret_val); +} + +static void cleanup_after_test(void *f) +{ + if (WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED) { + /* Disable watchdog so it doesn't break other tests */ + wdt_disable(wdt); + } +} + +ZTEST_SUITE(wdt_coverage, NULL, suite_setup, before_test, cleanup_after_test, NULL); diff --git a/tests/drivers/watchdog/wdt_error_cases/testcase.yaml b/tests/drivers/watchdog/wdt_error_cases/testcase.yaml new file mode 100644 index 00000000000000..c408d2f8f1d2cc --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/testcase.yaml @@ -0,0 +1,13 @@ +common: + tags: + - drivers + - watchdog + depends_on: watchdog + harness: ztest + +tests: + drivers.watchdog.wdt_error_cases: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp + integration_platforms: + - nrf54l15pdk/nrf54l15/cpuapp From 28d8862365612dd8b432813f8792164f6bd5f35a Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0141/1389] tests: net: tls: fix failures Fix the failures introduced in #72078 by manually enabling all the hash algorithms as they used to be. Signed-off-by: Tomi Fontanilles --- samples/net/sockets/http_get/overlay-tls.conf | 1 + tests/net/socket/tls/prj.conf | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/net/sockets/http_get/overlay-tls.conf b/samples/net/sockets/http_get/overlay-tls.conf index 3dd9096519f42f..29bfc2372f8539 100644 --- a/samples/net/sockets/http_get/overlay-tls.conf +++ b/samples/net/sockets/http_get/overlay-tls.conf @@ -6,5 +6,6 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=60000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=7168 +CONFIG_MBEDTLS_MAC_ALL_ENABLED=y CONFIG_NET_SOCKETS_SOCKOPT_TLS=y diff --git a/tests/net/socket/tls/prj.conf b/tests/net/socket/tls/prj.conf index 1b0c9485aee9ad..94fb56a7142d42 100644 --- a/tests/net/socket/tls/prj.conf +++ b/tests/net/socket/tls/prj.conf @@ -47,3 +47,4 @@ CONFIG_ZTEST_STACK_SIZE=3072 CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=18000 CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y +CONFIG_MBEDTLS_MAC_ALL_ENABLED=y From cfef084b35e34bb485fbf0353841957e6347f82f Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0142/1389] Bluetooth: CSIP: Set Coordinator move data to instances Moved the busy flag and the GATT paramters to the individual CSIP Set Coordinator instances. This allows to use multiple instances in parallel, and thus in turn allow CAP to do things in parallel. This commit has been done with minimal amount of changes, even if there are multiple pieces of code that could likely be refactored to be better. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/csip_set_coordinator.c | 395 ++++++++++-------- 1 file changed, 210 insertions(+), 185 deletions(-) diff --git a/subsys/bluetooth/audio/csip_set_coordinator.c b/subsys/bluetooth/audio/csip_set_coordinator.c index d2dac6f9b6e925..b59587ebdfc7ff 100644 --- a/subsys/bluetooth/audio/csip_set_coordinator.c +++ b/subsys/bluetooth/audio/csip_set_coordinator.c @@ -42,29 +42,30 @@ LOG_MODULE_REGISTER(bt_csip_set_coordinator, CONFIG_BT_CSIP_SET_COORDINATOR_LOG_LEVEL); -static uint8_t gatt_write_buf[1]; -static struct bt_gatt_write_params write_params; -static struct bt_gatt_read_params read_params; -static struct bt_gatt_discover_params discover_params; -static struct bt_csip_set_coordinator_svc_inst *cur_inst; -static bool busy; - static struct active_members { struct bt_csip_set_coordinator_set_member *members[CONFIG_BT_MAX_CONN]; const struct bt_csip_set_coordinator_set_info *info; uint8_t members_count; uint8_t members_handled; uint8_t members_restored; + bool in_progress; bt_csip_set_coordinator_ordered_access_t oap_cb; } active; struct bt_csip_set_coordinator_inst { uint8_t inst_count; - struct bt_csip_set_coordinator_svc_inst svc_insts - [CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES]; + bool busy; + uint8_t gatt_write_buf[1]; + + struct bt_csip_set_coordinator_svc_inst + svc_insts[CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES]; struct bt_csip_set_coordinator_set_member set_member; struct bt_conn *conn; + struct bt_csip_set_coordinator_svc_inst *cur_inst; + struct bt_gatt_discover_params discover_params; + struct bt_gatt_read_params read_params; + struct bt_gatt_write_params write_params; }; static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0); @@ -336,8 +337,8 @@ static void discover_complete(struct bt_csip_set_coordinator_inst *client, { struct bt_csip_set_coordinator_cb *listener; - cur_inst = NULL; - busy = false; + client->cur_inst = NULL; + client->busy = false; SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) { if (listener->discover) { @@ -529,30 +530,34 @@ static int csip_set_coordinator_write_set_lock(struct bt_csip_set_coordinator_sv bool lock, bt_gatt_write_func_t cb) { + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(inst->conn)]; + if (inst->set_lock_handle == 0) { LOG_DBG("Handle not set"); - cur_inst = NULL; + client->cur_inst = NULL; return -EINVAL; } /* Write to call control point */ - gatt_write_buf[0] = lock ? BT_CSIP_LOCK_VALUE : BT_CSIP_RELEASE_VALUE; - write_params.data = gatt_write_buf; - write_params.length = sizeof(lock); - write_params.func = cb; - write_params.handle = inst->set_lock_handle; + client->gatt_write_buf[0] = lock ? BT_CSIP_LOCK_VALUE : BT_CSIP_RELEASE_VALUE; + client->write_params.data = client->gatt_write_buf; + client->write_params.length = sizeof(lock); + client->write_params.func = cb; + client->write_params.handle = inst->set_lock_handle; - return bt_gatt_write(inst->conn, &write_params); + return bt_gatt_write(inst->conn, &client->write_params); } static int read_set_sirk(struct bt_csip_set_coordinator_svc_inst *svc_inst) { - if (cur_inst != NULL) { - if (cur_inst != svc_inst) { + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(svc_inst->conn)]; + + if (client->cur_inst != NULL) { + if (client->cur_inst != svc_inst) { return -EBUSY; } } else { - cur_inst = svc_inst; + client->cur_inst = svc_inst; } if (svc_inst->set_sirk_handle == 0) { @@ -560,86 +565,93 @@ static int read_set_sirk(struct bt_csip_set_coordinator_svc_inst *svc_inst) return -EINVAL; } - read_params.func = csip_set_coordinator_discover_insts_read_set_sirk_cb; - read_params.handle_count = 1; - read_params.single.handle = svc_inst->set_sirk_handle; - read_params.single.offset = 0U; + client->read_params.func = csip_set_coordinator_discover_insts_read_set_sirk_cb; + client->read_params.handle_count = 1; + client->read_params.single.handle = svc_inst->set_sirk_handle; + client->read_params.single.offset = 0U; - return bt_gatt_read(svc_inst->conn, &read_params); + return bt_gatt_read(svc_inst->conn, &client->read_params); } static int csip_set_coordinator_read_set_size(struct bt_conn *conn, uint8_t inst_idx, bt_gatt_read_func_t cb) { + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; + if (inst_idx >= CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES) { return -EINVAL; - } else if (cur_inst != NULL) { - if (cur_inst != bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx)) { + } else if (client->cur_inst != NULL) { + if (client->cur_inst != + bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx)) { return -EBUSY; } } else { - cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx); - if (cur_inst == NULL) { + client->cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx); + if (client->cur_inst == NULL) { LOG_DBG("Inst not found"); return -EINVAL; } } - if (cur_inst->set_size_handle == 0) { + if (client->cur_inst->set_size_handle == 0) { LOG_DBG("Handle not set"); - cur_inst = NULL; + client->cur_inst = NULL; return -EINVAL; } - read_params.func = cb; - read_params.handle_count = 1; - read_params.single.handle = cur_inst->set_size_handle; - read_params.single.offset = 0U; + client->read_params.func = cb; + client->read_params.handle_count = 1; + client->read_params.single.handle = client->cur_inst->set_size_handle; + client->read_params.single.offset = 0U; - return bt_gatt_read(conn, &read_params); + return bt_gatt_read(conn, &client->read_params); } static int csip_set_coordinator_read_rank(struct bt_conn *conn, uint8_t inst_idx, bt_gatt_read_func_t cb) { + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; + if (inst_idx >= CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES) { return -EINVAL; - } else if (cur_inst != NULL) { - if (cur_inst != bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx)) { + } else if (client->cur_inst != NULL) { + if (client->cur_inst != + bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx)) { return -EBUSY; } } else { - cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx); - if (cur_inst == NULL) { + client->cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx); + if (client->cur_inst == NULL) { LOG_DBG("Inst not found"); return -EINVAL; } } - if (cur_inst->rank_handle == 0) { + if (client->cur_inst->rank_handle == 0) { LOG_DBG("Handle not set"); - cur_inst = NULL; + client->cur_inst = NULL; return -EINVAL; } - read_params.func = cb; - read_params.handle_count = 1; - read_params.single.handle = cur_inst->rank_handle; - read_params.single.offset = 0U; + client->read_params.func = cb; + client->read_params.handle_count = 1; + client->read_params.single.handle = client->cur_inst->rank_handle; + client->read_params.single.offset = 0U; - return bt_gatt_read(conn, &read_params); + return bt_gatt_read(conn, &client->read_params); } -static int csip_set_coordinator_discover_sets(struct bt_csip_set_coordinator_set_member *member) +static int csip_set_coordinator_discover_sets(struct bt_csip_set_coordinator_inst *client) { + struct bt_csip_set_coordinator_set_member *member = &client->set_member; int err; /* Start reading values and call CB when done */ err = read_set_sirk((struct bt_csip_set_coordinator_svc_inst *)member->insts[0].svc_inst); if (err == 0) { - busy = true; + client->busy = true; } return err; @@ -655,21 +667,22 @@ static uint8_t discover_func(struct bt_conn *conn, void *notify_handler = NULL; if (attr == NULL) { - LOG_DBG("Setup complete for %u / %u", cur_inst->idx + 1, client->inst_count); + LOG_DBG("Setup complete for %u / %u", client->cur_inst->idx + 1, + client->inst_count); (void)memset(params, 0, sizeof(*params)); if (CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES > 1 && - (cur_inst->idx + 1) < client->inst_count) { + (client->cur_inst->idx + 1) < client->inst_count) { int err; - cur_inst = &client->svc_insts[cur_inst->idx + 1]; - discover_params.uuid = NULL; - discover_params.start_handle = cur_inst->start_handle; - discover_params.end_handle = cur_inst->end_handle; - discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; - discover_params.func = discover_func; + client->cur_inst = &client->svc_insts[client->cur_inst->idx + 1]; + client->discover_params.uuid = NULL; + client->discover_params.start_handle = client->cur_inst->start_handle; + client->discover_params.end_handle = client->cur_inst->end_handle; + client->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + client->discover_params.func = discover_func; - err = bt_gatt_discover(conn, &discover_params); + err = bt_gatt_discover(conn, &client->discover_params); if (err != 0) { LOG_DBG("Discover failed (err %d)", err); discover_complete(client, err); @@ -678,9 +691,9 @@ static uint8_t discover_func(struct bt_conn *conn, } else { int err; - cur_inst = NULL; - busy = false; - err = csip_set_coordinator_discover_sets(&client->set_member); + client->cur_inst = NULL; + client->busy = false; + err = csip_set_coordinator_discover_sets(client); if (err != 0) { LOG_DBG("Discover sets failed (err %d)", err); discover_complete(client, err); @@ -696,30 +709,30 @@ static uint8_t discover_func(struct bt_conn *conn, chrc = (struct bt_gatt_chrc *)attr->user_data; if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_SET_SIRK) == 0) { LOG_DBG("Set SIRK"); - cur_inst->set_sirk_handle = chrc->value_handle; - sub_params = &cur_inst->sirk_sub_params; - sub_params->disc_params = &cur_inst->sirk_sub_disc_params; + client->cur_inst->set_sirk_handle = chrc->value_handle; + sub_params = &client->cur_inst->sirk_sub_params; + sub_params->disc_params = &client->cur_inst->sirk_sub_disc_params; notify_handler = sirk_notify_func; } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_SET_SIZE) == 0) { LOG_DBG("Set size"); - cur_inst->set_size_handle = chrc->value_handle; - sub_params = &cur_inst->size_sub_params; - sub_params->disc_params = &cur_inst->size_sub_disc_params; + client->cur_inst->set_size_handle = chrc->value_handle; + sub_params = &client->cur_inst->size_sub_params; + sub_params->disc_params = &client->cur_inst->size_sub_disc_params; notify_handler = size_notify_func; } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_SET_LOCK) == 0) { struct bt_csip_set_coordinator_set_info *set_info; LOG_DBG("Set lock"); - cur_inst->set_lock_handle = chrc->value_handle; - sub_params = &cur_inst->lock_sub_params; - sub_params->disc_params = &cur_inst->lock_sub_disc_params; + client->cur_inst->set_lock_handle = chrc->value_handle; + sub_params = &client->cur_inst->lock_sub_params; + sub_params->disc_params = &client->cur_inst->lock_sub_disc_params; notify_handler = lock_notify_func; - set_info = &client->set_member.insts[cur_inst->idx].info; + set_info = &client->set_member.insts[client->cur_inst->idx].info; set_info->lockable = true; } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_RANK) == 0) { LOG_DBG("Set rank"); - cur_inst->rank_handle = chrc->value_handle; + client->cur_inst->rank_handle = chrc->value_handle; } if (sub_params != NULL && notify_handler != NULL) { @@ -735,7 +748,7 @@ static uint8_t discover_func(struct bt_conn *conn, /* With ccc_handle == 0 it will use auto discovery */ sub_params->ccc_handle = 0; - sub_params->end_handle = cur_inst->end_handle; + sub_params->end_handle = client->cur_inst->end_handle; sub_params->value_handle = chrc->value_handle; sub_params->notify = notify_handler; atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE); @@ -769,14 +782,14 @@ static uint8_t primary_discover_func(struct bt_conn *conn, if (client->inst_count != 0) { int err; - cur_inst = &client->svc_insts[0]; - discover_params.uuid = NULL; - discover_params.start_handle = cur_inst->start_handle; - discover_params.end_handle = cur_inst->end_handle; - discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; - discover_params.func = discover_func; + client->cur_inst = &client->svc_insts[0]; + client->discover_params.uuid = NULL; + client->discover_params.start_handle = client->cur_inst->start_handle; + client->discover_params.end_handle = client->cur_inst->end_handle; + client->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + client->discover_params.func = discover_func; - err = bt_gatt_discover(conn, &discover_params); + err = bt_gatt_discover(conn, &client->discover_params); if (err != 0) { LOG_DBG("Discover failed (err %d)", err); discover_complete(client, err); @@ -792,14 +805,14 @@ static uint8_t primary_discover_func(struct bt_conn *conn, if (params->type == BT_GATT_DISCOVER_PRIMARY) { prim_service = (struct bt_gatt_service_val *)attr->user_data; - discover_params.start_handle = attr->handle + 1; - - cur_inst = &client->svc_insts[client->inst_count]; - cur_inst->idx = client->inst_count; - cur_inst->start_handle = attr->handle; - cur_inst->end_handle = prim_service->end_handle; - cur_inst->conn = bt_conn_ref(conn); - cur_inst->set_info = &client->set_member.insts[cur_inst->idx].info; + client->discover_params.start_handle = attr->handle + 1; + + client->cur_inst = &client->svc_insts[client->inst_count]; + client->cur_inst->idx = client->inst_count; + client->cur_inst->start_handle = attr->handle; + client->cur_inst->end_handle = prim_service->end_handle; + client->cur_inst->conn = bt_conn_ref(conn); + client->cur_inst->set_info = &client->set_member.insts[client->cur_inst->idx].info; client->inst_count++; } @@ -843,9 +856,9 @@ static uint8_t csip_set_coordinator_discover_insts_read_rank_cb(struct bt_conn * { struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; - __ASSERT(cur_inst != NULL, "cur_inst must not be NULL"); + __ASSERT(client->cur_inst != NULL, "client->cur_inst must not be NULL"); - busy = false; + client->busy = false; if (err != 0) { LOG_DBG("err: 0x%02X", err); @@ -856,7 +869,7 @@ static uint8_t csip_set_coordinator_discover_insts_read_rank_cb(struct bt_conn * LOG_HEXDUMP_DBG(data, length, "Data read"); - set_info = &client->set_member.insts[cur_inst->idx].info; + set_info = &client->set_member.insts[client->cur_inst->idx].info; if (length == sizeof(set_info->rank)) { (void)memcpy(&set_info->rank, data, length); @@ -877,9 +890,9 @@ static uint8_t csip_set_coordinator_discover_insts_read_set_size_cb( { struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; - __ASSERT(cur_inst != NULL, "cur_inst must not be NULL"); + __ASSERT(client->cur_inst != NULL, "client->cur_inst must not be NULL"); - busy = false; + client->busy = false; if (err != 0) { LOG_DBG("err: 0x%02X", err); @@ -890,7 +903,7 @@ static uint8_t csip_set_coordinator_discover_insts_read_set_size_cb( LOG_HEXDUMP_DBG(data, length, "Data read"); - set_info = &client->set_member.insts[cur_inst->idx].info; + set_info = &client->set_member.insts[client->cur_inst->idx].info; if (length == sizeof(set_info->set_size)) { (void)memcpy(&set_info->set_size, data, length); @@ -899,7 +912,7 @@ static uint8_t csip_set_coordinator_discover_insts_read_set_size_cb( LOG_DBG("Invalid length"); } - discover_insts_resume(conn, 0, 0, cur_inst->rank_handle); + discover_insts_resume(conn, 0, 0, client->cur_inst->rank_handle); } return BT_GATT_ITER_STOP; @@ -910,7 +923,7 @@ static int parse_sirk(struct bt_csip_set_coordinator_inst *client, { uint8_t *set_sirk; - set_sirk = client->set_member.insts[cur_inst->idx].info.set_sirk; + set_sirk = client->set_member.insts[client->cur_inst->idx].info.set_sirk; if (length == sizeof(struct bt_csip_set_sirk)) { struct bt_csip_set_sirk *sirk = @@ -960,9 +973,9 @@ static uint8_t csip_set_coordinator_discover_insts_read_set_sirk_cb( { struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; int cb_err = err; - __ASSERT(cur_inst != NULL, "cur_inst must not be NULL"); + __ASSERT(client->cur_inst != NULL, "client->cur_inst must not be NULL"); - busy = false; + client->busy = false; if (err != 0) { LOG_DBG("err: 0x%02X", err); @@ -976,9 +989,8 @@ static uint8_t csip_set_coordinator_discover_insts_read_set_sirk_cb( if (cb_err != 0) { LOG_DBG("Could not parse SIRK: %d", cb_err); } else { - discover_insts_resume(conn, 0, - cur_inst->set_size_handle, - cur_inst->rank_handle); + discover_insts_resume(conn, 0, client->cur_inst->set_size_handle, + client->cur_inst->rank_handle); } } @@ -1003,28 +1015,28 @@ static void discover_insts_resume(struct bt_conn *conn, uint16_t sirk_handle, if (size_handle != 0) { cb_err = csip_set_coordinator_read_set_size( - conn, cur_inst->idx, - csip_set_coordinator_discover_insts_read_set_size_cb); + conn, client->cur_inst->idx, + csip_set_coordinator_discover_insts_read_set_size_cb); if (cb_err != 0) { LOG_DBG("Could not read set size: %d", cb_err); } } else if (rank_handle != 0) { cb_err = csip_set_coordinator_read_rank( - conn, cur_inst->idx, - csip_set_coordinator_discover_insts_read_rank_cb); + conn, client->cur_inst->idx, + csip_set_coordinator_discover_insts_read_rank_cb); if (cb_err != 0) { LOG_DBG("Could not read set rank: %d", cb_err); } } else { - uint8_t next_idx = cur_inst->idx + 1; + uint8_t next_idx = client->cur_inst->idx + 1; - cur_inst = NULL; + client->cur_inst = NULL; if (next_idx < client->inst_count) { - cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, - next_idx); + client->cur_inst = + bt_csip_set_coordinator_lookup_instance_by_index(conn, next_idx); /* Read next */ - cb_err = read_set_sirk(cur_inst); + cb_err = read_set_sirk(client->cur_inst); } else { discover_complete(client, 0); @@ -1035,7 +1047,7 @@ static void discover_insts_resume(struct bt_conn *conn, uint16_t sirk_handle, if (cb_err != 0) { discover_complete(client, cb_err); } else { - busy = true; + client->busy = true; } } @@ -1043,7 +1055,9 @@ static void csip_set_coordinator_write_restore_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params) { - busy = false; + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; + + client->busy = false; if (err != 0) { LOG_WRN("Could not restore (%d)", err); @@ -1061,18 +1075,17 @@ static void csip_set_coordinator_write_restore_cb(struct bt_conn *conn, int csip_err; member = active.members[active.members_handled - active.members_restored - 1]; - cur_inst = lookup_instance_by_set_info(member, active.info); - if (cur_inst == NULL) { + client->cur_inst = lookup_instance_by_set_info(member, active.info); + if (client->cur_inst == NULL) { release_set_complete(-ENOENT); return; } csip_err = csip_set_coordinator_write_set_lock( - cur_inst, false, - csip_set_coordinator_write_restore_cb); + client->cur_inst, false, csip_set_coordinator_write_restore_cb); if (csip_err == 0) { - busy = true; + client->busy = true; } else { LOG_DBG("Failed to release next member[%u]: %d", active.members_handled, csip_err); @@ -1088,7 +1101,9 @@ static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params) { - busy = false; + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; + + client->busy = false; if (err != 0) { LOG_DBG("Could not lock (0x%X)", err); @@ -1099,9 +1114,8 @@ static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn, active.members_restored = 0; member = active.members[active.members_handled - active.members_restored]; - cur_inst = lookup_instance_by_set_info(member, - active.info); - if (cur_inst == NULL) { + client->cur_inst = lookup_instance_by_set_info(member, active.info); + if (client->cur_inst == NULL) { LOG_DBG("Failed to lookup instance by set_info %p", active.info); lock_set_complete(-ENOENT); @@ -1109,10 +1123,9 @@ static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn, } csip_err = csip_set_coordinator_write_set_lock( - cur_inst, false, - csip_set_coordinator_write_restore_cb); + client->cur_inst, false, csip_set_coordinator_write_restore_cb); if (csip_err == 0) { - busy = true; + client->busy = true; } else { LOG_WRN("Could not release lock of previous locked member: %d", csip_err); @@ -1130,21 +1143,20 @@ static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn, LOG_DBG("Locked %u/%u members", active.members_handled, active.members_count); if (active.members_handled < active.members_count) { - struct bt_csip_set_coordinator_svc_inst *prev_inst = cur_inst; + struct bt_csip_set_coordinator_svc_inst *prev_inst = client->cur_inst; int csip_err; - cur_inst = get_next_active_instance(); - if (cur_inst == NULL) { + client->cur_inst = get_next_active_instance(); + if (client->cur_inst == NULL) { lock_set_complete(-ENOENT); return; } - csip_err = csip_set_coordinator_write_set_lock( - cur_inst, true, - csip_set_coordinator_write_lock_cb); + csip_err = csip_set_coordinator_write_set_lock(client->cur_inst, true, + csip_set_coordinator_write_lock_cb); if (csip_err == 0) { - busy = true; + client->busy = true; } else { LOG_DBG("Failed to lock next member[%u]: %d", active.members_handled, csip_err); @@ -1155,7 +1167,7 @@ static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn, prev_inst, false, csip_set_coordinator_write_restore_cb); if (csip_err == 0) { - busy = true; + client->busy = true; } else { LOG_WRN("Could not release lock of previous locked member: %d", csip_err); @@ -1171,7 +1183,9 @@ static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn, static void csip_set_coordinator_write_release_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params) { - busy = false; + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; + + client->busy = false; if (err != 0) { LOG_DBG("Could not release lock (%d)", err); @@ -1186,18 +1200,17 @@ static void csip_set_coordinator_write_release_cb(struct bt_conn *conn, uint8_t if (active.members_handled < active.members_count) { int csip_err; - cur_inst = get_next_active_instance(); - if (cur_inst == NULL) { + client->cur_inst = get_next_active_instance(); + if (client->cur_inst == NULL) { release_set_complete(-ENOENT); return; } csip_err = csip_set_coordinator_write_set_lock( - cur_inst, false, - csip_set_coordinator_write_release_cb); + client->cur_inst, false, csip_set_coordinator_write_release_cb); if (csip_err == 0) { - busy = true; + client->busy = true; } else { LOG_DBG("Failed to release next member[%u]: %d", active.members_handled, csip_err); @@ -1230,9 +1243,10 @@ static uint8_t csip_set_coordinator_read_lock_cb(struct bt_conn *conn, const void *data, uint16_t length) { + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)]; uint8_t value = 0; - busy = false; + client->busy = false; if (err != 0) { LOG_DBG("Could not read lock value (0x%X)", err); @@ -1245,7 +1259,7 @@ static uint8_t csip_set_coordinator_read_lock_cb(struct bt_conn *conn, active.members_handled++; LOG_DBG("Read lock state on %u/%u members", active.members_handled, active.members_count); - if (data == NULL || length != sizeof(cur_inst->set_lock)) { + if (data == NULL || length != sizeof(client->cur_inst->set_lock)) { LOG_DBG("Invalid data %p or length %u", data, length); csip_set_coordinator_lock_state_read_cb(err, false); @@ -1263,7 +1277,7 @@ static uint8_t csip_set_coordinator_read_lock_cb(struct bt_conn *conn, return BT_GATT_ITER_STOP; } - cur_inst->set_lock = value; + client->cur_inst->set_lock = value; if (value != BT_CSIP_RELEASE_VALUE) { LOG_DBG("Set member not unlocked"); @@ -1276,16 +1290,16 @@ static uint8_t csip_set_coordinator_read_lock_cb(struct bt_conn *conn, if (active.members_handled < active.members_count) { int csip_err; - cur_inst = get_next_active_instance(); - if (cur_inst == NULL) { + client->cur_inst = get_next_active_instance(); + if (client->cur_inst == NULL) { csip_set_coordinator_lock_state_read_cb(-ENOENT, false); return BT_GATT_ITER_STOP; } - csip_err = csip_set_coordinator_read_set_lock(cur_inst); + csip_err = csip_set_coordinator_read_set_lock(client->cur_inst); if (csip_err == 0) { - busy = true; + client->busy = true; } else { LOG_DBG("Failed to read next member[%u]: %d", active.members_handled, csip_err); @@ -1301,18 +1315,28 @@ static uint8_t csip_set_coordinator_read_lock_cb(struct bt_conn *conn, static int csip_set_coordinator_read_set_lock(struct bt_csip_set_coordinator_svc_inst *inst) { + struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(inst->conn)]; + int err; + if (inst->set_lock_handle == 0) { LOG_DBG("Handle not set"); - cur_inst = NULL; + client->cur_inst = NULL; return -EINVAL; } - read_params.func = csip_set_coordinator_read_lock_cb; - read_params.handle_count = 1; - read_params.single.handle = inst->set_lock_handle; - read_params.single.offset = 0; + client->read_params.func = csip_set_coordinator_read_lock_cb; + client->read_params.handle_count = 1; + client->read_params.single.handle = inst->set_lock_handle; + client->read_params.single.offset = 0; + + client->cur_inst = inst; + + err = bt_gatt_read(inst->conn, &client->read_params); + if (err != 0) { + client->cur_inst = NULL; + } - return bt_gatt_read(inst->conn, &read_params); + return err; } static void csip_set_coordinator_reset(struct bt_csip_set_coordinator_inst *inst) @@ -1418,29 +1442,28 @@ int bt_csip_set_coordinator_discover(struct bt_conn *conn) return -EINVAL; } - if (busy) { + client = &client_insts[bt_conn_index(conn)]; + if (client->busy) { return -EBUSY; } - client = &client_insts[bt_conn_index(conn)]; - csip_set_coordinator_reset(client); /* Discover CSIS on peer, setup handles and notify */ - (void)memset(&discover_params, 0, sizeof(discover_params)); + (void)memset(&client->discover_params, 0, sizeof(client->discover_params)); (void)memcpy(&uuid, BT_UUID_CSIS, sizeof(uuid)); - discover_params.func = primary_discover_func; - discover_params.uuid = &uuid.uuid; - discover_params.type = BT_GATT_DISCOVER_PRIMARY; - discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; - discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + client->discover_params.func = primary_discover_func; + client->discover_params.uuid = &uuid.uuid; + client->discover_params.type = BT_GATT_DISCOVER_PRIMARY; + client->discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + client->discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; - err = bt_gatt_discover(conn, &discover_params); + err = bt_gatt_discover(conn, &client->discover_params); if (err == 0) { for (size_t i = 0; i < ARRAY_SIZE(client->set_member.insts); i++) { client->set_member.insts[i].svc_inst = (void *)&client->svc_insts[i]; } - busy = true; + client->busy = true; client->conn = bt_conn_ref(conn); } @@ -1526,8 +1549,8 @@ static int bt_csip_set_coordinator_get_lock_state( { int err; - if (busy) { - LOG_DBG("csip_set_coordinator busy"); + if (active.in_progress) { + LOG_DBG("Procedure in progress"); return -EBUSY; } @@ -1540,20 +1563,20 @@ static int bt_csip_set_coordinator_get_lock_state( active_members_store_ordered(members, count, set_info, true); for (uint8_t i = 0U; i < count; i++) { - cur_inst = lookup_instance_by_set_info(active.members[i], active.info); - if (cur_inst == NULL) { + struct bt_csip_set_coordinator_svc_inst *svc_inst; + + svc_inst = lookup_instance_by_set_info(active.members[i], active.info); + if (svc_inst == NULL) { LOG_DBG("Failed to lookup instance by set_info %p", active.info); active_members_reset(); return -ENOENT; } - if (cur_inst->set_info->lockable) { - err = csip_set_coordinator_read_set_lock(cur_inst); + if (svc_inst->set_info->lockable) { + err = csip_set_coordinator_read_set_lock(svc_inst); if (err == 0) { - busy = true; - } else { - cur_inst = NULL; + active.in_progress = true; } break; @@ -1562,7 +1585,7 @@ static int bt_csip_set_coordinator_get_lock_state( active.members_handled++; } - if (!busy && err == 0) { + if (!active.in_progress && err == 0) { /* We are not reading any lock states (because they are not on the remote devices), * so we can just initiate the ordered access procedure (oap) callback directly * here. @@ -1604,10 +1627,11 @@ int bt_csip_set_coordinator_lock( uint8_t count, const struct bt_csip_set_coordinator_set_info *set_info) { + struct bt_csip_set_coordinator_svc_inst *svc_inst; int err; - CHECKIF(busy) { - LOG_DBG("csip_set_coordinator busy"); + CHECKIF(active.in_progress) { + LOG_DBG("Procedure in progress"); return -EBUSY; } @@ -1619,18 +1643,18 @@ int bt_csip_set_coordinator_lock( active_members_store_ordered(members, count, set_info, true); - cur_inst = lookup_instance_by_set_info(active.members[0], active.info); - if (cur_inst == NULL) { + svc_inst = lookup_instance_by_set_info(active.members[0], active.info); + if (svc_inst == NULL) { LOG_DBG("Failed to lookup instance by set_info %p", active.info); active_members_reset(); return -ENOENT; } - err = csip_set_coordinator_write_set_lock(cur_inst, true, + err = csip_set_coordinator_write_set_lock(svc_inst, true, csip_set_coordinator_write_lock_cb); if (err == 0) { - busy = true; + active.in_progress = true; } return err; @@ -1640,10 +1664,11 @@ int bt_csip_set_coordinator_release(const struct bt_csip_set_coordinator_set_mem uint8_t count, const struct bt_csip_set_coordinator_set_info *set_info) { + struct bt_csip_set_coordinator_svc_inst *svc_inst; int err; - CHECKIF(busy) { - LOG_DBG("csip_set_coordinator busy"); + CHECKIF(active.in_progress) { + LOG_DBG("Procedure in progress"); return -EBUSY; } @@ -1655,18 +1680,18 @@ int bt_csip_set_coordinator_release(const struct bt_csip_set_coordinator_set_mem active_members_store_ordered(members, count, set_info, false); - cur_inst = lookup_instance_by_set_info(active.members[0], active.info); - if (cur_inst == NULL) { + svc_inst = lookup_instance_by_set_info(active.members[0], active.info); + if (svc_inst == NULL) { LOG_DBG("Failed to lookup instance by set_info %p", active.info); active_members_reset(); return -ENOENT; } - err = csip_set_coordinator_write_set_lock(cur_inst, false, + err = csip_set_coordinator_write_set_lock(svc_inst, false, csip_set_coordinator_write_release_cb); if (err == 0) { - busy = true; + active.in_progress = true; } return err; From c4c19ca4334011d0a81c1df613f633a76943adaf Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0143/1389] Bluetooth: CAP: Fix issue with parallel CAP discover The bt_cap_common_discover function relied on a global variable used to indicate that a discovery was in process. This global variable prevented multiple discoveries to take place on multiple ACL connections, where the intention was to stop multiple discoveries on the same ACL. This has been fixed by moving the variable into the struct bt_cap_common_client, so that it applies per connection, rather than a global check. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/cap_common.c | 20 ++++++++++++-------- subsys/bluetooth/audio/cap_internal.h | 7 ++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/subsys/bluetooth/audio/cap_common.c b/subsys/bluetooth/audio/cap_common.c index 277b904355b2f7..23de8c19cb7ecf 100644 --- a/subsys/bluetooth/audio/cap_common.c +++ b/subsys/bluetooth/audio/cap_common.c @@ -17,7 +17,6 @@ LOG_MODULE_REGISTER(bt_cap_common, CONFIG_BT_CAP_COMMON_LOG_LEVEL); static struct bt_cap_common_client bt_cap_common_clients[CONFIG_BT_MAX_CONN]; static const struct bt_uuid *cas_uuid = BT_UUID_CAS; static struct bt_cap_common_proc active_proc; -static bt_cap_common_discover_func_t discover_cb_func; struct bt_cap_common_proc *bt_cap_common_get_active_proc(void) { @@ -258,10 +257,13 @@ struct bt_cap_common_client *bt_cap_common_get_client(enum bt_cap_set_type type, static void cap_common_discover_complete(struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { - if (discover_cb_func != NULL) { - const bt_cap_common_discover_func_t cb_func = discover_cb_func; + struct bt_cap_common_client *client; + + client = bt_cap_common_get_client_by_acl(conn); + if (client != NULL && client->discover_cb_func != NULL) { + const bt_cap_common_discover_func_t cb_func = client->discover_cb_func; - discover_cb_func = NULL; + client->discover_cb_func = NULL; cb_func(conn, err, csis_inst); } } @@ -386,24 +388,26 @@ static uint8_t bt_cap_common_discover_cas_cb(struct bt_conn *conn, const struct int bt_cap_common_discover(struct bt_conn *conn, bt_cap_common_discover_func_t func) { struct bt_gatt_discover_params *param; + struct bt_cap_common_client *client; int err; - if (discover_cb_func != NULL) { + client = bt_cap_common_get_client_by_acl(conn); + if (client->discover_cb_func != NULL) { return -EBUSY; } - param = &bt_cap_common_clients[bt_conn_index(conn)].param; + param = &client->param; param->func = bt_cap_common_discover_cas_cb; param->uuid = cas_uuid; param->type = BT_GATT_DISCOVER_PRIMARY; param->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; param->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; - discover_cb_func = func; + client->discover_cb_func = func; err = bt_gatt_discover(conn, param); if (err != 0) { - discover_cb_func = NULL; + client->discover_cb_func = NULL; /* Report expected possible errors */ if (err == -ENOTCONN || err == -ENOMEM) { diff --git a/subsys/bluetooth/audio/cap_internal.h b/subsys/bluetooth/audio/cap_internal.h index c2dc861da3dd95..2210110703ff4d 100644 --- a/subsys/bluetooth/audio/cap_internal.h +++ b/subsys/bluetooth/audio/cap_internal.h @@ -101,6 +101,9 @@ struct bt_cap_commander_proc_param { }; }; +typedef void (*bt_cap_common_discover_func_t)( + struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_csis_inst *csis_inst); + struct bt_cap_common_proc_param { union { #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST) @@ -133,6 +136,7 @@ struct bt_cap_common_proc { struct bt_cap_common_client { struct bt_conn *conn; struct bt_gatt_discover_params param; + bt_cap_common_discover_func_t discover_cb_func; uint16_t csis_start_handle; const struct bt_csip_set_coordinator_csis_inst *csis_inst; bool cas_found; @@ -158,7 +162,4 @@ struct bt_cap_common_client * bt_cap_common_get_client_by_csis(const struct bt_csip_set_coordinator_csis_inst *csis_inst); struct bt_cap_common_client *bt_cap_common_get_client(enum bt_cap_set_type type, const union bt_cap_set_member *member); - -typedef void (*bt_cap_common_discover_func_t)( - struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_csis_inst *csis_inst); int bt_cap_common_discover(struct bt_conn *conn, bt_cap_common_discover_func_t func); From 4f0b85bf3928a095a62211b25f0642999b9f4b34 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0144/1389] Tests: Bluetooth: CAP: Refactor some CAP commander functions Refactor som CAP commander test functions to perform operations in parallel, rather than sequential. The CAP initiator functions are kept sequential so that we are testing both versions. Signed-off-by: Emil Gydesen --- tests/bsim/bluetooth/audio/prj.conf | 1 + .../bluetooth/audio/src/cap_commander_test.c | 188 ++++++++++++------ 2 files changed, 129 insertions(+), 60 deletions(-) diff --git a/tests/bsim/bluetooth/audio/prj.conf b/tests/bsim/bluetooth/audio/prj.conf index 6da97725909bd1..1afbca08502e08 100644 --- a/tests/bsim/bluetooth/audio/prj.conf +++ b/tests/bsim/bluetooth/audio/prj.conf @@ -196,6 +196,7 @@ CONFIG_BT_HAS_CLIENT_LOG_LEVEL_DBG=y CONFIG_BT_CAP_ACCEPTOR_LOG_LEVEL_DBG=y CONFIG_BT_CAP_INITIATOR_LOG_LEVEL_DBG=y CONFIG_BT_CAP_COMMANDER_LOG_LEVEL_DBG=y +CONFIG_BT_CAP_COMMON_LOG_LEVEL_DBG=y CONFIG_BT_GMAP_LOG_LEVEL_DBG=y # LOGGING diff --git a/tests/bsim/bluetooth/audio/src/cap_commander_test.c b/tests/bsim/bluetooth/audio/src/cap_commander_test.c index 1a8bb6dd7f6319..9271a6a12dee54 100644 --- a/tests/bsim/bluetooth/audio/src/cap_commander_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_commander_test.c @@ -12,18 +12,22 @@ #include #include #include +#include #include #include "common.h" #include "bap_common.h" +#define SEM_TIMEOUT K_SECONDS(5) + extern enum bst_result_t bst_result; static struct bt_conn *connected_conns[CONFIG_BT_MAX_CONN]; static volatile size_t connected_conn_cnt; -CREATE_FLAG(flag_cas_discovered); -CREATE_FLAG(flag_vcs_discovered); -CREATE_FLAG(flag_mics_discovered); +static struct k_sem sem_disconnected; +static struct k_sem sem_cas_discovered; +static struct k_sem sem_vcs_discovered; +static struct k_sem sem_mics_discovered; CREATE_FLAG(flag_mtu_exchanged); CREATE_FLAG(flag_volume_changed); CREATE_FLAG(flag_volume_mute_changed); @@ -35,7 +39,7 @@ static void cap_discovery_complete_cb(struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { - FAIL("Failed to discover CAS: %d\n", err); + FAIL("Discover failed on %p: %d\n", (void *)conn, err); return; } @@ -47,12 +51,12 @@ static void cap_discovery_complete_cb(struct bt_conn *conn, int err, return; } - printk("Found CAS with CSIS %p\n", csis_inst); + printk("Found CAS on %p with CSIS %p\n", (void *)conn, csis_inst); } else { - printk("Found CAS\n"); + printk("Found CAS on %p\n", (void *)conn); } - SET_FLAG(flag_cas_discovered); + k_sem_give(&sem_cas_discovered); } #if defined(CONFIG_BT_VCP_VOL_CTLR) @@ -140,7 +144,7 @@ static void cap_vcp_discover_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8 } printk("VCS for %p found with %u VOCS and %u AICS\n", vol_ctlr, vocs_count, aics_count); - SET_FLAG(flag_vcs_discovered); + k_sem_give(&sem_vcs_discovered); } static void cap_vcp_state_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t volume, @@ -168,7 +172,7 @@ static void cap_micp_discover_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err, uin } printk("MICS for %p found with %u AICS\n", mic_ctlr, aics_count); - SET_FLAG(flag_mics_discovered); + k_sem_give(&sem_mics_discovered); } static struct bt_micp_mic_ctlr_cb micp_cb = { @@ -185,8 +189,16 @@ static struct bt_gatt_cb gatt_callbacks = { .att_mtu_updated = att_mtu_updated, }; -static void init(void) +static void cap_disconnected_cb(struct bt_conn *conn, uint8_t reason) +{ + k_sem_give(&sem_disconnected); +} + +static void init(size_t acceptor_cnt) { + static struct bt_conn_cb conn_cb = { + .disconnected = cap_disconnected_cb, + }; int err; err = bt_enable(NULL); @@ -196,6 +208,7 @@ static void init(void) } bt_gatt_cb_register(&gatt_callbacks); + bt_conn_cb_register(&conn_cb); err = bt_cap_commander_register_cb(&cap_cb); if (err != 0) { @@ -214,6 +227,11 @@ static void init(void) FAIL("Failed to register MICP callbacks (err %d)\n", err); return; } + + k_sem_init(&sem_disconnected, 0, acceptor_cnt); + k_sem_init(&sem_cas_discovered, 0, acceptor_cnt); + k_sem_init(&sem_vcs_discovered, 0, acceptor_cnt); + k_sem_init(&sem_mics_discovered, 0, acceptor_cnt); } static void cap_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, @@ -276,62 +294,117 @@ static void scan_and_connect(void) connected_conn_cnt++; } -static void disconnect_acl(struct bt_conn *conn) +static void disconnect_acl(size_t acceptor_cnt) { - int err; + k_sem_reset(&sem_disconnected); - err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); - if (err != 0) { - FAIL("Failed to disconnect (err %d)\n", err); - return; + for (size_t i = 0U; i < acceptor_cnt; i++) { + struct bt_conn *conn = connected_conns[i]; + int err; + + printk("Disconnecting %p\n", (void *)conn); + + err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0) { + FAIL("Failed to disconnect %p (err %d)\n", (void *)conn, err); + return; + } + } + + for (size_t i = 0U; i < acceptor_cnt; i++) { + const int err = k_sem_take(&sem_disconnected, SEM_TIMEOUT); + + if (err != 0) { + const struct bt_conn *conn = connected_conns[i]; + + FAIL("Failed to take sem_disconnected for %p: %d", (void *)conn, err); + } } } -static void discover_cas(struct bt_conn *conn) +static void discover_cas(size_t acceptor_cnt) { - int err; + k_sem_reset(&sem_cas_discovered); - UNSET_FLAG(flag_cas_discovered); + /* Do parallel discovery */ + for (size_t i = 0U; i < acceptor_cnt; i++) { + struct bt_conn *conn = connected_conns[i]; + int err; - err = bt_cap_commander_discover(conn); - if (err != 0) { - printk("Failed to discover CAS: %d\n", err); - return; + printk("Discovering CAS on %p\n", (void *)conn); + + err = bt_cap_commander_discover(conn); + if (err != 0) { + FAIL("Failed to discover CAS on %p: %d\n", (void *)conn, err); + return; + } } - WAIT_FOR_FLAG(flag_cas_discovered); + for (size_t i = 0U; i < acceptor_cnt; i++) { + const int err = k_sem_take(&sem_cas_discovered, SEM_TIMEOUT); + + if (err != 0) { + const struct bt_conn *conn = connected_conns[i]; + + FAIL("Failed to take sem_cas_discovered for %p: %d", (void *)conn, err); + } + } } -static void discover_vcs(struct bt_conn *conn) +static void discover_vcs(size_t acceptor_cnt) { - struct bt_vcp_vol_ctlr *vol_ctlr; - int err; + k_sem_reset(&sem_vcs_discovered); - UNSET_FLAG(flag_vcs_discovered); + /* Do parallel discovery */ + for (size_t i = 0U; i < acceptor_cnt; i++) { + struct bt_conn *conn = connected_conns[i]; + struct bt_vcp_vol_ctlr *vol_ctlr; + int err; - err = bt_vcp_vol_ctlr_discover(conn, &vol_ctlr); - if (err != 0) { - FAIL("Failed to discover VCS: %d\n", err); - return; + printk("Discovering VCS on %p\n", (void *)conn); + + err = bt_vcp_vol_ctlr_discover(conn, &vol_ctlr); + if (err != 0) { + FAIL("Failed to discover VCS on %p: %d\n", err); + return; + } } - WAIT_FOR_FLAG(flag_vcs_discovered); + for (size_t i = 0U; i < acceptor_cnt; i++) { + const int err = k_sem_take(&sem_vcs_discovered, SEM_TIMEOUT); + + if (err != 0) { + const struct bt_conn *conn = connected_conns[i]; + + FAIL("Failed to take sem_vcs_discovered for %p: %d", (void *)conn, err); + } + } } -static void discover_mics(struct bt_conn *conn) +static void discover_mics(size_t acceptor_cnt) { - struct bt_micp_mic_ctlr *mic_ctlr; - int err; + k_sem_reset(&sem_mics_discovered); - UNSET_FLAG(flag_mics_discovered); + for (size_t i = 0U; i < acceptor_cnt; i++) { + struct bt_micp_mic_ctlr *mic_ctlr; + int err; - err = bt_micp_mic_ctlr_discover(conn, &mic_ctlr); - if (err != 0) { - FAIL("Failed to discover MICS: %d\n", err); - return; + err = bt_micp_mic_ctlr_discover(connected_conns[i], &mic_ctlr); + if (err != 0) { + FAIL("Failed to discover MICS: %d\n", err); + return; + } } - WAIT_FOR_FLAG(flag_mics_discovered); + for (size_t i = 0U; i < acceptor_cnt; i++) { + const int err = k_sem_take(&sem_mics_discovered, SEM_TIMEOUT); + + if (err != 0) { + const struct bt_conn *conn = connected_conns[i]; + + FAIL("Failed to take sem_mics_discovered for %p: %d", (void *)conn, err); + } + } } static void test_change_volume(void) @@ -477,29 +550,25 @@ static void test_change_microphone_gain(void) static void test_main_cap_commander_capture_and_render(void) { - init(); + const size_t acceptor_cnt = get_dev_cnt() - 1; /* Assume all other devices are acceptors + */ + init(acceptor_cnt); /* Connect to and do discovery on all CAP acceptors */ - for (size_t i = 0U; i < get_dev_cnt() - 1; i++) { + for (size_t i = 0U; i < acceptor_cnt; i++) { scan_and_connect(); WAIT_FOR_FLAG(flag_mtu_exchanged); - - /* TODO: We should use CSIP to find set members */ - discover_cas(connected_conns[i]); - discover_cas(connected_conns[i]); /* test that we can discover twice */ - - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - discover_vcs(connected_conns[i]); - } - - if (IS_ENABLED(CONFIG_BT_MICP_MIC_CTLR)) { - discover_mics(connected_conns[i]); - } } + /* TODO: We should use CSIP to find set members */ + discover_cas(acceptor_cnt); + discover_cas(acceptor_cnt); /* verify that we can discover twice */ + if (IS_ENABLED(CONFIG_BT_CSIP_SET_COORDINATOR)) { if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { + discover_vcs(acceptor_cnt); + test_change_volume(); test_change_volume_mute(true); @@ -511,6 +580,8 @@ static void test_main_cap_commander_capture_and_render(void) } if (IS_ENABLED(CONFIG_BT_MICP_MIC_CTLR)) { + discover_mics(acceptor_cnt); + test_change_microphone_mute(true); test_change_microphone_mute(false); @@ -521,10 +592,7 @@ static void test_main_cap_commander_capture_and_render(void) } /* Disconnect all CAP acceptors */ - for (size_t i = 0U; i < connected_conn_cnt; i++) { - disconnect_acl(connected_conns[i]); - } - connected_conn_cnt = 0U; + disconnect_acl(acceptor_cnt); PASS("CAP commander capture and rendering passed\n"); } From 3ba461b8e0256277846376390557289b9d0386ad Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0145/1389] Revert "kernel: retrieve system timer clock frequency at runtime or static" This reverts commit 7c03e5de7f0298e9219f82da52b75696c45baa9d. https://github.com/zephyrproject-rtos/zephyr/pull/69705 Introduced a regression in main in which tests/subsys/logging/log_timestamp started failing. (See https://github.com/zephyrproject-rtos/zephyr/issues/72344 for more info). Let's revert the PR. It can be submitted after with the issue fixed. Signed-off-by: Alberto Escolar Piedras --- include/zephyr/sys_clock.h | 8 ++++---- kernel/Kconfig | 1 - kernel/timeout.c | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/zephyr/sys_clock.h b/include/zephyr/sys_clock.h index eab5df34d077fc..e43b539fb8f54b 100644 --- a/include/zephyr/sys_clock.h +++ b/include/zephyr/sys_clock.h @@ -146,9 +146,9 @@ typedef struct { /** @endcond */ -#if defined(CONFIG_SYS_CLOCK_EXISTS) && !defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) -BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC != 0, - "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!"); +#if defined(CONFIG_SYS_CLOCK_EXISTS) && \ + (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0) +#error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!" #endif @@ -164,7 +164,7 @@ BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC != 0, * @{ */ -#if defined(CONFIG_SYS_CLOCK_EXISTS) && !defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) +#ifdef CONFIG_SYS_CLOCK_EXISTS #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) || \ (MSEC_PER_SEC % CONFIG_SYS_CLOCK_TICKS_PER_SEC) || \ diff --git a/kernel/Kconfig b/kernel/Kconfig index c237a5af48a765..af51267edbf1fc 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -799,7 +799,6 @@ config SYS_CLOCK_TICKS_PER_SEC config SYS_CLOCK_HW_CYCLES_PER_SEC int "System clock's h/w timer frequency" - depends on !TIMER_READS_ITS_FREQUENCY_AT_RUNTIME help This option specifies the frequency of the hardware timer used for the system clock (in Hz). This option is set by the SOC's or board's Kconfig file diff --git a/kernel/timeout.c b/kernel/timeout.c index 55ba6dd3d2f8ff..8c727e204f91b7 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -25,7 +25,7 @@ static struct k_spinlock timeout_lock; static int announce_remaining; #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) -int z_clock_hw_cycles_per_sec; +int z_clock_hw_cycles_per_sec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; #ifdef CONFIG_USERSPACE static inline int z_vrfy_sys_clock_hw_cycles_per_sec_runtime_get(void) From 59fe914700ddf27d45ba27c8cc6690966696c61f Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0146/1389] Revert "board: x86: enable system timer clock frequency at run time" This reverts commit 8eabf80159e28d338f39d07d691caea8f267220e. https://github.com/zephyrproject-rtos/zephyr/pull/69705 Introduced a regression in main in which tests/subsys/logging/log_timestamp started failing. (See https://github.com/zephyrproject-rtos/zephyr/issues/72344 for more info). Let's revert the PR. It can be submitted after with the issue fixed. Signed-off-by: Alberto Escolar Piedras --- boards/acrn/acrn/acrn_defconfig | 2 +- boards/acrn/acrn/acrn_ehl_crb_defconfig | 2 +- boards/intel/adl/intel_adl_crb_defconfig | 1 - boards/intel/adl/intel_adl_rvp_defconfig | 1 - boards/intel/ehl/intel_ehl_crb_defconfig | 1 - boards/intel/rpl/intel_rpl_p_crb_defconfig | 1 - boards/intel/rpl/intel_rpl_s_crb_defconfig | 1 - boards/up-bridge-the-gap/up_squared/up_squared_defconfig | 4 +++- .../up_squared_pro_7000/up_squared_pro_7000_defconfig | 1 - 9 files changed, 5 insertions(+), 9 deletions(-) diff --git a/boards/acrn/acrn/acrn_defconfig b/boards/acrn/acrn/acrn_defconfig index fe9d1e974a2284..0ec5c2b256459f 100644 --- a/boards/acrn/acrn/acrn_defconfig +++ b/boards/acrn/acrn/acrn_defconfig @@ -9,8 +9,8 @@ CONFIG_X2APIC=y CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=25000000 CONFIG_BUILD_OUTPUT_BIN=y CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=n CONFIG_KERNEL_VM_SIZE=0x1000000 CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/acrn/acrn/acrn_ehl_crb_defconfig b/boards/acrn/acrn/acrn_ehl_crb_defconfig index eca92a16244aa0..f7b256d2c8482a 100644 --- a/boards/acrn/acrn/acrn_ehl_crb_defconfig +++ b/boards/acrn/acrn/acrn_ehl_crb_defconfig @@ -9,6 +9,7 @@ CONFIG_PCIE=y CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1900000000 CONFIG_BUILD_OUTPUT_BIN=y CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=n CONFIG_KERNEL_VM_SIZE=0x1000000 @@ -16,4 +17,3 @@ CONFIG_BUILD_NO_GAP_FILL=y CONFIG_APIC_TSC_DEADLINE_TIMER=y CONFIG_APIC_TIMER_IRQ_PRIORITY=1 CONFIG_SMP=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/adl/intel_adl_crb_defconfig b/boards/intel/adl/intel_adl_crb_defconfig index bb46638e17dd16..fb9be2a4994a30 100644 --- a/boards/intel/adl/intel_adl_crb_defconfig +++ b/boards/intel/adl/intel_adl_crb_defconfig @@ -10,4 +10,3 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/adl/intel_adl_rvp_defconfig b/boards/intel/adl/intel_adl_rvp_defconfig index bb46638e17dd16..fb9be2a4994a30 100644 --- a/boards/intel/adl/intel_adl_rvp_defconfig +++ b/boards/intel/adl/intel_adl_rvp_defconfig @@ -10,4 +10,3 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/ehl/intel_ehl_crb_defconfig b/boards/intel/ehl/intel_ehl_crb_defconfig index 9eac9a18020b51..ba1c681c4cf9de 100644 --- a/boards/intel/ehl/intel_ehl_crb_defconfig +++ b/boards/intel/ehl/intel_ehl_crb_defconfig @@ -10,4 +10,3 @@ CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y CONFIG_PCIE_PRT=n -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/rpl/intel_rpl_p_crb_defconfig b/boards/intel/rpl/intel_rpl_p_crb_defconfig index 939e226a7cd724..c94efc744f68c4 100644 --- a/boards/intel/rpl/intel_rpl_p_crb_defconfig +++ b/boards/intel/rpl/intel_rpl_p_crb_defconfig @@ -11,4 +11,3 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/intel/rpl/intel_rpl_s_crb_defconfig b/boards/intel/rpl/intel_rpl_s_crb_defconfig index 939e226a7cd724..c94efc744f68c4 100644 --- a/boards/intel/rpl/intel_rpl_s_crb_defconfig +++ b/boards/intel/rpl/intel_rpl_s_crb_defconfig @@ -11,4 +11,3 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y diff --git a/boards/up-bridge-the-gap/up_squared/up_squared_defconfig b/boards/up-bridge-the-gap/up_squared/up_squared_defconfig index f236ba13a52871..608e32cdef02b2 100644 --- a/boards/up-bridge-the-gap/up_squared/up_squared_defconfig +++ b/boards/up-bridge-the-gap/up_squared/up_squared_defconfig @@ -10,4 +10,6 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y + +CONFIG_APIC_TSC_DEADLINE_TIMER=n +CONFIG_HPET_TIMER=y diff --git a/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig b/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig index bb46638e17dd16..fb9be2a4994a30 100644 --- a/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig +++ b/boards/up-bridge-the-gap/up_squared_pro_7000/up_squared_pro_7000_defconfig @@ -10,4 +10,3 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y -CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME=y From 099009a3e4489f776abd08973b0498694af532a6 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0147/1389] Revert "tests: kernel: update test case with sys_clock_hw_cycles_per_sec" This reverts commit fd8ca83e9a1c0aafa3f62bc185c9f4140d9164c5. https://github.com/zephyrproject-rtos/zephyr/pull/69705 Introduced a regression in main in which tests/subsys/logging/log_timestamp started failing. (See https://github.com/zephyrproject-rtos/zephyr/issues/72344 for more info). Let's revert the PR. It can be submitted after with the issue fixed. Signed-off-by: Alberto Escolar Piedras --- tests/kernel/common/src/boot_delay.c | 2 +- tests/kernel/threads/no-multithreading/src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/kernel/common/src/boot_delay.c b/tests/kernel/common/src/boot_delay.c index 21f9411aaff3f3..7d4e44630fac84 100644 --- a/tests/kernel/common/src/boot_delay.c +++ b/tests/kernel/common/src/boot_delay.c @@ -18,7 +18,7 @@ */ ZTEST(boot_delay, test_bootdelay) { - if (sys_clock_hw_cycles_per_sec() > 1000000000) { + if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 1000000000) { /* Systems with very fast counters (like the x86 TSC) * and long firmware startup (often 10+ seconds on a * EFI PC!) can easily roll this over during startup, diff --git a/tests/kernel/threads/no-multithreading/src/main.c b/tests/kernel/threads/no-multithreading/src/main.c index 0e2db9ec81736d..c4e54b064bc006 100644 --- a/tests/kernel/threads/no-multithreading/src/main.c +++ b/tests/kernel/threads/no-multithreading/src/main.c @@ -11,7 +11,7 @@ ZTEST(no_multithreading, test_k_busy_wait) { int64_t now = k_uptime_get(); - uint32_t watchdog = sys_clock_hw_cycles_per_sec(); + uint32_t watchdog = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; while (k_uptime_get() != now) { /* Wait until uptime progresses */ From 5ef368222827ef813fab0b18f3f70a77f5117616 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0148/1389] Revert "drivers: timer: tsc: retrieve clock frequency of system timer at runtime" This reverts commit d82f4a92583fc423d97080db43130ccac4f69456. https://github.com/zephyrproject-rtos/zephyr/pull/69705 Introduced a regression in main in which tests/subsys/logging/log_timestamp started failing. (See https://github.com/zephyrproject-rtos/zephyr/issues/72344 for more info). Let's revert the PR. It can be submitted after with the issue fixed. Signed-off-by: Alberto Escolar Piedras --- drivers/timer/apic_tsc.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 2b8d5873242b8f..59b0017375c3db 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -8,18 +8,12 @@ #include #include #include -#include #define IA32_TSC_DEADLINE_MSR 0x6e0 #define IA32_TSC_ADJUST_MSR 0x03b -#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME -static uint64_t CYC_PER_TICK; -extern int z_clock_hw_cycles_per_sec; -#else #define CYC_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \ / (uint64_t) CONFIG_SYS_CLOCK_TICKS_PER_SEC) -#endif struct apic_timer_lvt { uint8_t vector : 8; @@ -164,11 +158,9 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t * static int sys_clock_driver_init(void) { -#if defined(CONFIG_ASSERT) || defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) +#ifdef CONFIG_ASSERT uint32_t eax, ebx, ecx, edx; -#endif -#ifdef CONFIG_ASSERT eax = 1; ecx = 0; cpuid(&eax, &ebx, &ecx, &edx); __ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support"); @@ -182,23 +174,6 @@ static int sys_clock_driver_init(void) __ASSERT((ebx & BIT(1)) != 0, "No TSC_ADJUST MSR support"); #endif -#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME - int tsc_freq; - - eax = 0; - ebx = 0; - ecx = 0; - if (!__get_cpuid(0x15, &eax, &ebx, &ecx, &edx)) { - __ASSERT(false, "error cpuid leaf 0x15\n"); - } - - __ASSERT((ebx != 0) && (ecx != 0), "No TSC/core crystal clock ratio is enumerated"); - - tsc_freq = (uint32_t)((ecx * (uint64_t)ebx) / eax); - z_clock_hw_cycles_per_sec = tsc_freq; - CYC_PER_TICK = tsc_freq/CONFIG_SYS_CLOCK_TICKS_PER_SEC; -#endif - clear_tsc_adjust(); /* Timer interrupt number is runtime-fetched, so can't use From 30fff69a1fec72b4deb16e8956318bb63c80c550 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Sun, 26 May 2024 22:38:31 +0200 Subject: [PATCH 0149/1389] samples: drivers: display: Fix drawing on non-x8 height VTILED display VTILED displays with a height other than x8 fail to draw bottom-row tiles. This is because it extends beyond the display area. I fixed the drawing area to be cropped to fit within the display. Signed-off-by: TOKITA Hiroshi --- samples/drivers/display/src/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/samples/drivers/display/src/main.c b/samples/drivers/display/src/main.c index a9267b51c747c7..fb81955c78aada 100644 --- a/samples/drivers/display/src/main.c +++ b/samples/drivers/display/src/main.c @@ -298,6 +298,14 @@ int main(void) buf_desc.height = h_step; for (int idx = 0; idx < capabilities.y_resolution; idx += h_step) { + /* + * Tweaking the height value not to draw outside of the display. + * It is required when using a monochrome display whose vertical + * resolution can not be divided by 8. + */ + if ((capabilities.y_resolution - idx) < h_step) { + buf_desc.height = (capabilities.y_resolution - idx); + } display_write(display_dev, 0, idx, &buf_desc, buf); } From f22216d654935e2abce0e11192e56db2518e807c Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0150/1389] drivers: ht16k33: convert from kscan to input Convert the ht16k33 to use the input subsystem. This can still be used with the kscan API with the zephyr,kscan-input driver, or use the input-keymap one to generate input codes instead. Signed-off-by: Fabio Baltieri --- drivers/kscan/CMakeLists.txt | 1 - drivers/kscan/Kconfig | 1 - drivers/kscan/Kconfig.ht16k33 | 13 ---- drivers/kscan/kscan_ht16k33.c | 63 ------------------- drivers/led/Kconfig.ht16k33 | 3 +- drivers/led/ht16k33.c | 29 ++------- .../kscan/holtek,ht16k33-keyscan.yaml | 7 --- include/zephyr/drivers/led/ht16k33.h | 27 -------- .../boards/nrf52840dk_nrf52840.overlay | 4 +- samples/drivers/ht16k33/prj.conf | 2 +- samples/drivers/ht16k33/src/main.c | 2 +- 11 files changed, 11 insertions(+), 141 deletions(-) delete mode 100644 drivers/kscan/Kconfig.ht16k33 delete mode 100644 drivers/kscan/kscan_ht16k33.c delete mode 100644 dts/bindings/kscan/holtek,ht16k33-keyscan.yaml delete mode 100644 include/zephyr/drivers/led/ht16k33.h diff --git a/drivers/kscan/CMakeLists.txt b/drivers/kscan/CMakeLists.txt index 5e846edcb36444..1108cd616290aa 100644 --- a/drivers/kscan/CMakeLists.txt +++ b/drivers/kscan/CMakeLists.txt @@ -4,7 +4,6 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/kscan.h) zephyr_library() -zephyr_library_sources_ifdef(CONFIG_KSCAN_HT16K33 kscan_ht16k33.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_INPUT kscan_input.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE kscan_handlers.c) diff --git a/drivers/kscan/Kconfig b/drivers/kscan/Kconfig index de9b79255ea8cc..ed0910bbd271d5 100644 --- a/drivers/kscan/Kconfig +++ b/drivers/kscan/Kconfig @@ -10,7 +10,6 @@ menuconfig KSCAN if KSCAN -source "drivers/kscan/Kconfig.ht16k33" source "drivers/kscan/Kconfig.input" module = KSCAN diff --git a/drivers/kscan/Kconfig.ht16k33 b/drivers/kscan/Kconfig.ht16k33 deleted file mode 100644 index ef16347ede2774..00000000000000 --- a/drivers/kscan/Kconfig.ht16k33 +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2019 - 2021 Henrik Brix Andersen -# SPDX-License-Identifier: Apache-2.0 - -config KSCAN_HT16K33 - bool "HT16K33 keyscan driver" - default y - depends on DT_HAS_HOLTEK_HT16K33_KEYSCAN_ENABLED - help - Enable keyscan driver for HT16K33. - - The HT16K33 is a memory mapping, multifunction LED - controller driver. The controller supports matrix key scan - circuit of up to 13x3 keys. diff --git a/drivers/kscan/kscan_ht16k33.c b/drivers/kscan/kscan_ht16k33.c deleted file mode 100644 index 9595874e9083f3..00000000000000 --- a/drivers/kscan/kscan_ht16k33.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2019 - 2021 Henrik Brix Andersen - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT holtek_ht16k33_keyscan - -/** - * @file - * @brief Keyscan driver for the HT16K33 I2C LED driver - */ - -#include -#include -#include -#include - -LOG_MODULE_REGISTER(kscan_ht16k33, CONFIG_KSCAN_LOG_LEVEL); - -BUILD_ASSERT(CONFIG_KSCAN_INIT_PRIORITY > CONFIG_LED_INIT_PRIORITY, - "HT16K33 keyscan driver must be initialized after HT16K33 LED driver"); - -struct kscan_ht16k33_cfg { - const struct device *parent; -}; - -static int kscan_ht16k33_config(const struct device *dev, - kscan_callback_t callback) -{ - const struct kscan_ht16k33_cfg *config = dev->config; - - return ht16k33_register_keyscan_callback(config->parent, dev, callback); -} - -static int kscan_ht16k33_init(const struct device *dev) -{ - const struct kscan_ht16k33_cfg *config = dev->config; - - if (!device_is_ready(config->parent)) { - LOG_ERR("HT16K33 parent device not ready"); - return -EINVAL; - } - - return 0; -} - -static const struct kscan_driver_api kscan_ht16k33_api = { - .config = kscan_ht16k33_config, -}; - -#define KSCAN_HT16K33_DEVICE(id) \ - static const struct kscan_ht16k33_cfg kscan_ht16k33_##id##_cfg = { \ - .parent = DEVICE_DT_GET(DT_INST_BUS(id)), \ - }; \ - \ - DEVICE_DT_INST_DEFINE(id, &kscan_ht16k33_init, \ - NULL, NULL, \ - &kscan_ht16k33_##id##_cfg, POST_KERNEL, \ - CONFIG_KSCAN_INIT_PRIORITY, \ - &kscan_ht16k33_api); - -DT_INST_FOREACH_STATUS_OKAY(KSCAN_HT16K33_DEVICE) diff --git a/drivers/led/Kconfig.ht16k33 b/drivers/led/Kconfig.ht16k33 index 6fd72d538376c6..1addae0436bf47 100644 --- a/drivers/led/Kconfig.ht16k33 +++ b/drivers/led/Kconfig.ht16k33 @@ -15,8 +15,7 @@ menuconfig HT16K33 config HT16K33_KEYSCAN bool "Keyscan support" - depends on (HT16K33 && KSCAN) - select KSCAN_HT16K33 + depends on (HT16K33 && INPUT) help Enable keyscan child device support in the HT16K33 LED driver. diff --git a/drivers/led/ht16k33.c b/drivers/led/ht16k33.c index 8df5b7553f6203..07a1ae56ca14ac 100644 --- a/drivers/led/ht16k33.c +++ b/drivers/led/ht16k33.c @@ -13,9 +13,9 @@ #include #include +#include #include #include -#include #include #include @@ -77,7 +77,6 @@ struct ht16k33_data { #ifdef CONFIG_HT16K33_KEYSCAN struct k_mutex lock; const struct device *child; - kscan_callback_t kscan_cb; struct gpio_callback irq_cb; struct k_thread irq_thread; struct k_sem irq_sem; @@ -230,15 +229,13 @@ static bool ht16k33_process_keyscan_data(const struct device *dev) pressed = true; } - if (data->kscan_cb == NULL) { - continue; - } - for (col = 0; col < HT16K33_KEYSCAN_COLS; col++) { - if (changed & BIT(col)) { - data->kscan_cb(data->child, row, col, - state & BIT(col)); + if ((changed & BIT(col)) == 0) { + continue; } + input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER); + input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER); + input_report_key(dev, INPUT_BTN_TOUCH, state & BIT(col), true, K_FOREVER); } } @@ -285,20 +282,6 @@ static void ht16k33_timer_callback(struct k_timer *timer) data = CONTAINER_OF(timer, struct ht16k33_data, timer); k_sem_give(&data->irq_sem); } - -int ht16k33_register_keyscan_callback(const struct device *parent, - const struct device *child, - kscan_callback_t callback) -{ - struct ht16k33_data *data = parent->data; - - k_mutex_lock(&data->lock, K_FOREVER); - data->child = child; - data->kscan_cb = callback; - k_mutex_unlock(&data->lock); - - return 0; -} #endif /* CONFIG_HT16K33_KEYSCAN */ static int ht16k33_init(const struct device *dev) diff --git a/dts/bindings/kscan/holtek,ht16k33-keyscan.yaml b/dts/bindings/kscan/holtek,ht16k33-keyscan.yaml deleted file mode 100644 index d39278fb66ea9d..00000000000000 --- a/dts/bindings/kscan/holtek,ht16k33-keyscan.yaml +++ /dev/null @@ -1,7 +0,0 @@ -description: Holtek HT16K33 keyscan - -compatible: "holtek,ht16k33-keyscan" - -include: base.yaml - -on-bus: ht16k33 diff --git a/include/zephyr/drivers/led/ht16k33.h b/include/zephyr/drivers/led/ht16k33.h deleted file mode 100644 index bc43b52a4bed84..00000000000000 --- a/include/zephyr/drivers/led/ht16k33.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019 Henrik Brix Andersen - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#ifndef ZEPHYR_INCLUDE_DRIVERS_LED_HT16K33_H_ -#define ZEPHYR_INCLUDE_DRIVERS_LED_HT16K33_H_ - -#include - -/** - * Register a HT16K33 keyscan device to be notified of relevant - * keyscan events by the keyscan interrupt thread in the HT16K33 - * parent driver. - * - * @param parent HT16K33 parent device. - * @param child HT16K33 child device. - * @param callback Keyscan callback function. - * @return 0 if successful, negative errno code on failure. - */ -int ht16k33_register_keyscan_callback(const struct device *parent, - const struct device *child, - kscan_callback_t callback); - -#endif /* ZEPHYR_INCLUDE_DRIVERS_LED_HT16K33_H_ */ diff --git a/samples/drivers/ht16k33/boards/nrf52840dk_nrf52840.overlay b/samples/drivers/ht16k33/boards/nrf52840dk_nrf52840.overlay index 8618745dcf5dca..c9f820cdb5835b 100644 --- a/samples/drivers/ht16k33/boards/nrf52840dk_nrf52840.overlay +++ b/samples/drivers/ht16k33/boards/nrf52840dk_nrf52840.overlay @@ -13,8 +13,8 @@ /* Uncomment to use IRQ instead of polling: */ /* irq-gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; */ - keyscan { - compatible = "holtek,ht16k33-keyscan"; + kscan-input { + compatible = "zephyr,kscan-input"; }; }; }; diff --git a/samples/drivers/ht16k33/prj.conf b/samples/drivers/ht16k33/prj.conf index 462075dc5f6ee2..fb580b93002461 100644 --- a/samples/drivers/ht16k33/prj.conf +++ b/samples/drivers/ht16k33/prj.conf @@ -2,5 +2,5 @@ CONFIG_LOG=y CONFIG_I2C=y CONFIG_LED=y CONFIG_KSCAN=y -CONFIG_KSCAN_INIT_PRIORITY=95 +CONFIG_INPUT=y CONFIG_HT16K33_KEYSCAN=y diff --git a/samples/drivers/ht16k33/src/main.c b/samples/drivers/ht16k33/src/main.c index 72ef587cb39e33..7ede8c6a0d358c 100644 --- a/samples/drivers/ht16k33/src/main.c +++ b/samples/drivers/ht16k33/src/main.c @@ -13,7 +13,7 @@ LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL); #define LED_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(holtek_ht16k33) -#define KEY_NODE DT_CHILD(LED_NODE, keyscan) +#define KEY_NODE DT_CHILD(LED_NODE, kscan_input) static void keyscan_callback(const struct device *dev, uint32_t row, uint32_t column, bool pressed) From 243f5987a93fe3e692e6a9deedb52e3375f94084 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0151/1389] doc: migration-guide: add a note about the ht16k33-keyscan driver Add a migration note about migrating the holtek,ht16k33-keyscan to the input subsystem. Signed-off-by: Fabio Baltieri --- doc/releases/migration-guide-3.7.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 23610b68ee02d1..7af637a557c02d 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -199,6 +199,10 @@ Input ``in-deadzone``) and when migrating to the new definition the value should be scaled accordingly. +* The ``holtek,ht16k33-keyscan`` driver has been converted to use the + :ref:`input` subsystem, callbacks have to be migrated to use the input APIs, + :dtcompatible:`zephyr,kscan-input` can be used for backward compatibility. + Interrupt Controller ==================== From d47ec6270f7aa0dced2871f17f608e98c4d46813 Mon Sep 17 00:00:00 2001 From: Ian Morris Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0152/1389] soc: renesas: ra: configure option settings memory An area of flash memory on the RA4M1 MCU is used to store information used to configure the device following a reset. This patch instructs the linker to reserve this memory area and provides kconfig options that are used to populate it (at build time) with the desired device configuration. Signed-off-by: Ian Morris --- soc/renesas/ra/ra4m1/CMakeLists.txt | 9 ++ soc/renesas/ra/ra4m1/Kconfig | 4 + soc/renesas/ra/ra4m1/opt_set_mem.ld | 11 +++ soc/renesas/ra/ra4m1/soc.c | 136 ++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 soc/renesas/ra/ra4m1/opt_set_mem.ld create mode 100644 soc/renesas/ra/ra4m1/soc.c diff --git a/soc/renesas/ra/ra4m1/CMakeLists.txt b/soc/renesas/ra/ra4m1/CMakeLists.txt index c0d9c7b1baa0be..00cdd96aa18764 100644 --- a/soc/renesas/ra/ra4m1/CMakeLists.txt +++ b/soc/renesas/ra/ra4m1/CMakeLists.txt @@ -3,4 +3,13 @@ zephyr_include_directories(.) +zephyr_library_sources_ifdef(CONFIG_SOC_OPTION_SETTING_MEMORY + soc.c +) + +zephyr_linker_sources_ifdef(CONFIG_SOC_OPTION_SETTING_MEMORY + ROM_START + ${CMAKE_CURRENT_SOURCE_DIR}/opt_set_mem.ld +) + set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/renesas/ra/ra4m1/Kconfig b/soc/renesas/ra/ra4m1/Kconfig index 56153d0732ff3a..c2f9efea3c79c4 100644 --- a/soc/renesas/ra/ra4m1/Kconfig +++ b/soc/renesas/ra/ra4m1/Kconfig @@ -9,3 +9,7 @@ config SOC_SERIES_RA4M1 select DYNAMIC_INTERRUPTS select TIMER_READS_ITS_FREQUENCY_AT_RUNTIME select XIP + +config SOC_OPTION_SETTING_MEMORY + bool "Option Setting Memory" + default y diff --git a/soc/renesas/ra/ra4m1/opt_set_mem.ld b/soc/renesas/ra/ra4m1/opt_set_mem.ld new file mode 100644 index 00000000000000..c05238789af716 --- /dev/null +++ b/soc/renesas/ra/ra4m1/opt_set_mem.ld @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +. = 0x400; +FILL(0xFF) +KEEP(*(.opt_set_mem*)) +. = 0x500; diff --git a/soc/renesas/ra/ra4m1/soc.c b/soc/renesas/ra/ra4m1/soc.c new file mode 100644 index 00000000000000..7f021ba17faead --- /dev/null +++ b/soc/renesas/ra/ra4m1/soc.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#define HOCO_FREQ DT_PROP(DT_PATH(clocks, hoco), clock_frequency) + +#if HOCO_FREQ == MHZ(24) +#define OFS1_HOCO_FREQ 0 +#elif HOCO_FREQ == MHZ(32) +#define OFS1_HOCO_FREQ 2 +#elif HOCO_FREQ == MHZ(48) +#define OFS1_HOCO_FREQ 4 +#elif HOCO_FREQ == MHZ(64) +#define OFS1_HOCO_FREQ 5 +#else +#error "Unsupported HOCO frequency" +#endif + +struct ofs0_reg { + uint32_t RSVD1: 1; + uint32_t IWDTSTRT: 1; + uint32_t IWDTTOPS: 2; + uint32_t IWDTCKS: 4; + uint32_t IWDTRPES: 2; + uint32_t IWDTRPSS: 2; + uint32_t IWDTRSTIRQS: 1; + uint32_t RSVD2: 1; + uint32_t IWDTSTPCTL: 1; + uint32_t RSVD3: 2; + uint32_t WDTSTRT: 1; + uint32_t WDTTOPS: 2; + uint32_t WDTCKS: 4; + uint32_t WDTRPES: 2; + uint32_t WDTRPSS: 2; + uint32_t WDTRSTIRQS: 1; + uint32_t RSVD4: 1; + uint32_t WDTSTPCTL: 1; + uint32_t RSVD5: 1; +}; + +struct ofs1_reg { + uint32_t RSVD1: 2; + uint32_t LVDAS: 1; + uint32_t VDSEL1: 3; + uint32_t RSVD2: 2; + uint32_t HOCOEN: 1; + uint32_t RSVD3: 3; + uint32_t HOCOFRQ1: 3; + uint32_t RSVD4: 17; +}; + +struct mpu_regs { + uint32_t SECMPUPCSO; + uint32_t SECMPUPCEO; + uint32_t SECMPUPCS1; + uint32_t SECMPUPCE1; + uint32_t SECMPUS0; + uint32_t SECMPUE0; + uint32_t SECMPUS1; + uint32_t SECMPUE1; + uint32_t SECMPUS2; + uint32_t SECMPUE2; + uint32_t SECMPUS3; + uint32_t SECMPUE3; + uint32_t SECMPUAC; +}; + +struct opt_set_mem { + struct ofs0_reg ofs0; + struct ofs1_reg ofs1; + struct mpu_regs mpu; +}; + +#ifdef CONFIG_SOC_OPTION_SETTING_MEMORY +const struct opt_set_mem ops __attribute__((section(".opt_set_mem"))) = { + .ofs0 = { + /* + * Initial settings for watchdog timers. Set all fields to 1, + * disabling watchdog functionality as config options have not + * yet been implemented. + */ + .RSVD1 = 0x1, + .IWDTSTRT = 0x1, /* Disable independent watchdog timer */ + .IWDTTOPS = 0x3, + .IWDTCKS = 0xf, + .IWDTRPES = 0x3, + .IWDTRPSS = 0x3, + .IWDTRSTIRQS = 0x1, + .RSVD2 = 0x1, + .IWDTSTPCTL = 0x1, + .RSVD3 = 0x3, + .WDTSTRT = 0x1, /* Stop watchdog timer following reset */ + .WDTTOPS = 0x3, + .WDTCKS = 0xf, + .WDTRPES = 0x3, + .WDTRPSS = 0x3, + .WDTRSTIRQS = 0x1, + .RSVD4 = 0x1, + .WDTSTPCTL = 0x1, + .RSVD5 = 0x1, + }, + .ofs1 = { + .RSVD1 = 0x3, + .LVDAS = 0x1, /* Disable voltage monitor 0 following reset */ + .VDSEL1 = 0x3, + .RSVD2 = 0x3, + .HOCOEN = !DT_NODE_HAS_STATUS(DT_PATH(clocks, hoco), okay), + .RSVD3 = 0x7, + .HOCOFRQ1 = OFS1_HOCO_FREQ, + .RSVD4 = 0x1ffff, + }, + .mpu = { + /* + * Initial settings for MPU. Set all areas to maximum values + * essentially disabling MPU functionality as config options + * have not yet been implemented. + */ + .SECMPUPCSO = 0x00fffffc, + .SECMPUPCEO = 0x00ffffff, + .SECMPUPCS1 = 0x00fffffc, + .SECMPUPCE1 = 0x00ffffff, + .SECMPUS0 = 0x00fffffc, + .SECMPUE0 = 0x00ffffff, + .SECMPUS1 = 0x200ffffc, + .SECMPUE1 = 0x200fffff, + .SECMPUS2 = 0x407ffffc, + .SECMPUE2 = 0x407fffff, + .SECMPUS3 = 0x40dffffc, + .SECMPUE3 = 0x40dfffff, + .SECMPUAC = 0xffffffff, + } +}; +#endif From d012c0906a389d16f0b6d90f004dad58988356e9 Mon Sep 17 00:00:00 2001 From: Markus Lassila Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0153/1389] net: l2: ppp: Fix terminate requests When PPP moves to the 'Closing' state it sends up to configured number of 'Terminate-Request' packets. It only moves to the 'Initial' state, after running out of retransmits or when it receives a 'Terminate-Ack' packet. Signed-off-by: Markus Lassila --- subsys/net/l2/ppp/ppp_l2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/net/l2/ppp/ppp_l2.c b/subsys/net/l2/ppp/ppp_l2.c index efbd7b81008f8e..bfe28738f7945f 100644 --- a/subsys/net/l2/ppp/ppp_l2.c +++ b/subsys/net/l2/ppp/ppp_l2.c @@ -231,7 +231,9 @@ static int ppp_lcp_close(struct ppp_context *ctx) k_sem_reset(&ctx->wait_ppp_link_terminated); ppp_lcp->close(ctx, "L2 Disabled"); - return k_sem_take(&ctx->wait_ppp_link_terminated, K_MSEC(CONFIG_NET_L2_PPP_TIMEOUT)); + return k_sem_take(&ctx->wait_ppp_link_terminated, + K_MSEC(CONFIG_NET_L2_PPP_TIMEOUT * + (1 + CONFIG_NET_L2_PPP_MAX_TERMINATE_REQ_RETRANSMITS))); } static void ppp_lcp_lower_down_async(struct ppp_context *ctx) From ca63853b91ca530c25d692b307183fd566f841fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0154/1389] usb: device: Do not claim to be USB 3.2 device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bcdUSB value 0x0210 defined in USB 3.2 Specification indicates USB 3.2 device operating in one of the USB 2.0 modes. USB 2.0 Link Power Management Addendum defines bcdUSB value 0x0201 to indicate that USB 2.0 device supports the request to read the BOS Descriptor. The main difference between bcdUSB 0x0210 and 0x0201 is that the USB 3.2 device must support LPM, while USB 2.0 devices can (but are not required to) support LPM. The difference is respected by USB 3 Gen X Command Verifier (2.3.0.0) Chapter 9 Tests [USB 2 devices], where the test behaves as follows: * For bcdUSB 0x0200: Checking Device Under Test for LPM L1 Compatibility... USB version of device is 2.00. DUT is NOT compatible with LPM. LPM is NOT required for DUT LPM is only supported in USB version 2.01 and above. * For bcdUSB 0x0201: Checking Device Under Test for LPM L1 Compatibility... USB version of device is 2.01. DUT IS compatible with LPM. LPM is NOT required for DUT USB 2.0 Extension Descriptor bmAttributes: LPM Capable = 0 BESL and Alternate HIRD Supported = 0 Baseline BESL Valid = 0 Deep BESL Valid = 0 Baseline BESL: 0d Deep BESL: 0d LPM is not supported * For bcdUSB 0x0210: Checking Device Under Test for LPM L1 Compatibility... USB version of device is 2.10. DUT IS compatible with LPM. LPM IS required for DUT USB 2.0 Extension Descriptor bmAttributes: LPM Capable = 0 BESL and Alternate HIRD Supported = 0 Baseline BESL Valid = 0 Deep BESL Valid = 0 Baseline BESL: 0d Deep BESL: 0d (USB: 9.6.2.1.6) Bit 1 in Attributes field of a USB 2.0 Extension descriptor returned in response to a GetDescriptor(BOS) request must be 1 for LS/FS/HS devices that support LPM L1. The test fails when LPM bit is not set in USB 2.0 Extension Descriptor only when bcdUSB is 0x0210. The test failure was incorrectly fixed in commit 312429be3c0c ("usb: samples: Add Extension descriptor to webUSB sample."). Properly fix the issue by changing bcdUSB to 0x0201 and removing the false LPM support claim. The false LPM claim was leading to device ceasing to work after some time if there was no traffic from host to device (when the host is likely to have executed the LPM L1 transition that was not properly handled by the device). Signed-off-by: Tomasz Moń --- include/zephyr/usb/usb_ch9.h | 1 + samples/subsys/usb/webusb/src/main.c | 5 ++++- subsys/usb/device/usb_descriptor.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/zephyr/usb/usb_ch9.h b/include/zephyr/usb/usb_ch9.h index 9eec123f06a654..8fe33f46b7171c 100644 --- a/include/zephyr/usb/usb_ch9.h +++ b/include/zephyr/usb/usb_ch9.h @@ -268,6 +268,7 @@ struct usb_association_descriptor { /** USB Specification Release Numbers (bcdUSB Descriptor field) */ #define USB_SRN_1_1 0x0110 #define USB_SRN_2_0 0x0200 +#define USB_SRN_2_0_1 0x0201 #define USB_SRN_2_1 0x0210 #define USB_DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10)) diff --git a/samples/subsys/usb/webusb/src/main.c b/samples/subsys/usb/webusb/src/main.c index 69317465877ae6..77866932e02d75 100644 --- a/samples/subsys/usb/webusb/src/main.c +++ b/samples/subsys/usb/webusb/src/main.c @@ -164,10 +164,13 @@ USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_capability_lpm bos_cap_lpm = { .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, /** + * Currently there is not a single device driver in Zephyr that supports + * LPM. Moreover, Zephyr USB stack does not have LPM support, so do not + * falsely claim to support LPM. * BIT(1) - LPM support * BIT(2) - BESL support */ - .bmAttributes = BIT(1) | BIT(2), + .bmAttributes = 0, }; /* WebUSB Device Requests */ diff --git a/subsys/usb/device/usb_descriptor.c b/subsys/usb/device/usb_descriptor.c index 7c2ac37d94a594..5f75fe97c4f92b 100644 --- a/subsys/usb/device/usb_descriptor.c +++ b/subsys/usb/device/usb_descriptor.c @@ -56,7 +56,7 @@ USBD_DEVICE_DESCR_DEFINE(primary) struct common_descriptor common_desc = { .bLength = sizeof(struct usb_device_descriptor), .bDescriptorType = USB_DESC_DEVICE, #ifdef CONFIG_USB_DEVICE_BOS - .bcdUSB = sys_cpu_to_le16(USB_SRN_2_1), + .bcdUSB = sys_cpu_to_le16(USB_SRN_2_0_1), #else .bcdUSB = sys_cpu_to_le16(USB_SRN_2_0), #endif From 6557300b18addcbbb1aedf88f87ec2c4401cc9db Mon Sep 17 00:00:00 2001 From: Charles Dias Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0155/1389] dts: arm: st: h7: add DCMI node into DTSI file Add the DCMI node into stm32h7.dtsi. Signed-off-by: Charles Dias --- dts/arm/st/h7/stm32h7.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 95c5590a8716d2..d03b8fc5ab41dd 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -1048,6 +1048,15 @@ clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00004000>; status = "disabled"; }; + + dcmi: dcmi@48020000 { + compatible = "st,stm32-dcmi"; + reg = <0x48020000 0x400>; + interrupts = <78 0>; + interrupt-names = "dcmi"; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000001>; + status = "disabled"; + }; }; die_temp: dietemp { From c0d87dc4721774f25a1b13986a0a6001c3aa4155 Mon Sep 17 00:00:00 2001 From: Charles Dias Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0156/1389] drivers: video: Add support for STM32 DCMI Add Kconfig, DCMI driver, Yaml, and CMakeLists files Signed-off-by: Charles Dias --- drivers/video/CMakeLists.txt | 1 + drivers/video/Kconfig | 2 + drivers/video/Kconfig.stm32_dcmi | 22 ++ drivers/video/video_stm32_dcmi.c | 504 ++++++++++++++++++++++++++ dts/bindings/video/st,stm32-dcmi.yaml | 123 +++++++ 5 files changed, 652 insertions(+) create mode 100644 drivers/video/Kconfig.stm32_dcmi create mode 100644 drivers/video/video_stm32_dcmi.c create mode 100644 dts/bindings/video/st,stm32-dcmi.yaml diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 68fd96d1b4cf83..0b279de38134fe 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_VIDEO_SW_GENERATOR video_sw_generator.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_MT9M114 mt9m114.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7725 ov7725.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV2640 ov2640.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_STM32_DCMI video_stm32_dcmi.c) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 488ad6c80ccd4e..8a489cc4be6bd2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -41,4 +41,6 @@ source "drivers/video/Kconfig.ov7725" source "drivers/video/Kconfig.ov2640" +source "drivers/video/Kconfig.stm32_dcmi" + endif # VIDEO diff --git a/drivers/video/Kconfig.stm32_dcmi b/drivers/video/Kconfig.stm32_dcmi new file mode 100644 index 00000000000000..8f0c11a42c74c5 --- /dev/null +++ b/drivers/video/Kconfig.stm32_dcmi @@ -0,0 +1,22 @@ +# STM32 DCMI driver configuration options + +# Copyright (c) 2024 Charles Dias +# SPDX-License-Identifier: Apache-2.0 + +DT_STM32_DCMI_HAS_DMA := $(dt_nodelabel_has_prop,dcmi,dmas) + +config VIDEO_STM32_DCMI + bool "STM32 Digital camera interface (DCMI) driver" + default y + depends on DT_HAS_ST_STM32_DCMI_ENABLED + select USE_STM32_HAL_DCMI + select USE_STM32_HAL_MDMA if SOC_SERIES_STM32H7X + select DMA if $(DT_STM32_DCMI_HAS_DMA) + select USE_STM32_HAL_DMA if $(DT_STM32_DCMI_HAS_DMA) + select USE_STM32_HAL_DMA_EX if $(DT_STM32_DCMI_HAS_DMA) + help + Enable driver for STM32 Digital camera interface periheral. + +module = STM32_DCMI +module-str = stm32_dcmi +source "subsys/logging/Kconfig.template.log_config" diff --git a/drivers/video/video_stm32_dcmi.c b/drivers/video/video_stm32_dcmi.c new file mode 100644 index 00000000000000..d8f875b76731b5 --- /dev/null +++ b/drivers/video/video_stm32_dcmi.c @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2024 Charles Dias + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT st_stm32_dcmi + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +LOG_MODULE_REGISTER(video_stm32_dcmi, CONFIG_STM32_DCMI_LOG_LEVEL); + +K_HEAP_DEFINE(video_stm32_buffer_pool, CONFIG_VIDEO_BUFFER_POOL_SZ_MAX); + +typedef void (*irq_config_func_t)(const struct device *dev); + +struct stream { + DMA_TypeDef *reg; + const struct device *dma_dev; + uint32_t channel; + struct dma_config cfg; +}; + +struct video_stm32_dcmi_data { + const struct device *dev; + DCMI_HandleTypeDef hdcmi; + struct video_format fmt; + struct k_fifo fifo_in; + struct k_fifo fifo_out; + uint32_t pixel_format; + uint32_t height; + uint32_t width; + uint32_t pitch; + uint8_t *buffer; +}; + +struct video_stm32_dcmi_config { + struct stm32_pclken pclken; + irq_config_func_t irq_config; + const struct pinctrl_dev_config *pctrl; + const struct device *sensor_dev; + const struct stream dma; +}; + +static inline unsigned int video_pix_fmt_bpp(uint32_t pixelformat) +{ + switch (pixelformat) { + case VIDEO_PIX_FMT_BGGR8: + case VIDEO_PIX_FMT_GBRG8: + case VIDEO_PIX_FMT_GRBG8: + case VIDEO_PIX_FMT_RGGB8: + return 1; + case VIDEO_PIX_FMT_RGB565: + case VIDEO_PIX_FMT_YUYV: + return 2; + default: + return 0; + } +} + +void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi) +{ + LOG_WRN("%s", __func__); +} + +void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) +{ + struct video_stm32_dcmi_data *dev_data = + CONTAINER_OF(hdcmi, struct video_stm32_dcmi_data, hdcmi); + struct video_buffer *vbuf; + + HAL_DCMI_Suspend(hdcmi); + + vbuf = k_fifo_get(&dev_data->fifo_in, K_NO_WAIT); + + if (vbuf == NULL) { + LOG_DBG("Failed to get buffer from fifo"); + goto resume; + } + + vbuf->timestamp = k_uptime_get_32(); + memcpy(vbuf->buffer, dev_data->buffer, vbuf->bytesused); + + k_fifo_put(&dev_data->fifo_out, vbuf); + +resume: + HAL_DCMI_Resume(hdcmi); +} + +static void stm32_dcmi_isr(const struct device *dev) +{ + struct video_stm32_dcmi_data *data = dev->data; + + HAL_DCMI_IRQHandler(&data->hdcmi); +} + +static void dmci_dma_callback(const struct device *dev, void *arg, + uint32_t channel, int status) +{ + DMA_HandleTypeDef *hdma = arg; + + ARG_UNUSED(dev); + + if (status < 0) { + LOG_ERR("DMA callback error with channel %d.", channel); + } + + HAL_DMA_IRQHandler(hdma); +} + +void HAL_DMA_ErrorCallback(DMA_HandleTypeDef *hdma) +{ + LOG_WRN("%s", __func__); +} + +static int stm32_dma_init(const struct device *dev) +{ + struct video_stm32_dcmi_data *data = dev->data; + const struct video_stm32_dcmi_config *config = dev->config; + int ret; + + /* Check if the DMA device is ready */ + if (!device_is_ready(config->dma.dma_dev)) { + LOG_ERR("%s DMA device not ready", config->dma.dma_dev->name); + return -ENODEV; + } + + /* + * DMA configuration + * Due to use of QSPI HAL API in current driver, + * both HAL and Zephyr DMA drivers should be configured. + * The required configuration for Zephyr DMA driver should only provide + * the minimum information to inform the DMA slot will be in used and + * how to route callbacks. + */ + struct dma_config dma_cfg = config->dma.cfg; + static DMA_HandleTypeDef hdma; + + /* Proceed to the minimum Zephyr DMA driver init */ + dma_cfg.user_data = &hdma; + /* HACK: This field is used to inform driver that it is overridden */ + dma_cfg.linked_channel = STM32_DMA_HAL_OVERRIDE; + /* Because of the STREAM OFFSET, the DMA channel given here is from 1 - 8 */ + ret = dma_config(config->dma.dma_dev, + config->dma.channel + STM32_DMA_STREAM_OFFSET, &dma_cfg); + if (ret != 0) { + LOG_ERR("Failed to configure DMA channel %d", + config->dma.channel + STM32_DMA_STREAM_OFFSET); + return ret; + } + + /*** Configure the DMA ***/ + /* Set the parameters to be configured */ + hdma.Init.Request = DMA_REQUEST_DCMI; + hdma.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma.Init.PeriphInc = DMA_PINC_DISABLE; + hdma.Init.MemInc = DMA_MINC_ENABLE; + hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma.Init.Mode = DMA_CIRCULAR; + hdma.Init.Priority = DMA_PRIORITY_HIGH; + hdma.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + + hdma.Instance = __LL_DMA_GET_STREAM_INSTANCE(config->dma.reg, + config->dma.channel); + + /* Initialize DMA HAL */ + __HAL_LINKDMA(&data->hdcmi, DMA_Handle, hdma); + + if (HAL_DMA_Init(&hdma) != HAL_OK) { + LOG_ERR("DCMI DMA Init failed"); + return -EIO; + } + + return 0; +} + +static int stm32_dcmi_enable_clock(const struct device *dev) +{ + const struct video_stm32_dcmi_config *config = dev->config; + const struct device *dcmi_clock = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + int err; + + if (!device_is_ready(dcmi_clock)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + /* Turn on DCMI peripheral clock */ + err = clock_control_on(dcmi_clock, (clock_control_subsys_t *) &config->pclken); + if (err < 0) { + LOG_ERR("Failed to enable DCMI clock. Error %d", err); + return err; + } + + return 0; +} + +static int video_stm32_dcmi_set_fmt(const struct device *dev, + enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct video_stm32_dcmi_config *config = dev->config; + struct video_stm32_dcmi_data *data = dev->data; + unsigned int bpp = video_pix_fmt_bpp(fmt->pixelformat); + + if (!bpp || ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + data->pixel_format = fmt->pixelformat; + data->pitch = fmt->pitch; + data->height = fmt->height; + data->width = fmt->width; + + if (video_set_format(config->sensor_dev, ep, fmt)) { + return -EIO; + } + + return 0; +} + +static int video_stm32_dcmi_get_fmt(const struct device *dev, + enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct video_stm32_dcmi_data *data = dev->data; + const struct video_stm32_dcmi_config *config = dev->config; + + if ((fmt == NULL) || (ep != VIDEO_EP_OUT)) { + return -EINVAL; + } + + if (!video_get_format(config->sensor_dev, ep, fmt)) { + /* align DCMI with sensor fmt */ + return video_stm32_dcmi_set_fmt(dev, ep, fmt); + } + + fmt->pixelformat = data->pixel_format; + fmt->height = data->height; + fmt->width = data->width; + fmt->pitch = data->pitch; + + return 0; +} + +static int video_stm32_dcmi_stream_start(const struct device *dev) +{ + struct video_stm32_dcmi_data *data = dev->data; + const struct video_stm32_dcmi_config *config = dev->config; + size_t buffer_size = data->pitch * data->height; + + data->buffer = k_heap_alloc(&video_stm32_buffer_pool, buffer_size, K_NO_WAIT); + if (data->buffer == NULL) { + LOG_ERR("Failed to allocate DCMI buffer for image. Size %d bytes", buffer_size); + return -ENOMEM; + } + + int err = HAL_DCMI_Start_DMA(&data->hdcmi, DCMI_MODE_CONTINUOUS, + (uint32_t)data->buffer, buffer_size / 4); + if (err != HAL_OK) { + LOG_ERR("Failed to start DCMI DMA"); + return -EIO; + } + + if (video_stream_start(config->sensor_dev)) { + return -EIO; + } + + return 0; +} + +static int video_stm32_dcmi_stream_stop(const struct device *dev) +{ + struct video_stm32_dcmi_data *data = dev->data; + const struct video_stm32_dcmi_config *config = dev->config; + int err; + + if (video_stream_stop(config->sensor_dev)) { + return -EIO; + } + + /* Release the buffer allocated in stream_start */ + k_heap_free(&video_stm32_buffer_pool, data->buffer); + + err = HAL_DCMI_Stop(&data->hdcmi); + if (err != HAL_OK) { + LOG_ERR("Failed to stop DCMI"); + return -EIO; + } + + return 0; +} + +static int video_stm32_dcmi_enqueue(const struct device *dev, + enum video_endpoint_id ep, + struct video_buffer *vbuf) +{ + struct video_stm32_dcmi_data *data = dev->data; + + if (ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + vbuf->bytesused = data->pitch * data->height; + + k_fifo_put(&data->fifo_in, vbuf); + + return 0; +} + +static int video_stm32_dcmi_dequeue(const struct device *dev, + enum video_endpoint_id ep, + struct video_buffer **vbuf, + k_timeout_t timeout) +{ + struct video_stm32_dcmi_data *data = dev->data; + + if (ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + *vbuf = k_fifo_get(&data->fifo_out, timeout); + if (*vbuf == NULL) { + return -EAGAIN; + } + + return 0; +} + +static int video_stm32_dcmi_get_caps(const struct device *dev, + enum video_endpoint_id ep, + struct video_caps *caps) +{ + const struct video_stm32_dcmi_config *config = dev->config; + int ret = -ENODEV; + + if (ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + /* Forward the message to the sensor device */ + ret = video_get_caps(config->sensor_dev, ep, caps); + + return ret; +} + +static const struct video_driver_api video_stm32_dcmi_driver_api = { + .set_format = video_stm32_dcmi_set_fmt, + .get_format = video_stm32_dcmi_get_fmt, + .stream_start = video_stm32_dcmi_stream_start, + .stream_stop = video_stm32_dcmi_stream_stop, + .enqueue = video_stm32_dcmi_enqueue, + .dequeue = video_stm32_dcmi_dequeue, + .get_caps = video_stm32_dcmi_get_caps, +}; + +static void video_stm32_dcmi_irq_config_func(const struct device *dev) +{ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), + stm32_dcmi_isr, DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +} + +#define DCMI_DMA_CHANNEL_INIT(index, src_dev, dest_dev) \ + .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_IDX(index, 0)), \ + .channel = DT_INST_DMAS_CELL_BY_IDX(index, 0, channel), \ + .reg = (DMA_TypeDef *)DT_REG_ADDR( \ + DT_PHANDLE_BY_IDX(DT_DRV_INST(0), dmas, 0)), \ + .cfg = { \ + .dma_slot = STM32_DMA_SLOT_BY_IDX(index, 0, slot), \ + .channel_direction = STM32_DMA_CONFIG_DIRECTION( \ + STM32_DMA_CHANNEL_CONFIG_BY_IDX(index, 0)), \ + .source_data_size = STM32_DMA_CONFIG_##src_dev##_DATA_SIZE( \ + STM32_DMA_CHANNEL_CONFIG_BY_IDX(index, 0)), \ + .dest_data_size = STM32_DMA_CONFIG_##dest_dev##_DATA_SIZE( \ + STM32_DMA_CHANNEL_CONFIG_BY_IDX(index, 0)), \ + .source_burst_length = 1, /* SINGLE transfer */ \ + .dest_burst_length = 1, /* SINGLE transfer */ \ + .channel_priority = STM32_DMA_CONFIG_PRIORITY( \ + STM32_DMA_CHANNEL_CONFIG_BY_IDX(index, 0)), \ + .dma_callback = dmci_dma_callback, \ + }, \ + +PINCTRL_DT_INST_DEFINE(0); + +#define STM32_DCMI_GET_CAPTURE_RATE(capture_rate) \ + ((capture_rate) == 1 ? DCMI_CR_ALL_FRAME : \ + (capture_rate) == 2 ? DCMI_CR_ALTERNATE_2_FRAME : \ + (capture_rate) == 4 ? DCMI_CR_ALTERNATE_4_FRAME : \ + DCMI_CR_ALL_FRAME) + +#define STM32_DCMI_GET_BUS_WIDTH(bus_width) \ + ((bus_width) == 8 ? DCMI_EXTEND_DATA_8B : \ + (bus_width) == 10 ? DCMI_EXTEND_DATA_10B : \ + (bus_width) == 12 ? DCMI_EXTEND_DATA_12B : \ + (bus_width) == 14 ? DCMI_EXTEND_DATA_14B : \ + DCMI_EXTEND_DATA_8B) + +#define DCMI_DMA_CHANNEL(id, src, dest) \ + .dma = { \ + COND_CODE_1(DT_INST_DMAS_HAS_IDX(id, 0), \ + (DCMI_DMA_CHANNEL_INIT(id, src, dest)), \ + (NULL)) \ + }, + +static struct video_stm32_dcmi_data video_stm32_dcmi_data_0 = { + .hdcmi = { + .Instance = (DCMI_TypeDef *) DT_INST_REG_ADDR(0), + .Init = { + .SynchroMode = DCMI_SYNCHRO_HARDWARE, + .PCKPolarity = (DT_INST_PROP(0, pixelclk_active) ? + DCMI_PCKPOLARITY_RISING : DCMI_PCKPOLARITY_FALLING), + .HSPolarity = (DT_INST_PROP(0, hsync_active) ? + DCMI_HSPOLARITY_HIGH : DCMI_HSPOLARITY_LOW), + .VSPolarity = (DT_INST_PROP(0, vsync_active) ? + DCMI_VSPOLARITY_HIGH : DCMI_VSPOLARITY_LOW), + .CaptureRate = STM32_DCMI_GET_CAPTURE_RATE( + DT_INST_PROP(0, capture_rate)), + .ExtendedDataMode = STM32_DCMI_GET_BUS_WIDTH( + DT_INST_PROP(0, bus_width)), + .JPEGMode = DCMI_JPEG_DISABLE, + .ByteSelectMode = DCMI_BSM_ALL, + .ByteSelectStart = DCMI_OEBS_ODD, + .LineSelectMode = DCMI_LSM_ALL, + .LineSelectStart = DCMI_OELS_ODD, + }, + }, +}; + +static const struct video_stm32_dcmi_config video_stm32_dcmi_config_0 = { + .pclken = { + .enr = DT_INST_CLOCKS_CELL(0, bits), + .bus = DT_INST_CLOCKS_CELL(0, bus) + }, + .irq_config = video_stm32_dcmi_irq_config_func, + .pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .sensor_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, sensor)), + DCMI_DMA_CHANNEL(0, PERIPHERAL, MEMORY) +}; + +static int video_stm32_dcmi_init(const struct device *dev) +{ + const struct video_stm32_dcmi_config *config = dev->config; + struct video_stm32_dcmi_data *data = dev->data; + int err; + + /* Configure DT provided pins */ + err = pinctrl_apply_state(config->pctrl, PINCTRL_STATE_DEFAULT); + if (err < 0) { + LOG_ERR("pinctrl setup failed. Error %d.", err); + return err; + } + + /* Initialize DMA peripheral */ + err = stm32_dma_init(dev); + if (err < 0) { + LOG_ERR("DMA initialization failed."); + return err; + } + + /* Enable DCMI clock */ + err = stm32_dcmi_enable_clock(dev); + if (err < 0) { + LOG_ERR("Clock enabling failed."); + return -EIO; + } + + data->dev = dev; + k_fifo_init(&data->fifo_in); + k_fifo_init(&data->fifo_out); + + /* Run IRQ init */ + config->irq_config(dev); + + /* Initialize DCMI peripheral */ + err = HAL_DCMI_Init(&data->hdcmi); + if (err != HAL_OK) { + LOG_ERR("DCMI initialization failed."); + return -EIO; + } + + k_sleep(K_MSEC(100)); + LOG_DBG("%s inited", dev->name); + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, &video_stm32_dcmi_init, + NULL, &video_stm32_dcmi_data_0, + &video_stm32_dcmi_config_0, + POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, + &video_stm32_dcmi_driver_api); diff --git a/dts/bindings/video/st,stm32-dcmi.yaml b/dts/bindings/video/st,stm32-dcmi.yaml new file mode 100644 index 00000000000000..8381ae0acaf251 --- /dev/null +++ b/dts/bindings/video/st,stm32-dcmi.yaml @@ -0,0 +1,123 @@ +# +# Copyright (c) 2024 Charles Dias +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + STMicroelectronics STM32 Digital Camera Memory Interface (DCMI). + Example of node configuration at board level: + + &dcmi { + status = "okay"; + sensor = <&ov2640>; + pinctrl-0 = <&dcmi_hsync_pa4 &dcmi_pixclk_pa6 &dcmi_vsync_pb7 + &dcmi_d0_pc6 &dcmi_d1_pc7 &dcmi_d2_pe0 &dcmi_d3_pe1 + &dcmi_d4_pe4 &dcmi_d5_pd3 &dcmi_d6_pe5 &dcmi_d7_pe6>; + pinctrl-names = "default"; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + pixelclk-active = <1>; + capture-rate = <1>; + dmas = <&dma1 0 75 (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_PERIPH_NO_INC | + STM32_DMA_MEM_INC | STM32_DMA_PERIPH_8BITS | STM32_DMA_MEM_32BITS | + STM32_DMA_PRIORITY_HIGH) STM32_DMA_FIFO_1_4>; + + port { + dcmi_ep_in: endpoint { + remote-endpoint = <&ov2640_ep_out>; + }; + }; + }; + +compatible: "st,stm32-dcmi" + +include: [base.yaml, pinctrl-device.yaml] + +properties: + interrupts: + required: true + + sensor: + required: true + type: phandle + description: phandle of connected sensor device + + bus-width: + type: int + required: true + enum: + - 8 + - 10 + - 12 + - 14 + default: 8 + description: | + Number of data lines actively used, valid for the parallel busses. + + hsync-active: + type: int + required: true + enum: + - 0 + - 1 + description: | + Polarity of horizontal synchronization (DCMI_HSYNC_Polarity). + 0 Horizontal synchronization active Low. + 1 Horizontal synchronization active High. + + For example, if DCMI_HSYNC_Polarity is programmed active high: + When HSYNC is low, the data is valid. + When HSYNC is high, the data is not valid (horizontal blanking). + + vsync-active: + type: int + required: true + enum: + - 0 + - 1 + description: | + Polarity of vertical synchronization (DCMI_VSYNC_Polarity). + 0 Vertical synchronization active Low. + 1 Vertical synchronization active High. + + For example, if DCMI_VSYNC_Polarity is programmed active high: + When VSYNC is low, the data is valid. + When VSYNC is high, the data is not valid (vertical blanking). + + pixelclk-active: + type: int + required: true + enum: + - 0 + - 1 + description: | + Polarity of pixel clock (DCMI_PIXCK_Polarity). + 0 Pixel clock active on Falling edge. + 1 Pixel clock active on Rising edge. + + capture-rate: + type: int + enum: + - 1 + - 2 + - 4 + default: 1 + description: | + The DCMI can capture all frames or alternate frames. If it is not specified, + the default is all frames. + 1 Capture all frames. + 2 Capture alternate frames. + 4 Capture one frame every 4 frames. + + dmas: + required: true + description: | + phandle of DMA controller. The DMA controller should be compatible with + DMA channel specifier. Specifies a phandle reference to the dma controller, + the channel number, the slot number, channel configuration and finally features. + + dmas = <&dma1 0 75 (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_PERIPH_NO_INC | + STM32_DMA_MEM_INC | STM32_DMA_PERIPH_8BITS | STM32_DMA_MEM_32BITS | + STM32_DMA_PRIORITY_HIGH) STM32_DMA_FIFO_1_4>; From b5be9c959d70a2bb754309182ebc3b4808692f28 Mon Sep 17 00:00:00 2001 From: Juliane Schulze Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0157/1389] drivers: allow lis2dh anymotion triggers if no anymotion latching is active Since the interrupt state of the IA bit (interrupt source register) is checked, it needs to be read out everytime, not only on latching. Fixes #71245 Signed-off-by: Juliane Schulze --- drivers/sensor/st/lis2dh/lis2dh_trigger.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/sensor/st/lis2dh/lis2dh_trigger.c b/drivers/sensor/st/lis2dh/lis2dh_trigger.c index 3c075b2a0e881d..6afa8af839b1f3 100644 --- a/drivers/sensor/st/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/st/lis2dh/lis2dh_trigger.c @@ -467,17 +467,15 @@ static void lis2dh_thread_cb(const struct device *dev) TRIGGED_INT2)) { uint8_t reg_val = 0; - if (cfg->hw.anym_latch) { - /* clear interrupt to de-assert int line */ - status = lis2dh->hw_tf->read_reg(dev, - cfg->hw.anym_on_int1 ? - LIS2DH_REG_INT1_SRC : - LIS2DH_REG_INT2_SRC, - ®_val); - if (status < 0) { - LOG_ERR("clearing interrupt 2 failed: %d", status); - return; - } + /* if necessary also clears an interrupt to de-assert int line */ + status = lis2dh->hw_tf->read_reg(dev, + cfg->hw.anym_on_int1 ? + LIS2DH_REG_INT1_SRC : + LIS2DH_REG_INT2_SRC, + ®_val); + if (status < 0) { + LOG_ERR("clearing interrupt 2 failed: %d", status); + return; } if (likely(lis2dh->handler_anymotion != NULL) && From 7fd572781cd54f48efc682e58137b3b31b99ac91 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0158/1389] hostap: Convert channel to frequency conversion to a loop This makes it readable and also scalable for upcoming extension of operating classes. Signed-off-by: Chaitanya Tata Signed-off-by: Jukka Rissanen --- modules/hostap/src/supp_api.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index 305c27f3546a46..4b51c7012ec353 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -269,11 +269,15 @@ static inline int chan_to_freq(int chan) * op_class for 5GHz channels as there is no user input * for these (yet). */ - int freq; + int freq = -1; + int op_classes[] = {81, 128}; + int op_classes_size = ARRAY_SIZE(op_classes); - freq = ieee80211_chan_to_freq(NULL, 81, chan); - if (freq <= 0) { - freq = ieee80211_chan_to_freq(NULL, 128, chan); + for (int i = 0; i < op_classes_size; i++) { + freq = ieee80211_chan_to_freq(NULL, op_classes[i], chan); + if (freq > 0) { + break; + } } if (freq <= 0) { From 5dc48e1dcccb01b2d4557811074b7405eeae4aa0 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0159/1389] hostap: Fix handling channel 14 Channel 14 in JP is still allowed (though OFDM is disabled), this wasn't handled by operating class 81, so, add 82 to the list. We still need to full implement regulatory support in the WPA supplicant but that is handled in separate fix. Signed-off-by: Chaitanya Tata Signed-off-by: Jukka Rissanen --- modules/hostap/src/supp_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index 4b51c7012ec353..e7bae126c4b32d 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -270,7 +270,7 @@ static inline int chan_to_freq(int chan) * for these (yet). */ int freq = -1; - int op_classes[] = {81, 128}; + int op_classes[] = {81, 82, 128}; int op_classes_size = ARRAY_SIZE(op_classes); for (int i = 0; i < op_classes_size; i++) { From 807dc23ad197dfac0359f63f2055d94ce8585c80 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0160/1389] hostap: Increase the stack size for net_mgmt Due to recent changes in hostap to move few buffers from heap->stack (to improve the reliability of allocations) this has increased the stack size and with another recent change to increase the max polling sockets this puts over the 4096 stack size for net_mgmt causing stack overflow. Signed-off-by: Chaitanya Tata Signed-off-by: Jukka Rissanen --- subsys/net/ip/Kconfig.mgmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/ip/Kconfig.mgmt b/subsys/net/ip/Kconfig.mgmt index e5adb9e5728aa3..04fe2adf14e891 100644 --- a/subsys/net/ip/Kconfig.mgmt +++ b/subsys/net/ip/Kconfig.mgmt @@ -57,7 +57,7 @@ config NET_MGMT_EVENT_QUEUE config NET_MGMT_EVENT_STACK_SIZE int "Stack size for the inner thread handling event callbacks" - default 4096 if WIFI_NM_WPA_SUPPLICANT + default 4200 if WIFI_NM_WPA_SUPPLICANT default 2048 if COVERAGE_GCOV default 840 if X86 default 800 if THREAD_LOCAL_STORAGE From 704af0abb494bbbaa6ecced25d781b9a81554159 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0161/1389] hostap: Support BSSID configuration for connect command Support BSSID configuration while setting up the network information as part of the connect command processing. Signed-off-by: Ravi Dondaputi Signed-off-by: Jukka Rissanen --- modules/hostap/src/supp_api.c | 23 +++++++++++++++++++++++ modules/hostap/src/supp_api.h | 1 + 2 files changed, 24 insertions(+) diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index e7bae126c4b32d..c1b748c4640049 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -326,6 +326,7 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, { struct add_network_resp resp = {0}; char *chan_list = NULL; + struct net_eth_addr mac = {0}; int ret = 0; if (!wpa_cli_cmd_v("remove_network all")) { @@ -487,6 +488,28 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, } } + memcpy((void *)&mac, params->bssid, WIFI_MAC_ADDR_LEN); + if (net_eth_is_addr_broadcast(&mac) || + net_eth_is_addr_multicast(&mac)) { + wpa_printf(MSG_ERROR, "Invalid BSSID. Configuration " + "of multicast or broadcast MAC is not allowed."); + ret = -EINVAL; + goto rem_net; + } + + if (!net_eth_is_addr_unspecified(&mac)) { + char bssid_str[MAC_STR_LEN] = {0}; + + snprintf(bssid_str, MAC_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x", + params->bssid[0], params->bssid[1], params->bssid[2], + params->bssid[3], params->bssid[4], params->bssid[5]); + + if (!wpa_cli_cmd_v("set_network %d bssid %s", + resp.network_id, bssid_str)) { + goto out; + } + } + /* enable and select network */ if (!wpa_cli_cmd_v("enable_network %d", resp.network_id)) { goto out; diff --git a/modules/hostap/src/supp_api.h b/modules/hostap/src/supp_api.h index 04d720d7509044..e4f92e0b96992d 100644 --- a/modules/hostap/src/supp_api.h +++ b/modules/hostap/src/supp_api.h @@ -16,6 +16,7 @@ #define MAC_ADDR_LEN 6 #endif +#define MAC_STR_LEN 18 /* for ':' or '-' separated MAC address string */ #define CHAN_NUM_LEN 6 /* for space-separated channel numbers string */ /** From dd73b0b5197fbd045716d39be30b61a27fbb077c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0162/1389] hostap: Enable suitable mbedtls options Enable all needed mbedtls options to allow crypto support. Signed-off-by: Jukka Rissanen --- modules/hostap/Kconfig | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 686c65695c2579..473b6278055cfe 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -112,19 +112,18 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO select MBEDTLS select MBEDTLS_CIPHER_MODE_CTR_ENABLED select MBEDTLS_CIPHER_MODE_CBC_ENABLED - select MBEDTLS_PK_WRITE_C select MBEDTLS_ECP_C select MBEDTLS_ECP_ALL_ENABLED - select MBEDTLS_PKCS5_C select MBEDTLS_MAC_CMAC_ENABLED -# select MBEDTLS_PK_C -# select MBEDTLS_CIPHER_PADDING_PKCS7 -# select MBEDTLS_CIPHER_MODE_CBC -# select MBEDTLS_CIPHER_MODE_CTR -# select MBEDTLS_LEGACY_CRYPTO_C -# select MBEDTLS_CTR_DRBG_C -# select MBEDTLS_PK_WRITE_C -# select MBEDTLS_KEY_EXCHANGE_ALL_ENABLED + select MBEDTLS_PKCS5_C + select MBEDTLS_PK_WRITE_C + select MBEDTLS_ECDH_C + select MBEDTLS_ECDSA_C + select MBEDTLS_ECJPAKE_C + select MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + select MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + select MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + select MBEDTLS_KEY_EXCHANGE_ALL_ENABLED config WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE bool "No Crypto support for WiFi" From 1bae912ca5c3e0b684b3b628b519ae7365d52699 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0163/1389] hostap: Handle CTRL-EVENT-SCAN-RESULTS event Handle scan results event in order to avoid warning print for unhandled event. The event is not used for anything atm, this just prevents unknown event printout. Signed-off-by: Jukka Rissanen --- modules/hostap/src/supp_events.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/hostap/src/supp_events.c b/modules/hostap/src/supp_events.c index 31a1e55e793025..22b352aba9782e 100644 --- a/modules/hostap/src/supp_events.c +++ b/modules/hostap/src/supp_events.c @@ -36,6 +36,7 @@ static const struct wpa_supp_event_info { { "CTRL-EVENT-BSS-REMOVED", SUPPLICANT_EVENT_BSS_REMOVED }, { "CTRL-EVENT-TERMINATING", SUPPLICANT_EVENT_TERMINATING }, { "CTRL-EVENT-SCAN-STARTED", SUPPLICANT_EVENT_SCAN_STARTED }, + { "CTRL-EVENT-SCAN-RESULTS", SUPPLICANT_EVENT_SCAN_RESULTS }, { "CTRL-EVENT-SCAN-FAILED", SUPPLICANT_EVENT_SCAN_FAILED }, { "CTRL-EVENT-NETWORK-NOT-FOUND", SUPPLICANT_EVENT_NETWORK_NOT_FOUND }, { "CTRL-EVENT-NETWORK-ADDED", SUPPLICANT_EVENT_NETWORK_ADDED }, @@ -172,6 +173,7 @@ static int supplicant_process_status(struct supplicant_int_event_data *event_dat break; case SUPPLICANT_EVENT_TERMINATING: case SUPPLICANT_EVENT_SCAN_STARTED: + case SUPPLICANT_EVENT_SCAN_RESULTS: case SUPPLICANT_EVENT_SCAN_FAILED: case SUPPLICANT_EVENT_NETWORK_NOT_FOUND: case SUPPLICANT_EVENT_NETWORK_ADDED: From af6970f5ec8d277769824d9d4e722f9a27438682 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0164/1389] hostap: Fix the function name to be more descriptive The wpas_to_wifi_mgmt_diconn_status() was missing "s" char, so name it to wpas_to_wifi_mgmt_disconn_status() as that is more descriptive. Signed-off-by: Jukka Rissanen --- modules/hostap/src/supp_events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/hostap/src/supp_events.c b/modules/hostap/src/supp_events.c index 22b352aba9782e..48a4f58c5ee07c 100644 --- a/modules/hostap/src/supp_events.c +++ b/modules/hostap/src/supp_events.c @@ -68,7 +68,7 @@ static enum wifi_conn_status wpas_to_wifi_mgmt_conn_status(int status) } } -static enum wifi_disconn_reason wpas_to_wifi_mgmt_diconn_status(int status) +static enum wifi_disconn_reason wpas_to_wifi_mgmt_disconn_status(int status) { switch (status) { case WLAN_REASON_DEAUTH_LEAVING: @@ -221,7 +221,7 @@ int supplicant_send_wifi_mgmt_conn_event(void *ctx, int status_code) int supplicant_send_wifi_mgmt_disc_event(void *ctx, int reason_code) { struct wpa_supplicant *wpa_s = ctx; - int status = wpas_to_wifi_mgmt_diconn_status(reason_code); + int status = wpas_to_wifi_mgmt_disconn_status(reason_code); enum net_event_wifi_cmd event; if (!wpa_s || !wpa_s->current_ssid) { From fd3e19f5158c62091a94e43301488809fa456cc8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0165/1389] west.yaml: Update hostap module This contains cherry-pick from Nordic downstream hostap repo as how it is today (20240423) Signed-off-by: Jukka Rissanen --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 2dfce2b26ee286..f3ac97be4f930d 100644 --- a/west.yml +++ b/west.yml @@ -256,7 +256,7 @@ manifest: - name: hostap repo-path: hostap path: modules/lib/hostap - revision: 81bdd8343347a2e36c67253a8aeb22ea7cb41132 + revision: 83574f533fb5c6808af0d9872741d72d48be2f98 - name: libmetal revision: 243eed541b9c211a2ce8841c788e62ddce84425e path: modules/hal/libmetal From 6872ed2494614529a809298a044a604084aa0edc Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:32 +0200 Subject: [PATCH 0166/1389] dts: bindings: vendor-prefixes: Add Croxel Adding Croxel to the list. Signed-off-by: Luis Ubieda --- dts/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 63e7186781bb22..21920433fc7f15 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -150,6 +150,7 @@ cortina Cortina Systems, Inc. cosmic Cosmic Circuits crane Crane Connectivity Solutions creative Creative Technology Ltd +croxel Croxel, Inc. crystalfontz Crystalfontz America, Inc. csky Hangzhou C-SKY Microsystems Co., Ltd csq Shenzen Chuangsiqi Technology Co.,Ltd. From 9e49e7ed49e28bd68dd86544e4a83dedaba0d8a3 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0167/1389] boards: croxel: Add CX1825 Bluetooth prototyping board Basic support: - Discrete LEDs - Buttons - Sensors - Beeper Not included support for: - PDM Microphone - RGB LEDs (charge-pump) Signed-off-by: Luis Ubieda --- boards/croxel/croxel_cx1825/Kconfig | 16 ++ .../croxel_cx1825/Kconfig.croxel_cx1825 | 5 + boards/croxel/croxel_cx1825/Kconfig.defconfig | 9 + boards/croxel/croxel_cx1825/board.cmake | 9 + boards/croxel/croxel_cx1825/board.yml | 5 + .../croxel_cx1825_nrf52840-pinctrl.dtsi | 35 ++++ .../croxel_cx1825/croxel_cx1825_nrf52840.dts | 157 ++++++++++++++++++ .../croxel_cx1825/croxel_cx1825_nrf52840.yaml | 19 +++ .../croxel_cx1825_nrf52840_defconfig | 22 +++ .../croxel_cx1825/doc/img/cx1825_nrf52840.jpg | Bin 0 -> 92855 bytes boards/croxel/croxel_cx1825/doc/index.rst | 130 +++++++++++++++ .../croxel/croxel_cx1825/pre_dt_board.cmake | 7 + boards/croxel/index.rst | 10 ++ 13 files changed, 424 insertions(+) create mode 100644 boards/croxel/croxel_cx1825/Kconfig create mode 100644 boards/croxel/croxel_cx1825/Kconfig.croxel_cx1825 create mode 100644 boards/croxel/croxel_cx1825/Kconfig.defconfig create mode 100644 boards/croxel/croxel_cx1825/board.cmake create mode 100644 boards/croxel/croxel_cx1825/board.yml create mode 100644 boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840-pinctrl.dtsi create mode 100644 boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.dts create mode 100644 boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.yaml create mode 100644 boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840_defconfig create mode 100644 boards/croxel/croxel_cx1825/doc/img/cx1825_nrf52840.jpg create mode 100644 boards/croxel/croxel_cx1825/doc/index.rst create mode 100644 boards/croxel/croxel_cx1825/pre_dt_board.cmake create mode 100644 boards/croxel/index.rst diff --git a/boards/croxel/croxel_cx1825/Kconfig b/boards/croxel/croxel_cx1825/Kconfig new file mode 100644 index 00000000000000..81b03929adc483 --- /dev/null +++ b/boards/croxel/croxel_cx1825/Kconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Luis Ubieda +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_CROXEL_CX1825 + +config BOARD_ENABLE_DCDC + bool "DCDC mode" + select SOC_DCDC_NRF52X + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF52X_HV + default y + +endif # BOARD_CROXEL_CX1825 diff --git a/boards/croxel/croxel_cx1825/Kconfig.croxel_cx1825 b/boards/croxel/croxel_cx1825/Kconfig.croxel_cx1825 new file mode 100644 index 00000000000000..0900f35b4ab5eb --- /dev/null +++ b/boards/croxel/croxel_cx1825/Kconfig.croxel_cx1825 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Luis Ubieda +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_CROXEL_CX1825 + select SOC_NRF52840_QIAA diff --git a/boards/croxel/croxel_cx1825/Kconfig.defconfig b/boards/croxel/croxel_cx1825/Kconfig.defconfig new file mode 100644 index 00000000000000..3e83179e5861da --- /dev/null +++ b/boards/croxel/croxel_cx1825/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Luis Ubieda +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_CROXEL_CX1825 + +config BT_CTLR + default BT + +endif # BOARD_CROXEL_CX1825 diff --git a/boards/croxel/croxel_cx1825/board.cmake b/boards/croxel/croxel_cx1825/board.cmake new file mode 100644 index 00000000000000..f95878945bedfd --- /dev/null +++ b/boards/croxel/croxel_cx1825/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=nRF52840_xxAA" "--speed=4000") +board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000") +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake) diff --git a/boards/croxel/croxel_cx1825/board.yml b/boards/croxel/croxel_cx1825/board.yml new file mode 100644 index 00000000000000..eed390e4a2c090 --- /dev/null +++ b/boards/croxel/croxel_cx1825/board.yml @@ -0,0 +1,5 @@ +board: + name: croxel_cx1825 + vendor: croxel + socs: + - name: nrf52840 diff --git a/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840-pinctrl.dtsi b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840-pinctrl.dtsi new file mode 100644 index 00000000000000..218e6214eb9458 --- /dev/null +++ b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840-pinctrl.dtsi @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Luis Ubieda + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + pwm0_default: pwm0_default { + group1 { + psels = ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; diff --git a/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.dts b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.dts new file mode 100644 index 00000000000000..fac78f10b712c5 --- /dev/null +++ b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.dts @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024 Luis Ubieda + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "croxel_cx1825_nrf52840-pinctrl.dtsi" +#include + +/ { + model = "Croxel CX1825 NRF52840"; + compatible = "croxel,cx1825-nrf52840"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,console = &cdc_acm_0; + zephyr,shell-uart = &cdc_acm_0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led1: led_1 { + gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 16 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button switch 0"; + zephyr,code = ; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + bootloader-led0 = &led0; + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + watchdog0 = &wdt0; + }; +}; + +&adc { + status = "okay"; +}; + +&uicr { + gpio-as-nreset; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +arduino_i2c: &i2c0 { + compatible = "nordic,nrf-twi"; + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; + + hts221: hts221@5f { + compatible = "st,hts221"; + status = "okay"; + reg = <0x5f>; + drdy-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + }; + + lps22hb: lps22hb-press@5c { + compatible = "st,lps22hb-press"; + status = "okay"; + reg = <0x5c>; + }; + + apds9960: apds9960@39 { + compatible = "avago,apds9960"; + status = "okay"; + reg = <0x39>; + int-gpios = <&gpio0 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + lis3dh: lis3dh@18 { + compatible = "st,lis3dh", "st,lis2dh"; + status = "okay"; + reg = <0x18>; + irq-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; + }; +}; + +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + cdc_acm_0: cdc_acm_0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000C000>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000C000 0x00076000>; + }; + slot1_partition: partition@82000 { + label = "image-1"; + reg = <0x00082000 0x00076000>; + }; + + /* + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 0x00008000>; + }; + }; +}; diff --git a/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.yaml b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.yaml new file mode 100644 index 00000000000000..8fa7989a6eb6fd --- /dev/null +++ b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840.yaml @@ -0,0 +1,19 @@ +identifier: croxel_cx1825/nrf52840 +name: Croxel-CX1825-NRF52840 +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - arduino_gpio + - arduino_i2c + - ble + - counter + - gpio + - i2c + - watchdog +vendor: croxel diff --git a/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840_defconfig b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840_defconfig new file mode 100644 index 00000000000000..8694d118b007ac --- /dev/null +++ b/boards/croxel/croxel_cx1825/croxel_cx1825_nrf52840_defconfig @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Luis Ubieda +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# Assume we start console by default +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y + +# Console over USB CDC-ACM +CONFIG_USB_DEVICE_STACK=y +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y diff --git a/boards/croxel/croxel_cx1825/doc/img/cx1825_nrf52840.jpg b/boards/croxel/croxel_cx1825/doc/img/cx1825_nrf52840.jpg new file mode 100644 index 0000000000000000000000000000000000000000..64ce7b6369c8277026694d684fec51d8b85e76f0 GIT binary patch literal 92855 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%0AZZ3bhrxc@QM_%_nNFLUeB`^WS*)Dy(#nhl( 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 AV*mgE literal 0 HcmV?d00001 diff --git a/boards/croxel/croxel_cx1825/doc/index.rst b/boards/croxel/croxel_cx1825/doc/index.rst new file mode 100644 index 00000000000000..f3e42b3657b885 --- /dev/null +++ b/boards/croxel/croxel_cx1825/doc/index.rst @@ -0,0 +1,130 @@ +.. _croxel_cx1825_nrf52840: + +CX1825 nRF52840 +############### + +Overview +******** + +Croxel's `CX1825 Bluetooth Prototyping board`_ provides support for the Nordic +Semiconductor nRF52840 ARM Cortex-M4F CPU and the following devices: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* RADIO (Bluetooth Low Energy and 802.15.4) +* :abbr:`RTC (nRF RTC System Clock)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`USB (Universal Serial Bus)` +* :abbr:`WDT (Watchdog Timer)` + +.. figure:: img/cx1825_nrf52840.jpg + :align: center + :alt: CX1825 + + Croxel's CX1825 Bluetooth Prototyping board (Credit: Croxel) + +Hardware +******** + +- Ezurio's BL654 (nRF52840 ARM Cortex-M4F processor at 64MHz) +- 1 MB flash memory and 256 KB of SRAM +- Coin-cell retainer for Lithium coincell batteries +- 2 Discrete LEDs (Red and Green) +- User Button +- Reset Button +- Accelerometer (LIS3DH) +- Ambient & RGB Light and Proximity Sensor (APDS9960) +- Temperature and Humidity Sensor (HTS221) +- Barometric Pressure sensor (LPS22H) +- Hall Effect Switch (MLX90248) +- RGB LED with Charge-Pump driver (LPS5521) +- Digital Microphone +- Beeper +- QWIIC connector supporting expansion for I2C devices +- USB Connector for data and power +- 16-pin Expansion connector +- SWD Connector + +Supported Features +================== + +- Discrete LEDs (red and green) +- Buttons (User and Reset) +- Sensors (Accelerometer, Light, Temperature and Humidity, Pressure and Hall-Effect sensors) +- Beeper +- Radio (Bluetooth, IEEE 802.15.4) +- SOC peripherals (ADC, Clock, Flash, GPIO, I2C, MPU, NVIC, PWM, Radio, RTC, SPI, USB, WDT) + +Future Feature Support +====================== + +- RGB LED (Charge-Pump driver not implemented) +- Microphone + +Connections and IOs +=================== + +Croxel's CX1825 Bluetooth Prototyping board has detailed information +about the board (`schematic`_) + +LEDs +---- + +- LED1 (red) = P0.8 +- LED2 (green) = P0.12 + +Digital Inputs +-------------- + +- User Button = P1.16 +- Reset Button = P0.18 +- Hall-Effect Switch = P0.15 + +Programming and Debugging +************************* + +Applications for the ``croxel_cx1825/nrf52840`` board configuration +can be built and flashed in the usual way (see :ref:`build_an_application` +and :ref:`application_run` for more details). + +Flashing +======== + +Flashing Zephyr onto the ``croxel_cx1825_nrf52840`` board requires +an external programmer. The programmer is attached to the SWD header. + +Build the Zephyr kernel and the :zephyr:code-sample:`blinky` sample application. + + .. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: croxel_cx1825/nrf52840 + :goals: build + :compact: + +Flash the image. + + .. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: croxel_cx1825/nrf52840 + :goals: flash + :compact: + +You should see the red LED blink. + +References +********** + +.. target-notes:: + +.. _CX1825 Bluetooth Prototyping board: + https://croxel.com/ble + +.. _schematic: + https://croxeldata.s3.amazonaws.com/cx1825/CX1825-01_SCH_200424A.PDF diff --git a/boards/croxel/croxel_cx1825/pre_dt_board.cmake b/boards/croxel/croxel_cx1825/pre_dt_board.cmake new file mode 100644 index 00000000000000..3369c21d3af5ba --- /dev/null +++ b/boards/croxel/croxel_cx1825/pre_dt_board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2022 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - power@40000000 & clock@40000000 & bprot@40000000 +# - acl@4001e000 & flash-controller@4001e000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/croxel/index.rst b/boards/croxel/index.rst new file mode 100644 index 00000000000000..0555c607d90612 --- /dev/null +++ b/boards/croxel/index.rst @@ -0,0 +1,10 @@ +.. _boards-croxel: + +Croxel +###### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* From 9f733e55f491ff711a9bcf7c2ef239ed85cd1fbc Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0168/1389] net: lwm2m: Move one Kconfig to engine features submenu Kconfig option to enable object version reporting should be moved into sub section "Engine features" so it does not clutter up the main LwM2M menu. Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index 4d8e911e373180..d8e0b6fc61fb6f 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -134,6 +134,14 @@ config LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP help Enabling this setting allows the RD client to support bootstrap mode. +config LWM2M_ENGINE_ALWAYS_REPORT_OBJ_VERSION + bool "LwM2M engine always report object version" + help + According to LwM2M specification v1.0 and v1.1, non-core object versions other than 1.0 + 'must' be provided, while all other versions 'may' be provided. With specification v1.2, + a client 'can always attach Object Version Information'. Enable this configuration to + always report all object versions. + choice prompt "Socket handling at idle state" @@ -492,14 +500,6 @@ config LWM2M_ENGINE_DEFAULT_LIFETIME This is also a minimum lifetime that client accepts. If server sets lifetime less than this value, client automatically raises it. -config LWM2M_ENGINE_ALWAYS_REPORT_OBJ_VERSION - bool "LwM2M engine always report object version" - help - According to LwM2M specification v1.0 and v1.1, non-core object versions other than 1.0 - 'must' be provided, while all other versions 'may' be provided. With specification v1.2, - a client 'can always attach Object Version Information'. Enable this configuration to - always report all object versions. - config LWM2M_UPDATE_PERIOD int "LwM2M engine update period" default 0 From a76285e0b62bb988b6afd291841c421e7a7b2042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0169/1389] doc: ci: Zephyr now requires Python 3.10 or higher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update getting started guide, release notes, and CI actions to use Python 3.10 as minimum supported version. Signed-off-by: Benjamin Cabé --- .github/workflows/devicetree_checks.yml | 2 +- .github/workflows/pylib_tests.yml | 2 +- .github/workflows/scripts_tests.yml | 2 +- .github/workflows/twister_tests.yml | 2 +- .github/workflows/twister_tests_blackbox.yml | 2 +- .github/workflows/west_cmds.yml | 2 +- doc/develop/getting_started/index.rst | 2 +- doc/releases/release-notes-3.7.rst | 1 + 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/devicetree_checks.yml b/.github/workflows/devicetree_checks.yml index 3b254354bc2a2a..fd902ac457957f 100644 --- a/.github/workflows/devicetree_checks.yml +++ b/.github/workflows/devicetree_checks.yml @@ -26,7 +26,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04, macos-11, windows-2022] exclude: - os: macos-11 diff --git a/.github/workflows/pylib_tests.yml b/.github/workflows/pylib_tests.yml index fd010bb207b490..8827acebdb493d 100644 --- a/.github/workflows/pylib_tests.yml +++ b/.github/workflows/pylib_tests.yml @@ -25,7 +25,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04] steps: - name: checkout diff --git a/.github/workflows/scripts_tests.yml b/.github/workflows/scripts_tests.yml index bf04640a30a5cb..86db35ae02e0eb 100644 --- a/.github/workflows/scripts_tests.yml +++ b/.github/workflows/scripts_tests.yml @@ -25,7 +25,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-20.04] steps: - name: checkout diff --git a/.github/workflows/twister_tests.yml b/.github/workflows/twister_tests.yml index e7fe29f9e4ad53..fa6737badb81ec 100644 --- a/.github/workflows/twister_tests.yml +++ b/.github/workflows/twister_tests.yml @@ -32,7 +32,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04] steps: - name: checkout diff --git a/.github/workflows/twister_tests_blackbox.yml b/.github/workflows/twister_tests_blackbox.yml index ec380f0eecd574..edec21e28d393c 100644 --- a/.github/workflows/twister_tests_blackbox.yml +++ b/.github/workflows/twister_tests_blackbox.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04] container: image: ghcr.io/zephyrproject-rtos/ci:v0.26.11 diff --git a/.github/workflows/west_cmds.yml b/.github/workflows/west_cmds.yml index 379086e3d14261..c1e38695dc9e98 100644 --- a/.github/workflows/west_cmds.yml +++ b/.github/workflows/west_cmds.yml @@ -29,7 +29,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04, macos-11, windows-2022] exclude: - os: macos-11 diff --git a/doc/develop/getting_started/index.rst b/doc/develop/getting_started/index.rst index 56fcb7e991f456..e51365e34c7c3a 100644 --- a/doc/develop/getting_started/index.rst +++ b/doc/develop/getting_started/index.rst @@ -61,7 +61,7 @@ The current minimum required version for the main dependencies are: - 3.20.5 * - `Python `_ - - 3.8 + - 3.10 * - `Devicetree compiler `_ - 1.4.6 diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 9c3cf6b9de0869..54d96f9d3672e0 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -12,6 +12,7 @@ Major enhancements with this release include: * A new, completely overhauled hardware model has been introduced. This changes the way both SoCs and boards are named, defined and constructed in Zephyr. Additional information can be found in the :ref:`board_porting_guide`. +* Zephyr now requires Python 3.10 or higher An overview of the changes required or recommended when migrating your application from Zephyr v3.6.0 to Zephyr v3.7.0 can be found in the separate :ref:`migration guide`. From 49a8e890501b01622c4557a994ca813df275a1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0170/1389] doc: Relax Sphinx pip dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Zephyr now supports Python 3.10 and onwards, we can use more recent versions of Sphinx, i.e 7.3.x at the time of this commit. Signed-off-by: Benjamin Cabé --- doc/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index 983a29d2f18159..bb12e241930e5a 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,7 +1,7 @@ # DOC: used to generate docs breathe>=4.34 -sphinx~=7.1.0 +sphinx sphinx_rtd_theme~=2.0 sphinx-tabs sphinxcontrib-svg2pdfconverter From 5b99f87d8bef63259a7185cf9d979aa70f44e6f0 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0171/1389] kernel: coding guidelines: cast unused arguments to void - added missing ARG_UNUSED Signed-off-by: frei tycho --- kernel/userspace.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/userspace.c b/kernel/userspace.c index fec564188f883b..a60f2c76dad7df 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -981,6 +981,12 @@ static uintptr_t handler_bad_syscall(uintptr_t bad_id, uintptr_t arg2, uintptr_t arg5, uintptr_t arg6, void *ssf) { + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + ARG_UNUSED(arg4); + ARG_UNUSED(arg5); + ARG_UNUSED(arg6); + LOG_ERR("Bad system call id %" PRIuPTR " invoked", bad_id); arch_syscall_oops(ssf); CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ @@ -990,6 +996,13 @@ static uintptr_t handler_no_syscall(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, void *ssf) { + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + ARG_UNUSED(arg4); + ARG_UNUSED(arg5); + ARG_UNUSED(arg6); + LOG_ERR("Unimplemented system call"); arch_syscall_oops(ssf); CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ From d3c4a0e4eaae2ad2f2ac473d4e3a835355f2ee74 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0172/1389] spelling: Replace occurrences of "iff" with "if and only if" Spell checking tools do not recognize "iff", replace with "if and only if". See https://en.wikipedia.org/wiki/If_and_only_if Signed-off-by: Pieter De Gendt --- drivers/counter/maxim_ds3231.c | 2 +- dts/bindings/base/mutable.yaml | 2 +- include/zephyr/bluetooth/addr.h | 4 ++-- kernel/mmu.c | 6 +++--- scripts/pylib/twister/twisterlib/testsuite.py | 8 ++++---- scripts/spelling.txt | 1 + scripts/west_commands/zspdx/scanner.py | 2 +- subsys/fs/ext2/ext2_ops.c | 2 +- tests/kernel/workq/work/src/main.c | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/counter/maxim_ds3231.c b/drivers/counter/maxim_ds3231.c index d1436ecb3aeb87..c6b8e08b79c717 100644 --- a/drivers/counter/maxim_ds3231.c +++ b/drivers/counter/maxim_ds3231.c @@ -234,7 +234,7 @@ int maxim_ds3231_stat_update(const struct device *dev, /* * Look for current users of the interrupt/square-wave signal and - * enable monitoring iff at least one consumer is active. + * enable monitoring if and only if at least one consumer is active. */ static void validate_isw_monitoring(const struct device *dev) { diff --git a/dts/bindings/base/mutable.yaml b/dts/bindings/base/mutable.yaml index 0e2d1cad3b04ec..7f7aab7dbb78bf 100644 --- a/dts/bindings/base/mutable.yaml +++ b/dts/bindings/base/mutable.yaml @@ -7,7 +7,7 @@ properties: zephyr,mutable: type: boolean description: | - True iff the device structure may be mutated. + True if and only if the device structure may be mutated. Inherit this binding for devices that are runtime-modifiable, in-place. This places the device structure into SRAM rather than Flash. diff --git a/include/zephyr/bluetooth/addr.h b/include/zephyr/bluetooth/addr.h index 3afb5f4a9035cc..794e2acbaf66d5 100644 --- a/include/zephyr/bluetooth/addr.h +++ b/include/zephyr/bluetooth/addr.h @@ -108,8 +108,8 @@ static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b) /** @brief Determine equality of two Bluetooth LE device addresses. * - * The Bluetooth LE addresses are equal iff both the types and the 48-bit - * addresses are numerically equal. + * The Bluetooth LE addresses are equal if and only if both the types and + * the 48-bit addresses are numerically equal. * * @retval #true if the two addresses are equal * @retval #false otherwise diff --git a/kernel/mmu.c b/kernel/mmu.c index 4d364a1b0a64df..162e1c413e941a 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -1440,9 +1440,9 @@ static bool do_page_fault(void *addr, bool pin) * during the page-in/out operation. * * We do however re-enable interrupts during the page-in/page-out - * operation iff interrupts were enabled when the exception was taken; - * in this configuration page faults in an ISR are a bug; all their - * code/data must be pinned. + * operation if and only if interrupts were enabled when the exception + * was taken; in this configuration page faults in an ISR are a bug; + * all their code/data must be pinned. * * If interrupts were disabled when the exception was taken, the * arch code is responsible for keeping them that way when entering diff --git a/scripts/pylib/twister/twisterlib/testsuite.py b/scripts/pylib/twister/twisterlib/testsuite.py index 2a132c3945f578..e967ec1df86fdf 100644 --- a/scripts/pylib/twister/twisterlib/testsuite.py +++ b/scripts/pylib/twister/twisterlib/testsuite.py @@ -82,10 +82,10 @@ def scan_file(inf_name): re.MULTILINE) # Checks if the file contains a definition of "void test_main(void)" # Since ztest provides a plain test_main implementation it is OK to: - # 1. register test suites and not call the run function iff the test - # doesn't have a custom test_main. - # 2. register test suites and a custom test_main definition iff the test - # also calls ztest_run_registered_test_suites. + # 1. register test suites and not call the run function if and only if + # the test doesn't have a custom test_main. + # 2. register test suites and a custom test_main definition if and only if + # the test also calls ztest_run_registered_test_suites. test_main_regex = re.compile( br"^\s*void\s+test_main\(void\)", re.MULTILINE) diff --git a/scripts/spelling.txt b/scripts/spelling.txt index c06453a7aeeb6f..2fe2d7cdea7c98 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -773,6 +773,7 @@ hypervior||hypervisor hypter||hyper idel||idle identidier||identifier +iff||if and only if iligal||illegal illigal||illegal illgal||illegal diff --git a/scripts/west_commands/zspdx/scanner.py b/scripts/west_commands/zspdx/scanner.py index 9f81ede6c7c741..a259325b189657 100644 --- a/scripts/west_commands/zspdx/scanner.py +++ b/scripts/west_commands/zspdx/scanner.py @@ -159,7 +159,7 @@ def normalizeExpression(licsConcluded): return licsConcluded[0] # more than one, so we'll need to combine them - # iff an expression has spaces, it needs parens + # if and only if an expression has spaces, it needs parens revised = [] for lic in licsConcluded: if lic in ["NONE", "NOASSERTION"]: diff --git a/subsys/fs/ext2/ext2_ops.c b/subsys/fs/ext2/ext2_ops.c index 1f8cbdaf04a584..297601c5646974 100644 --- a/subsys/fs/ext2/ext2_ops.c +++ b/subsys/fs/ext2/ext2_ops.c @@ -59,7 +59,7 @@ static int ext2_open(struct fs_file_t *filp, const char *fs_path, fs_mode_t flag /* Inodes allocated by lookup. Must be freed in manually. */ struct ext2_inode *found_inode = args.inode; - /* Not NULL iff FS_O_CREATE and found_inode == NULL */ + /* Not NULL if FS_O_CREATE and found_inode == NULL */ struct ext2_inode *parent = args.parent; /* File has to be created */ diff --git a/tests/kernel/workq/work/src/main.c b/tests/kernel/workq/work/src/main.c index 68a89588379fd4..808c83cb17febc 100644 --- a/tests/kernel/workq/work/src/main.c +++ b/tests/kernel/workq/work/src/main.c @@ -1263,7 +1263,7 @@ ZTEST(work_1cpu, test_1cpu_immed_reschedule) zassert_equal(rc, 1); } -/* Test no-yield behavior, returns true iff work queue priority is +/* Test no-yield behavior, returns true if and only if work queue priority is * higher than test thread priority */ static bool try_queue_no_yield(struct k_work_q *wq) From b9473f0cd8229709127a79c8d5c7932933a14466 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0173/1389] coding guidelines: comply with MISRA Rule 20.9 - avoid to use undefined macros in #if expressions Signed-off-by: Hess Nathan --- tests/subsys/logging/log_api/src/mock_backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/subsys/logging/log_api/src/mock_backend.c b/tests/subsys/logging/log_api/src/mock_backend.c index e9cd66978ace7a..ab4d901c36906b 100644 --- a/tests/subsys/logging/log_api/src/mock_backend.c +++ b/tests/subsys/logging/log_api/src/mock_backend.c @@ -140,7 +140,7 @@ static void process(const struct log_backend *const backend, } zassert_equal(msg->log.hdr.timestamp, exp->timestamp, -#if CONFIG_LOG_TIMESTAMP_64BIT +#ifdef CONFIG_LOG_TIMESTAMP_64BIT "Got: %llu, expected: %llu", #else "Got: %u, expected: %u", From 85ebd210d7f388696cc92f53cecf340130e57bd3 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0174/1389] dts/arm/st: wl: decrease Sub-GHz SPI frequency to 8MHz Commit 246ea739bb03 ("dts/arm/st: wl: increase Sub-GHz SPI frequency to 12MHz") increased the Sub-GHz to 12 MHz. This matches the SX126x datasheet, but there is no information about the maximum speed in the STM32WL datasheet or reference. This works fine when not using DMA. However with DMA activated (adding entries to the device-tree and enabling CONFIG_SPI_STM32_DMA), I have encountered some rare corruption. When it happens, the read from the Sub-GHz device gets an extra 0x00 byte prepended, which confuses the LoRaMac-node library and causes reception failures. Decreasing the frequency to the next round number, that is 8 MHz (i.e. increasing the prescaler from 4 to 6) fixes all the issues I encountered. Signed-off-by: Aurelien Jarno --- dts/arm/st/wl/stm32wl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 3dc4b3fcc3f390..5e69ef4f3b7866 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -333,7 +333,7 @@ compatible = "st,stm32wl-subghz-radio"; reg = <0>; interrupts = <50 0>; - spi-max-frequency = <12000000>; + spi-max-frequency = <8000000>; status = "disabled"; }; }; From 53ebfc0b586569f09f20e2bc5e8e1e121f61ebbd Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0175/1389] drivers: clock_control: add support for MSI clock on STM32WL Add support for the MSI clock on the STM32WL family. This is needed for instance to set the RNG clock domain to MSI in the device tree when not using the PLL. Signed-off-by: Aurelien Jarno --- include/zephyr/dt-bindings/clock/stm32wl_clock.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/zephyr/dt-bindings/clock/stm32wl_clock.h b/include/zephyr/dt-bindings/clock/stm32wl_clock.h index 081490d37e15ae..125e9a765e8255 100644 --- a/include/zephyr/dt-bindings/clock/stm32wl_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32wl_clock.h @@ -29,9 +29,10 @@ /** Fixed clocks */ /* Low speed clocks defined in stm32_common_clocks.h */ #define STM32_SRC_HSI (STM32_SRC_LSI + 1) +#define STM32_SRC_MSI (STM32_SRC_HSI + 1) /* #define STM32_SRC_HSI48 TBD */ /** Bus clock */ -#define STM32_SRC_PCLK (STM32_SRC_HSI + 1) +#define STM32_SRC_PCLK (STM32_SRC_MSI + 1) /** PLL clock outputs */ #define STM32_SRC_PLL_P (STM32_SRC_PCLK + 1) #define STM32_SRC_PLL_Q (STM32_SRC_PLL_P + 1) From c182ea969a9e3e8669b2bfffd6c59b9544d6289a Mon Sep 17 00:00:00 2001 From: Brandon Allen Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0176/1389] samples: Bluetooth: broadcast_audio_sink: rm nrf52820 from sample.yaml nrf52833dk/nrf52820 does not compile so remove it from platform_allow list Signed-off-by: Brandon Allen --- samples/bluetooth/broadcast_audio_sink/sample.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/bluetooth/broadcast_audio_sink/sample.yaml b/samples/bluetooth/broadcast_audio_sink/sample.yaml index d44b5585f79548..ef88ecc4bb23aa 100644 --- a/samples/bluetooth/broadcast_audio_sink/sample.yaml +++ b/samples/bluetooth/broadcast_audio_sink/sample.yaml @@ -18,7 +18,6 @@ tests: harness: bluetooth platform_allow: - nrf52_bsim - - nrf52833dk/nrf52820 - nrf52833dk/nrf52833 - nrf52840dongle/nrf52840 integration_platforms: From eb428689730a88a02c5ccf4c7ea53b06c607a1f8 Mon Sep 17 00:00:00 2001 From: Troels Nilsson Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0177/1389] Bluetooth: Controller: Fix BIS target_event truncated to 8 bits The target_event value is up to 39-bits but was put into a uint8_t Signed-off-by: Troels Nilsson --- subsys/bluetooth/controller/hci/hci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index f5f7f2b2cfcb24..36e062a0ad9151 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5998,7 +5998,7 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) ISO_INT_UNIT_US)); #else /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */ - uint8_t target_event; + uint64_t target_event; uint8_t event_offset; /* Determine the target event and the first event offset after From 09384c68f891dc941c8354aab509fa9900dadce9 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0178/1389] soc: st: stm32: stm32f1x: remove hwmv1 stuff Remove forgotten "config SOC..." stuff. Signed-off-by: Abderrahmane Jarmouni --- soc/st/stm32/stm32f1x/Kconfig.defconfig.stm32f100xx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/soc/st/stm32/stm32f1x/Kconfig.defconfig.stm32f100xx b/soc/st/stm32/stm32f1x/Kconfig.defconfig.stm32f100xx index 916d2fd3d31dd1..65df1c356e7ade 100644 --- a/soc/st/stm32/stm32f1x/Kconfig.defconfig.stm32f100xx +++ b/soc/st/stm32/stm32f1x/Kconfig.defconfig.stm32f100xx @@ -1,13 +1,10 @@ -# ST Microelectronics STM32F100XX MCU +# STMicroelectronics STM32F100XX MCU # Copyright (c) 2020, Jonas Eriksson, Up to Code AB # SPDX-License-Identifier: Apache-2.0 if SOC_STM32F100XB -config SOC - default "stm32f100xb" - config NUM_IRQS default 56 @@ -15,9 +12,6 @@ endif # SOC_STM32F100XB if SOC_STM32F100XE -config SOC - default "stm32f100xe" - config NUM_IRQS default 61 From 296f1f2a4f384c9df75a95e706a8f6d22cec8612 Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0179/1389] Boards: QEMU: Replace -no-acpi with -machine acpi=off on x86 emulation. QEMU 9.0 removes the `-no-acpi` option, which breaks emulation on x86 platforms when CONFIG_ACPI is not set. See: https://github.com/zephyrproject-rtos/zephyr/issues/72191 This PR replaces `-no-acpi` with `-machine acpi=off`, as specified by the QEMU documentation. It works on QEMU 8, but not been tested on earlier versions. Signed-off-by: Glenn Andrews --- boards/qemu/x86/board.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/qemu/x86/board.cmake b/boards/qemu/x86/board.cmake index 2738f43bddefab..660a07fae31d10 100644 --- a/boards/qemu/x86/board.cmake +++ b/boards/qemu/x86/board.cmake @@ -71,7 +71,7 @@ set(QEMU_FLAGS_${ARCH} ) if(NOT CONFIG_ACPI) - list(APPEND QEMU_FLAGS_${ARCH} -no-acpi) + list(APPEND QEMU_FLAGS_${ARCH} -machine acpi=off) endif() # TODO: Support debug From 30e989bcc0482f7405362e1ed2bf0baab8b9dfe7 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0180/1389] drivers: dai: intel: ssp: Only setup mclk/bclk when it is needed by role When SSP is consumer for FS and BCLK then it does not needs MCLK as the shifting and rate is derived form the I2S bus directly. When SSP provides FS only then the BCLK setup is not needed. When SSP provides BCLK only then both MCLK and BCLK setup is needed. In hardware multiple SSPs share the same MCLK source, in case of one SSP port is used as clock provider while other is used as clock consumer then the consumer SSP should not need to depend on the provider SSP configuration, the ports can run in different clock rates. In this example the consumer SSP should not try to configure and lock the MCLK frequency to some arbitrary rate (as it does not need MCLK at all) which might be different than the frequency needed by the provider port. Signed-off-by: Peter Ujfalusi --- drivers/dai/intel/ssp/ssp.c | 50 +++++++++++++++++++++++++++++-------- drivers/dai/intel/ssp/ssp.h | 10 +++++--- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index 5e53bdc41ebf42..215f9912d57740 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -997,15 +997,18 @@ static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) static int dai_ssp_mclk_prepare_enable(struct dai_intel_ssp *dp) { struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); - int ret; + int ret = 0; if (ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE) { return 0; } /* MCLK config */ - ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, - ssp_plat_data->params.mclk_rate); + if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { + ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, + ssp_plat_data->params.mclk_rate); + } + if (ret < 0) { LOG_ERR("invalid mclk_rate = %d for mclk_id = %d", ssp_plat_data->params.mclk_rate, ssp_plat_data->params.mclk_id); @@ -1024,7 +1027,9 @@ static void dai_ssp_mclk_disable_unprepare(struct dai_intel_ssp *dp) return; } - dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); + if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { + dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); + } ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ACTIVE; } @@ -1044,6 +1049,10 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) return 0; } + if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_IS_NEEDED)) { + goto out; + } + sscr0 = sys_read32(dai_base(dp) + SSCR0); #if CONFIG_INTEL_MN @@ -1103,7 +1112,9 @@ static void dai_ssp_bclk_disable_unprepare(struct dai_intel_ssp *dp) return; } #if CONFIG_INTEL_MN - dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); + if (ssp_plat_data->clk_active & SSP_CLK_BCLK_IS_NEEDED) { + dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); + } #endif ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ACTIVE; } @@ -1226,16 +1237,19 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; break; case DAI_INTEL_IPC3_SSP_FMT_CBC_CFC: + ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED | SSP_CLK_BCLK_IS_NEEDED; sscr1 |= SSCR1_SCFR; cfs = true; break; case DAI_INTEL_IPC3_SSP_FMT_CBP_CFC: + ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED; sscr1 |= SSCR1_SCLKDIR; /* FIXME: this mode has not been tested */ cfs = true; break; case DAI_INTEL_IPC3_SSP_FMT_CBC_CFP: + ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED | SSP_CLK_BCLK_IS_NEEDED; sscr1 |= SSCR1_SCFR | SSCR1_SFRMDIR; /* FIXME: this mode has not been tested */ break; @@ -1909,6 +1923,15 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co dp->ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); dp->ssp_plat_data->params.fsync_rate = cfg->rate; + /* MCLK is needed if SSP is FS and/or BCLK provider */ + if (!(regs->ssc1 & (SSCR1_SCLKDIR | SSCR1_SFRMDIR))) { + dp->ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED; + /* BCLK is only needed if SSP is BCLK provider */ + if (!(regs->ssc1 & SSCR1_SCLKDIR)) { + dp->ssp_plat_data->clk_active |= SSP_CLK_BCLK_IS_NEEDED; + } + } + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; } @@ -1933,14 +1956,19 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co if (err) return err; dai_ssp_set_reg_config(dp, cfg, &blob15->i2s_ssp_config); - err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); - if (err) - return err; + if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { + err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); + if (err) + return err; + } } else { dai_ssp_set_reg_config(dp, cfg, &blob->i2s_driver_config.i2s_config); - err = dai_ssp_set_clock_control_ver_1(dp, &blob->i2s_driver_config.mclk_config); - if (err) - return err; + if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { + err = dai_ssp_set_clock_control_ver_1(dp, + &blob->i2s_driver_config.mclk_config); + if (err) + return err; + } } ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; diff --git a/drivers/dai/intel/ssp/ssp.h b/drivers/dai/intel/ssp/ssp.h index f35b398b6b78b9..4f12ceece91dbf 100644 --- a/drivers/dai/intel/ssp/ssp.h +++ b/drivers/dai/intel/ssp/ssp.h @@ -211,10 +211,12 @@ /* SSP flush retry counts maximum */ #define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 -#define SSP_CLK_MCLK_ES_REQ BIT(0) -#define SSP_CLK_MCLK_ACTIVE BIT(1) -#define SSP_CLK_BCLK_ES_REQ BIT(2) -#define SSP_CLK_BCLK_ACTIVE BIT(3) +#define SSP_CLK_MCLK_IS_NEEDED BIT(0) +#define SSP_CLK_MCLK_ES_REQ BIT(1) +#define SSP_CLK_MCLK_ACTIVE BIT(2) +#define SSP_CLK_BCLK_IS_NEEDED BIT(3) +#define SSP_CLK_BCLK_ES_REQ BIT(4) +#define SSP_CLK_BCLK_ACTIVE BIT(5) #define I2SLCTL_OFFSET 0x04 From 06e08ff78f11ba3f1557fd912ad01788d9053709 Mon Sep 17 00:00:00 2001 From: Ping Wang Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0181/1389] Bluetooth: Audio: Shell: adds support for LESC in the host The commit adds support for LESC in the host if the controller does not support the public key generation for ECDH. Signed-off-by: Ping Wang --- .../bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index ff527ea848bb7f..1fdf79b2067f35 100644 --- a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -8,3 +8,4 @@ CONFIG_USB_DEVICE_PRODUCT="Zephyr Shell USB" # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +CONFIG_BT_TINYCRYPT_ECC=y From b40ee2f24eaee03b6e4cc9280cf5a305620f86c5 Mon Sep 17 00:00:00 2001 From: Ping Wang Date: Sun, 26 May 2024 22:38:33 +0200 Subject: [PATCH 0182/1389] Bluetooth: Audio: Shell: adds support for BIS index parameter When calling bap_broadcast_assistant add_pa_sync, it should only set the BIS index field as optional parameters and not to whatever is in the BASE. If setting BIS index which the BASE does not support, then the command should be rejected. This PR fixes https://github.com/zephyrproject-rtos/zephyr/issues/70835 Signed-off-by: Ping Wang --- .../audio/shell/bap_broadcast_assistant.c | 19 +++++++++++++++++++ .../nrf5340_audio_dk_nrf5340_cpuapp.conf | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index fe28cdbb853116..d7fc15387433af 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -810,6 +810,7 @@ static inline bool add_pa_sync_base_subgroup_cb(const struct bt_bap_base_subgrou ret = bt_bap_base_subgroup_foreach_bis(subgroup, add_pa_sync_base_subgroup_bis_cb, subgroup_param); + if (ret < 0) { return false; } @@ -848,6 +849,8 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, param.adv_sid = pa_info.sid; param.pa_interval = pa_info.interval; + memset(&subgroup_params, 0, sizeof(subgroup_params)); + param.pa_sync = shell_strtobool(argv[1], 0, &err); if (err != 0) { shell_error(sh, "Could not parse pa_sync: %d", err); @@ -900,6 +903,22 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, } } + /* use the BASE to verify the BIS indexes set by command */ + for (size_t j = 0U; j < param.num_subgroups; j++) { + if (bis_bitfield_req == 0) { + /* Not set the BIS indexes by command, use BASE directly */ + break; + } else if ((subgroup_params[j].bis_sync & bis_bitfield_req) != 0) { + subgroup_params[j].bis_sync &= bis_bitfield_req; + } else { + /* Command is rejected when BASE does not support BIS index in command */ + shell_error(ctx_shell, "Cannot set BIS index 0x%06X when BASE subgroup %d " + "only supports %d", bis_bitfield_req, j, + subgroup_params[j].bis_sync); + return -ENOEXEC; + } + } + err = bt_bap_broadcast_assistant_add_src(default_conn, ¶m); if (err != 0) { shell_print(sh, "Fail: %d", err); diff --git a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index 1fdf79b2067f35..849817b36acb27 100644 --- a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -7,5 +7,5 @@ CONFIG_USB_DEVICE_AUDIO=y CONFIG_USB_DEVICE_PRODUCT="Zephyr Shell USB" # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=5120 CONFIG_BT_TINYCRYPT_ECC=y From 42064004d975f06f5e66f0405ea5aa685293bc6e Mon Sep 17 00:00:00 2001 From: Ping Wang Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0183/1389] Bluetooth: Audio: Shell: adds support for BIS index parameter When calling bap_broadcast_assistant add_pa_sync, it should only set the BIS index field as optional parameters and not to whatever is in the BASE. If setting BIS index which the BASE does not support, then the command should be rejected. This PR fixes https://github.com/zephyrproject-rtos/zephyr/issues/70835 Signed-off-by: Ping Wang --- .../audio/shell/bap_broadcast_assistant.c | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index d7fc15387433af..dfe868fac45a1e 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -830,6 +830,7 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, struct bt_le_per_adv_sync_info pa_info; unsigned long broadcast_id; uint32_t bis_bitfield_req; + uint32_t subgroups_bis_sync; int err; if (pa_sync == NULL) { @@ -873,6 +874,7 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, param.broadcast_id = broadcast_id; bis_bitfield_req = 0U; + subgroups_bis_sync = 0U; for (size_t i = 3U; i < argc; i++) { const unsigned long index = shell_strtoul(argv[i], 16, &err); @@ -906,19 +908,24 @@ static int cmd_bap_broadcast_assistant_add_pa_sync(const struct shell *sh, /* use the BASE to verify the BIS indexes set by command */ for (size_t j = 0U; j < param.num_subgroups; j++) { if (bis_bitfield_req == 0) { - /* Not set the BIS indexes by command, use BASE directly */ - break; - } else if ((subgroup_params[j].bis_sync & bis_bitfield_req) != 0) { - subgroup_params[j].bis_sync &= bis_bitfield_req; + /* Request a PA sync without BIS sync */ + subgroup_params[j].bis_sync = 0; } else { - /* Command is rejected when BASE does not support BIS index in command */ - shell_error(ctx_shell, "Cannot set BIS index 0x%06X when BASE subgroup %d " - "only supports %d", bis_bitfield_req, j, - subgroup_params[j].bis_sync); - return -ENOEXEC; + subgroups_bis_sync |= subgroup_params[j].bis_sync; + /* only set the BIS index field as optional parameters */ + /* not to whatever is in the BASE */ + subgroup_params[j].bis_sync &= bis_bitfield_req; } } + if ((subgroups_bis_sync & bis_bitfield_req) != bis_bitfield_req) { + /* bis_sync of all subgroups should contain at least all the bits in request */ + /* Otherwise Command will be rejected */ + shell_error(ctx_shell, "Cannot set BIS index 0x%06X when BASE subgroups only " + "supports %d", bis_bitfield_req, subgroups_bis_sync); + return -ENOEXEC; + } + err = bt_bap_broadcast_assistant_add_src(default_conn, ¶m); if (err != 0) { shell_print(sh, "Fail: %d", err); From a773c69da318da5975e0f4f8d4d3e3a66d16084c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0184/1389] drivers: hwinfo: shell: fix error message when no hardware support When there is no implementation for a particular hardware information device, the API return -ENOSYS, while the hardware information shell checks for -ENOTSUP. This returns a non-user friendly message: uart:~$ hwinfo devid Error: -88 The API can't be changed easily without breaking things, so let's change the shell instead. This gives: uart:~$ hwinfo devid Not supported by hardware Signed-off-by: Aurelien Jarno --- drivers/hwinfo/hwinfo_shell.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hwinfo/hwinfo_shell.c b/drivers/hwinfo/hwinfo_shell.c index 39104425d5293e..934c5c4283fa12 100644 --- a/drivers/hwinfo/hwinfo_shell.c +++ b/drivers/hwinfo/hwinfo_shell.c @@ -18,9 +18,9 @@ static int cmd_get_device_id(const struct shell *sh, size_t argc, char **argv) length = hwinfo_get_device_id(dev_id, sizeof(dev_id)); - if (length == -ENOTSUP) { + if (length == -ENOSYS) { shell_error(sh, "Not supported by hardware"); - return -ENOTSUP; + return -ENOSYS; } else if (length < 0) { shell_error(sh, "Error: %zd", length); return length; @@ -138,7 +138,7 @@ static int cmd_show_reset_cause(const struct shell *sh, size_t argc, ARG_UNUSED(argv); res = hwinfo_get_reset_cause(&cause); - if (res == -ENOTSUP) { + if (res == -ENOSYS) { shell_error(sh, "Not supported by hardware"); return res; } else if (res != 0) { @@ -165,7 +165,7 @@ static int cmd_clear_reset_cause(const struct shell *sh, size_t argc, ARG_UNUSED(argv); res = hwinfo_clear_reset_cause(); - if (res == -ENOTSUP) { + if (res == -ENOSYS) { shell_error(sh, "Not supported by hardware"); } else if (res != 0) { shell_error(sh, "Error clearing the reset causes [%d]", res); @@ -185,7 +185,7 @@ static int cmd_supported_reset_cause(const struct shell *sh, size_t argc, ARG_UNUSED(argv); res = hwinfo_get_supported_reset_cause(&cause); - if (res == -ENOTSUP) { + if (res == -ENOSYS) { shell_error(sh, "Not supported by hardware"); } else if (res != 0) { shell_error(sh, "Could not get the supported reset causes [%d]", res); From 29ac730f83e1a1545982bdf5fb3ff28f992409a7 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0185/1389] coding guidelines: comply with MISRA Rule 20.9 - avoid to use undefined macros in #if expressions Signed-off-by: Hess Nathan --- drivers/serial/uart_nrfx_uarte.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index b6d138dc2e0bac..cc2c9b90594d85 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -548,7 +548,7 @@ static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) const struct uarte_nrfx_config *config = dev->config; NRF_UARTE_Type *uarte = get_uarte_instance(dev); -#if CONFIG_PM_DEVICE +#ifdef CONFIG_PM_DEVICE enum pm_device_state state; (void)pm_device_state_get(dev, &state); From e725fe283e61b4fa1e5cf87b8b87a9faea3455a1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0186/1389] tests: net: reuseaddr_reuseport: Fix zassert statements One should not call a function directly from within zassert() as it can cause the value of errno to be lost as seen by this failed test output Assertion failed at tests/net/socket/reuseaddr_reuseport/src/main.c:151: test_bind_success: (zsock_bind(sock, addr, addrlen) not equal to 0) bind() failed with error 0 FAIL - test_ipv4_udp_bad_both_not_set in 0.000 seconds Signed-off-by: Jukka Rissanen --- .../net/socket/reuseaddr_reuseport/src/main.c | 101 ++++++++++-------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/tests/net/socket/reuseaddr_reuseport/src/main.c b/tests/net/socket/reuseaddr_reuseport/src/main.c index c5e6cb4633f3d4..a59dd1a9560585 100644 --- a/tests/net/socket/reuseaddr_reuseport/src/main.c +++ b/tests/net/socket/reuseaddr_reuseport/src/main.c @@ -36,13 +36,15 @@ static void test_add_local_ip_address(sa_family_t family, const char *ip) { if (family == AF_INET) { struct sockaddr_in addr; + struct net_if_addr *ifaddr; zsock_inet_pton(AF_INET, ip, &addr.sin_addr); - zassert_not_null(net_if_ipv4_addr_add(net_if_get_default(), - &addr.sin_addr, - NET_ADDR_MANUAL, - 0), + ifaddr = net_if_ipv4_addr_add(net_if_get_default(), + &addr.sin_addr, + NET_ADDR_MANUAL, + 0); + zassert_not_null(ifaddr, "Cannot add IPv4 address %s", ip); } else if (family == AF_INET6) { struct sockaddr_in6 addr; @@ -102,16 +104,18 @@ static inline void prepare_sock_udp(sa_family_t family, const char *ip, uint16_t static void test_getsocketopt_reuseaddr(int sock, void *optval, socklen_t *optlen) { - zassert_equal(zsock_getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, optval, optlen), - 0, - "getsocketopt() failed with error %d", errno); + int ret; + + ret = zsock_getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, optval, optlen); + zassert_equal(ret, 0, "getsocketopt() failed with error %d", errno); } static void test_setsocketopt_reuseaddr(int sock, void *optval, socklen_t optlen) { - zassert_equal(zsock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, optval, optlen), - 0, - "setsocketopt() failed with error %d", errno); + int ret; + + ret = zsock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, optval, optlen); + zassert_equal(ret, 0, "setsocketopt() failed with error %d", errno); } static void test_enable_reuseaddr(int sock) @@ -123,16 +127,18 @@ static void test_enable_reuseaddr(int sock) static void test_getsocketopt_reuseport(int sock, void *optval, socklen_t *optlen) { - zassert_equal(zsock_getsockopt(sock, SOL_SOCKET, SO_REUSEPORT, optval, optlen), - 0, - "getsocketopt() failed with error %d", errno); + int ret; + + ret = zsock_getsockopt(sock, SOL_SOCKET, SO_REUSEPORT, optval, optlen); + zassert_equal(ret, 0, "getsocketopt() failed with error %d", errno); } static void test_setsocketopt_reuseport(int sock, void *optval, socklen_t optlen) { - zassert_equal(zsock_setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, optval, optlen), - 0, - "setsocketopt() failed with error %d", errno); + int ret; + + ret = zsock_setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, optval, optlen); + zassert_equal(ret, 0, "setsocketopt() failed with error %d", errno); } static void test_enable_reuseport(int sock) @@ -144,16 +150,18 @@ static void test_enable_reuseport(int sock) static void test_bind_success(int sock, const struct sockaddr *addr, socklen_t addrlen) { - zassert_equal(zsock_bind(sock, addr, addrlen), - 0, - "bind() failed with error %d", errno); + int ret; + + ret = zsock_bind(sock, addr, addrlen); + zassert_equal(ret, 0, "bind() failed with error %d", errno); } static void test_bind_fail(int sock, const struct sockaddr *addr, socklen_t addrlen) { - zassert_equal(zsock_bind(sock, addr, addrlen), - -1, - "bind() succeeded incorrectly"); + int ret; + + ret = zsock_bind(sock, addr, addrlen); + zassert_equal(ret, -1, "bind() succeeded incorrectly"); zassert_equal(errno, EADDRINUSE, "bind() returned unexpected errno (%d)", errno); } @@ -167,9 +175,10 @@ static void test_listen(int sock) static void test_connect_success(int sock, const struct sockaddr *addr, socklen_t addrlen) { - zassert_equal(zsock_connect(sock, addr, addrlen), - 0, - "connect() failed with error %d", errno); + int ret; + + ret = zsock_connect(sock, addr, addrlen); + zassert_equal(ret, 0, "connect() failed with error %d", errno); if (IS_ENABLED(CONFIG_NET_TC_THREAD_PREEMPTIVE)) { /* Let the connection proceed */ @@ -179,9 +188,10 @@ static void test_connect_success(int sock, const struct sockaddr *addr, socklen_ static void test_connect_fail(int sock, const struct sockaddr *addr, socklen_t addrlen) { - zassert_equal(zsock_connect(sock, addr, addrlen), - -1, - "connect() succeeded incorrectly"); + int ret; + + ret = zsock_connect(sock, addr, addrlen); + zassert_equal(ret, -1, "connect() succeeded incorrectly"); zassert_equal(errno, EADDRINUSE, "connect() returned unexpected errno (%d)", errno); } @@ -198,41 +208,46 @@ static int test_accept(int sock, struct sockaddr *addr, socklen_t *addrlen) static void test_sendto(int sock, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { - zassert_equal(zsock_sendto(sock, buf, len, flags, dest_addr, addrlen), - len, - "sendto failed with error %d", errno); + int ret; + + ret = zsock_sendto(sock, buf, len, flags, dest_addr, addrlen); + zassert_equal(ret, len, "sendto failed with error %d", errno); } static void test_recvfrom_success(int sock, void *buf, size_t max_len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { - zassert_equal(zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen), - max_len, - "recvfrom failed with error %d", errno); + int ret; + + ret = zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen); + zassert_equal(ret, max_len, "recvfrom failed with error %d", errno); } static void test_recvfrom_fail(int sock, void *buf, size_t max_len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { - zassert_equal(zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen), - -1, - "recvfrom succeeded incorrectly"); + int ret; + + ret = zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen); + zassert_equal(ret, -1, "recvfrom succeeded incorrectly"); zassert_equal(errno, EAGAIN, "recvfrom() returned unexpected errno (%d)", errno); } static void test_recv_success(int sock, void *buf, size_t max_len, int flags) { - zassert_equal(zsock_recv(sock, buf, max_len, flags), - max_len, - "recv failed with error %d", errno); + int ret; + + ret = zsock_recv(sock, buf, max_len, flags); + zassert_equal(ret, max_len, "recv failed with error %d", errno); } static void test_recv_fail(int sock, void *buf, size_t max_len, int flags) { - zassert_equal(zsock_recv(sock, buf, max_len, flags), - -1, - "recvfrom succeeded incorrectly"); + int ret; + + ret = zsock_recv(sock, buf, max_len, flags); + zassert_equal(ret, -1, "recvfrom succeeded incorrectly"); zassert_equal(errno, EAGAIN, "recv() returned unexpected errno (%d)", errno); } From 2ba785311e1c059f98f5c81534c9935f7a63d9c0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0187/1389] net: Do not directly use net_buf size field The size field in net_buf should not be used directly as then the optional headroom will not be taken into account. There is the net_buf_max_len() API that should be used instead. Signed-off-by: Jukka Rissanen --- subsys/net/ip/net_pkt.c | 7 ++++--- subsys/net/ip/tcp.c | 4 ++-- subsys/net/lib/dns/llmnr_responder.c | 4 ++-- subsys/net/lib/dns/mdns_responder.c | 6 +++--- subsys/net/lib/dns/resolve.c | 10 ++++++---- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index 81d9d35b736837..3a72522c928930 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -315,10 +315,10 @@ void net_pkt_print_frags(struct net_pkt *pkt) while (frag) { total += frag->len; - frag_size = frag->size; + frag_size = net_buf_max_len(frag); NET_INFO("[%d] frag %p len %d max len %u size %d pool %p", - count, frag, frag->len, net_buf_max_len(frag), + count, frag, frag->len, frag->size, frag_size, net_buf_pool_get(frag->pool_id)); count++; @@ -2130,8 +2130,9 @@ size_t net_pkt_get_contiguous_len(struct net_pkt *pkt) size_t len; len = net_pkt_is_being_overwritten(pkt) ? - pkt->cursor.buf->len : pkt->cursor.buf->size; + pkt->cursor.buf->len : net_buf_max_len(pkt->cursor.buf); len -= pkt->cursor.pos - pkt->cursor.buf->data; + return len; } diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 2de0e0c3401954..8d72e45c164727 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -111,7 +111,7 @@ static int tcp_pkt_linearize(struct net_pkt *pkt, size_t pos, size_t len) buf = net_pkt_get_frag(pkt, len, TCP_PKT_ALLOC_TIMEOUT); - if (!buf || buf->size < len) { + if (!buf || net_buf_max_len(buf) < len) { if (buf) { net_buf_unref(buf); } @@ -119,7 +119,7 @@ static int tcp_pkt_linearize(struct net_pkt *pkt, size_t pos, size_t len) goto out; } - net_buf_linearize(buf->data, buf->size, pkt->frags, pos, len); + net_buf_linearize(buf->data, net_buf_max_len(buf), pkt->frags, pos, len); net_buf_add(buf, len); len1 = first->len - (pkt->cursor.pos - pkt->cursor.buf->data); diff --git a/subsys/net/lib/dns/llmnr_responder.c b/subsys/net/lib/dns/llmnr_responder.c index b5442904a74f9b..b2881e7829cdb7 100644 --- a/subsys/net/lib/dns/llmnr_responder.c +++ b/subsys/net/lib/dns/llmnr_responder.c @@ -246,7 +246,7 @@ static int create_answer(struct net_context *ctx, /* Prepare the response into the query buffer: move the name * query buffer has to get enough free space: dns_hdr + query + answer */ - if ((query->size - query->len) < (DNS_MSG_HEADER_SIZE + + if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE + (DNS_QTYPE_LEN + DNS_QCLASS_LEN) * 2 + DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len + query->len)) { @@ -491,7 +491,7 @@ static int dns_read(struct net_context *ctx, enum dns_rr_type qtype; enum dns_class qclass; - (void)memset(result->data, 0, result->size); + (void)memset(result->data, 0, net_buf_max_len(result)); result->len = 0U; ret = dns_unpack_query(&dns_msg, result, &qtype, &qclass); diff --git a/subsys/net/lib/dns/mdns_responder.c b/subsys/net/lib/dns/mdns_responder.c index 893a3692d373ff..e10f40d1194e9b 100644 --- a/subsys/net/lib/dns/mdns_responder.c +++ b/subsys/net/lib/dns/mdns_responder.c @@ -238,7 +238,7 @@ static int create_answer(struct net_context *ctx, /* Prepare the response into the query buffer: move the name * query buffer has to get enough free space: dns_hdr + answer */ - if ((query->size - query->len) < (DNS_MSG_HEADER_SIZE + + if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE + DNS_QTYPE_LEN + DNS_QCLASS_LEN + DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len)) { @@ -453,7 +453,7 @@ static void send_sd_response(struct net_context *ctx, /* Construct the response */ if (service_type_enum) { ret = dns_sd_handle_service_type_enum(record, addr4, addr6, - result->data, result->size); + result->data, net_buf_max_len(result)); if (ret < 0) { NET_DBG("dns_sd_handle_service_type_enum() failed (%d)", ret); @@ -461,7 +461,7 @@ static void send_sd_response(struct net_context *ctx, } } else { ret = dns_sd_handle_ptr_query(record, addr4, addr6, - result->data, result->size); + result->data, net_buf_max_len(result)); if (ret < 0) { NET_DBG("dns_sd_handle_ptr_query() failed (%d)", ret); continue; diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 37032f4de45b87..4e723944800e00 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -689,7 +689,7 @@ int dns_validate_msg(struct dns_resolve_context *ctx, if (dns_cname) { ret = dns_copy_qname(dns_cname->data, &dns_cname->len, - dns_cname->size, + net_buf_max_len(dns_cname), dns_msg, pos); if (ret < 0) { ret = DNS_EAI_SYSTEM; @@ -893,7 +893,8 @@ static int dns_write(struct dns_resolve_context *ctx, dns_id = ctx->queries[query_idx].id; query_type = ctx->queries[query_idx].query_type; - ret = dns_msg_pack_query(dns_data->data, &dns_data->len, dns_data->size, + ret = dns_msg_pack_query(dns_data->data, &dns_data->len, + net_buf_max_len(dns_data), dns_qname->data, dns_qname->len, dns_id, (enum dns_rr_type)query_type); if (ret < 0) { @@ -1028,13 +1029,14 @@ int dns_resolve_cancel_with_name(struct dns_resolve_context *ctx, return -ENOMEM; } - ret = dns_msg_pack_qname(&len, buf->data, buf->size, + ret = dns_msg_pack_qname(&len, buf->data, + net_buf_max_len(buf), query_name); if (ret >= 0) { /* If the query string + \0 + query type (A or AAAA) * does not fit the tmp buf, then bail out */ - if ((len + 2) > buf->size) { + if ((len + 2) > net_buf_max_len(buf)) { net_buf_unref(buf); return -ENOMEM; } From cc45b9838ff480165df18f5da9ea90ef91b7bf71 Mon Sep 17 00:00:00 2001 From: Benjamin Lindqvist Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0188/1389] net: coap_client: handle observe requests as intended The coap_client lib only handled "one-shot" requests properly. This patch allows it to keep listening for additional responses to a request, if the request was made with the CoAP OBSERVE option appended. An API for canceling such requests is also added. Signed-off-by: Benjamin Lindqvist --- include/zephyr/net/coap_client.h | 11 +++++++++++ subsys/net/lib/coap/coap_client.c | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index e48048d5c26518..819559e9d936f2 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -137,6 +137,17 @@ int coap_client_init(struct coap_client *client, const char *info); int coap_client_req(struct coap_client *client, int sock, const struct sockaddr *addr, struct coap_client_request *req, struct coap_transmission_parameters *params); +/** + * @brief Cancel all current requests. + * + * This is intended for canceling long-running requests (e.g. GETs with the OBSERVE option set) + * which has gone stale for some reason. + * + * @param client Client instance. + */ +void coap_client_cancel_requests(struct coap_client *client); + + /** * @} */ diff --git a/subsys/net/lib/coap/coap_client.c b/subsys/net/lib/coap/coap_client.c index 4bdf387a2429d5..33b66acf7dce92 100644 --- a/subsys/net/lib/coap/coap_client.c +++ b/subsys/net/lib/coap/coap_client.c @@ -811,10 +811,19 @@ static int handle_response(struct coap_client *client, const struct coap_packet } fail: client->response_ready = false; - internal_req->request_ongoing = false; + if (ret != 0 || !coap_request_is_observe(&internal_req->request)) { + internal_req->request_ongoing = false; + } return ret; } +void coap_client_cancel_requests(struct coap_client *client) +{ + for (int i = 0; i < ARRAY_SIZE(client->requests); i++) { + client->requests[i].request_ongoing = false; + } +} + void coap_client_recv(void *coap_cl, void *a, void *b) { int ret; From 8c500ba1faeeef667151edec2aa67044f446710a Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0189/1389] pm: re-program timer HW only when the exit latency is not zero Avoid re-programming timer unnecessarily. Signed-off-by: Dong Wang Signed-off-by: Flavio Ceolin --- subsys/pm/pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index d81072c3a5b6a0..bb586073fcbf3e 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -210,7 +210,8 @@ bool pm_system_suspend(int32_t ticks) } #endif - if (ticks != K_TICKS_FOREVER) { + if ((z_cpus_pm_state[id].exit_latency_us != 0) && + (ticks != K_TICKS_FOREVER)) { /* * We need to set the timer to interrupt a little bit early to * accommodate the time required by the CPU to fully wake up. From feff26cad1db7d84adaae9d6ebe00d65b594d983 Mon Sep 17 00:00:00 2001 From: Juliane Schulze Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0190/1389] drivers: tmag5273 add missing ifdef around CRC support Fixes an error causing build issues if CRC support is not set to active. Signed-off-by: Juliane Schulze --- drivers/sensor/ti/tmag5273/tmag5273.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/sensor/ti/tmag5273/tmag5273.c b/drivers/sensor/ti/tmag5273/tmag5273.c index bade48fa80f4f1..0ef91725deef87 100644 --- a/drivers/sensor/ti/tmag5273/tmag5273.c +++ b/drivers/sensor/ti/tmag5273/tmag5273.c @@ -65,7 +65,7 @@ struct tmag5273_config { struct gpio_dt_spec int_gpio; -#if CONFIG_CRC +#ifdef CONFIG_CRC bool crc_enabled; #endif }; @@ -146,7 +146,7 @@ static int tmag5273_check_device_status(const struct tmag5273_config *drv_cfg, if ((*device_status & TMAG5273_VCC_UV_ER_MSK) == TMAG5273_VCC_UV_ERR) { LOG_WRN("VCC undervoltage detected"); } -#if CONFIG_CRC +#ifdef CONFIG_CRC if (drv_cfg->crc_enabled && ((*device_status & TMAG5273_OTP_CRC_ER_MSK) == TMAG5273_OTP_CRC_ERR)) { LOG_WRN("OTP CRC error detected"); @@ -387,7 +387,7 @@ static inline int tmag5273_attr_get_xyz_calc(const struct device *dev, struct se static inline uint8_t tmag5273_get_fetch_block_size(const struct tmag5273_config *drv_cfg, uint8_t remaining_bytes) { -#if CONFIG_CRC +#ifdef CONFIG_CRC if (drv_cfg->crc_enabled && (remaining_bytes > TMAG5273_CRC_DATA_BYTES)) { return TMAG5273_CRC_DATA_BYTES; } @@ -398,10 +398,13 @@ static inline uint8_t tmag5273_get_fetch_block_size(const struct tmag5273_config /** @brief returns the size of the CRC field if active */ static inline uint8_t tmag5273_get_crc_size(const struct tmag5273_config *drv_cfg) { +#ifdef CONFIG_CRC if (drv_cfg->crc_enabled) { return TMAG5273_CRC_I2C_SIZE; } - +#else + ARG_UNUSED(drv_cfg); +#endif return 0; } @@ -624,7 +627,7 @@ static int tmag5273_sample_fetch(const struct device *dev, enum sensor_channel c uint32_t nb_bytes = end_address - start_address + 1; -#if CONFIG_CRC +#ifdef CONFIG_CRC /* if CRC is enabled multiples of TMAG5273_CRC_DATA_BYTES need to be read */ if (drv_cfg->crc_enabled && ((nb_bytes % TMAG5273_CRC_DATA_BYTES) != 0)) { const uint8_t diff = TMAG5273_CRC_DATA_BYTES - (nb_bytes % TMAG5273_CRC_DATA_BYTES); @@ -659,7 +662,7 @@ static int tmag5273_sample_fetch(const struct device *dev, enum sensor_channel c return -EIO; } -#if CONFIG_CRC +#ifdef CONFIG_CRC /* check data validity, if activated */ if (drv_cfg->crc_enabled) { const uint8_t crc = crc8_ccitt(0xFF, &i2c_buffer[offset], block_size); @@ -891,7 +894,7 @@ static inline int tmag5273_init_device_config(const struct device *dev) /* REG_DEVICE_CONFIG_1 */ regdata = 0; -#if CONFIG_CRC +#ifdef CONFIG_CRC if (drv_cfg->crc_enabled) { regdata |= TMAG5273_CRC_ENABLE; } From 148f93b046b6598de7d2cfcff8b5d8062cd77f89 Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0191/1389] libc: minimal: Add 'noreturn' attribute to abort() and exit() This aligns abort() and exit() definitions with other libc. Without 'noreturn' attribute, compilers have to assume that we will return from these functions which can lead to surprising errors like 'error: non-void function does not return a value'. Signed-off-by: Patryk Duda --- lib/libc/common/source/stdlib/abort.c | 2 +- lib/libc/minimal/include/stdlib.h | 8 +++++--- lib/libc/minimal/source/stdlib/exit.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/libc/common/source/stdlib/abort.c b/lib/libc/common/source/stdlib/abort.c index 49d18e8ae6782d..3b17be4a638309 100644 --- a/lib/libc/common/source/stdlib/abort.c +++ b/lib/libc/common/source/stdlib/abort.c @@ -7,7 +7,7 @@ #include #include -void abort(void) +FUNC_NORETURN void abort(void) { printk("abort()\n"); k_panic(); diff --git a/lib/libc/minimal/include/stdlib.h b/lib/libc/minimal/include/stdlib.h index c60f9c17825a5f..a62a4a1e4d61f7 100644 --- a/lib/libc/minimal/include/stdlib.h +++ b/lib/libc/minimal/include/stdlib.h @@ -12,6 +12,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -41,12 +43,12 @@ void qsort(void *base, size_t nmemb, size_t size, #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 -void _exit(int status); -static inline void exit(int status) +FUNC_NORETURN void _exit(int status); +FUNC_NORETURN static inline void exit(int status) { _exit(status); } -void abort(void); +FUNC_NORETURN void abort(void); #ifdef CONFIG_MINIMAL_LIBC_RAND #define RAND_MAX INT_MAX diff --git a/lib/libc/minimal/source/stdlib/exit.c b/lib/libc/minimal/source/stdlib/exit.c index 036132ac1e9510..789a2940409bdc 100644 --- a/lib/libc/minimal/source/stdlib/exit.c +++ b/lib/libc/minimal/source/stdlib/exit.c @@ -7,7 +7,7 @@ #include #include -void _exit(int status) +FUNC_NORETURN void _exit(int status) { printk("exit\n"); while (1) { From 859703bc63aa420aaa4d32464a56a7f358006148 Mon Sep 17 00:00:00 2001 From: Louis Feller Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0192/1389] dts: stm32wba: Fix RNG base address Set RNG address to its non-secure alias. See RM0493 STM32WBA5 Reference manual for details. Using the secure alias (0x5..)instead of the non-secure alias (0x4..) for this peripheral results in a SecureFault during kernel init if TrustZone is activated, Zephyr is running as NSPE and RNG is enabled. Signed-off-by: Louis Feller --- dts/arm/st/wba/stm32wba.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi index 0039b1500a1c71..38a76023cfc43a 100644 --- a/dts/arm/st/wba/stm32wba.dtsi +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -447,9 +447,9 @@ status = "disabled"; }; - rng: rng@520c0800 { + rng: rng@420c0800 { compatible = "st,stm32-rng"; - reg = <0x520c0800 0x400>; + reg = <0x420c0800 0x400>; interrupts = <59 0>; clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00040000>, <&rcc STM32_SRC_HSI16 RNG_SEL(2)>; From a27436d8e45aee599d0c9e8db07beaa11e102cb6 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0193/1389] testsuite: interrupt_util: add `trigger_irq` for VPR CLIC Enable triggering IRQs in tests for VPR CLIC. Signed-off-by: Marcin Szymczyk --- subsys/testsuite/include/zephyr/interrupt_util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/testsuite/include/zephyr/interrupt_util.h b/subsys/testsuite/include/zephyr/interrupt_util.h index 0bccd53cc512ee..a3653618d97014 100644 --- a/subsys/testsuite/include/zephyr/interrupt_util.h +++ b/subsys/testsuite/include/zephyr/interrupt_util.h @@ -166,7 +166,7 @@ static inline void trigger_irq(int irq) } #elif defined(CONFIG_RISCV) -#if defined(CONFIG_NUCLEI_ECLIC) +#if defined(CONFIG_NUCLEI_ECLIC) || defined(CONFIG_NRFX_CLIC) void riscv_clic_irq_set_pending(uint32_t irq); static inline void trigger_irq(int irq) { From f9679ea1ca42a469a0bd8ce273cea70686e2d027 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0194/1389] tests: kernel: interrupt: account for custom RISCV IRQ offset `CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET` offsets IRQ in vector table, align test to this functionality. Signed-off-by: Marcin Szymczyk --- tests/kernel/interrupt/src/dynamic_isr.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/kernel/interrupt/src/dynamic_isr.c b/tests/kernel/interrupt/src/dynamic_isr.c index d697fda32e8fc6..1fe6db4b4b2077 100644 --- a/tests/kernel/interrupt/src/dynamic_isr.c +++ b/tests/kernel/interrupt/src/dynamic_isr.c @@ -22,6 +22,12 @@ static void dyn_isr(const void *arg) #if defined(CONFIG_GEN_SW_ISR_TABLE) extern struct _isr_table_entry _sw_isr_table[]; +#if defined(CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET) +#define IRQ_OFFSET CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET +#else +#define IRQ_OFFSET 0 +#endif + /** * @brief Test dynamic ISR installation * @@ -55,8 +61,8 @@ ZTEST(interrupt_feature, test_isr_dynamic) arch_irq_connect_dynamic(i + CONFIG_GEN_IRQ_START_VECTOR, 0, dyn_isr, argval, 0); - zassert_true(_sw_isr_table[i].isr == dyn_isr && - _sw_isr_table[i].arg == argval, + zassert_true(_sw_isr_table[i + IRQ_OFFSET].isr == dyn_isr && + _sw_isr_table[i + IRQ_OFFSET].arg == argval, "dynamic isr did not install successfully"); } #else From 65116f7599606989dcd733b5ae7decbaf36a659f Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0195/1389] tests: kernel: interrupt: nested_irq: support nRF54L15 FLPR CLIC Add support for VPR CLIC to `nested_irq` kernel test. Verified on nRF54L15 FLPR for now. Signed-off-by: Marcin Szymczyk --- tests/kernel/interrupt/src/nested_irq.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/kernel/interrupt/src/nested_irq.c b/tests/kernel/interrupt/src/nested_irq.c index ee48a0366d268c..21fccc5cadfb12 100644 --- a/tests/kernel/interrupt/src/nested_irq.c +++ b/tests/kernel/interrupt/src/nested_irq.c @@ -12,7 +12,7 @@ * Run the nested interrupt test for the supported platforms only. */ #if defined(CONFIG_CPU_CORTEX_M) || defined(CONFIG_ARC) || \ - defined(CONFIG_GIC) + defined(CONFIG_GIC) || defined(CONFIG_NRFX_CLIC) #define TEST_NESTED_ISR #endif @@ -56,6 +56,12 @@ */ #define IRQ0_PRIO IRQ_DEFAULT_PRIORITY #define IRQ1_PRIO 0x0 +#elif defined(CONFIG_SOC_NRF54L15_ENGA_CPUFLPR) +#define IRQ0_LINE 16 +#define IRQ1_LINE 17 + +#define IRQ0_PRIO 1 +#define IRQ1_PRIO 2 #else /* * For all the other platforms, use the last two available IRQ lines for From a272615167cc721a0a01dbf8e904d28de3d177da Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0196/1389] drivers: mipi dbi: smartbond: Add support for PM This commit should add all the functionality needed for the MIPI DBI driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios --- .../renesas/da1469x_dk_pro/Kconfig.defconfig | 9 ++ drivers/mipi_dbi/mipi_dbi_smartbond.c | 87 ++++++------------- 2 files changed, 37 insertions(+), 59 deletions(-) diff --git a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig index 9c447539c3b862..34b4913118160f 100644 --- a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig +++ b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig @@ -34,4 +34,13 @@ config LV_Z_POINTER_INPUT_MSGQ_COUNT endif # INPUT +#if PM || PM_DEVICE + +# Increase stack size to avoid raising usage-fault +# exceptions due to stack overflow. +config IDLE_STACK_SIZE + default 2048 + +#endif # PM || PM_DEVICE + endif # BOARD_DA1469X_DK_PRO diff --git a/drivers/mipi_dbi/mipi_dbi_smartbond.c b/drivers/mipi_dbi/mipi_dbi_smartbond.c index 6187d38d16e8f4..034831075b2e84 100644 --- a/drivers/mipi_dbi/mipi_dbi_smartbond.c +++ b/drivers/mipi_dbi/mipi_dbi_smartbond.c @@ -62,6 +62,10 @@ struct mipi_dbi_smartbond_data { struct k_sem sync_sem; /* Flag indicating whether or not an underflow took place */ volatile bool underflow_flag; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + /* Flag to designate whether or not a frame update is in progress */ + bool is_active; +#endif /* Layer settings */ lcdc_smartbond_layer_cfg layer; }; @@ -80,44 +84,20 @@ struct mipi_dbi_smartbond_config { /* Mark the device is is progress and so it's not allowed to enter the sleep state. */ static void mipi_dbi_pm_get(const struct device *dev) { -#if CONFIG_PM_DEVICE - /* - * By marking the device as busy, PM will not communicate PM events - * to the device via mipi_dbi_smartbond_pm_action. It's OK if PM is - * not used at all. Executing a single frame requires waiting for - * the frame to be completed. As such, the system might enter the idle - * state if no other tasks are pending and for as long as the frame is - * being sent. - * - * XXX: Another option would be to use a flag and mark when the controller - * is in progress so a negative value other than -ENOSYS, -ENOTSUP or - * -EALREADY is returned in mipi_dbi_smartbond_pm_action. Sideffect - * of this approach is that the sleep state will be aborted at all, - * though the system could enter a low-power state, instead (see comment - * below on how to achieve a low-power state). - */ - pm_device_busy_set(dev); -#endif -#if CONFIG_PM - /* - * LCDC controller resides in PD_SYS which is turned off when the system enters - * the extended sleep state. By calling this API, a reference counter is - * incremented, designating that the specific power domain should not be turned off. - * As a result, a low-power state (i.e. ARM WFI) will be selected, instead (when the - * system is idle). - */ - (void)da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS); +#ifdef CONFIG_PM_DEVICE + struct mipi_dbi_smartbond_data *data = dev->data; + + data->is_active = true; #endif } /* Mark that device is inactive and so it's allowed to enter the sleep state */ static void mipi_dbi_pm_put(const struct device *dev) { -#if CONFIG_PM_DEVICE - (void)pm_device_busy_clear(dev); -#endif -#if CONFIG_PM - (void)da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); +#ifdef CONFIG_PM_DEVICE + struct mipi_dbi_smartbond_data *data = dev->data; + + data->is_active = false; #endif } @@ -488,7 +468,7 @@ static int mipi_dbi_smartbond_resume(const struct device *dev) return mipi_dbi_smartbond_configure(dev); } -#ifdef CONFIG_PM_DEVICE +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) static int mipi_dbi_smartbond_suspend(const struct device *dev) { const struct mipi_dbi_smartbond_config *config = dev->config; @@ -508,31 +488,26 @@ static int mipi_dbi_smartbond_suspend(const struct device *dev) static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { - int ret = 0; + /* Initialize with an error code that should abort sleeping */ + int ret = -EBUSY; + struct mipi_dbi_smartbond_data *data = dev->data; switch (action) { case PM_DEVICE_ACTION_SUSPEND: - (void)mipi_dbi_smartbond_suspend(dev); - -#if CONFIG_PM_DEVICE_RUNTIME && CONFIG_PM - da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); -#endif - break; + /* Sleep is only allowed when there are no active LCDC operations */ + if (!data->is_active) { + (void)mipi_dbi_smartbond_suspend(dev); + ret = 0; + } + break; case PM_DEVICE_ACTION_RESUME: - ret = mipi_dbi_smartbond_resume(dev); - -#if CONFIG_PM_DEVICE_RUNTIME && CONFIG_PM + __ASSERT_NO_MSG(!data->is_active); /* - * If resume succeeded, prevent the system from entering the - * extended sleep state (Instead, use __WFI). If not, do not - * as users should not suspend the device and thus releasing - * PD_SYS. + * The resume error code should not be taken into consideration + * by the PM subsystem. */ - if (ret == 0) { - da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS); - } -#endif - break; + ret = mipi_dbi_smartbond_resume(dev); + break; default: return -ENOTSUP; } @@ -570,18 +545,12 @@ static int mipi_dbi_smartbond_init(const struct device *dev) pm_device_init_suspended(dev); ret = pm_device_runtime_enable(dev); - if ((ret < 0) && (ret != -ENOSYS)) { - return ret; - } #else /* Resme if either PM is not used at all or if PM without runtime is used. */ ret = mipi_dbi_smartbond_resume(dev); - if (ret < 0) { - return ret; - } #endif - return 0; + return ret; } static struct mipi_dbi_driver_api mipi_dbi_smartbond_driver_api = { From de9b9cd4727c0b806cd4880d477103a7bd381fd8 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0197/1389] boards: croxel_cx1825: disable CDC-ACM logging by default Disable this explicitly as done for other boards using a USB console by default, prevents a build warning: Signed-off-by: Fabio Baltieri --- boards/croxel/croxel_cx1825/Kconfig.defconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/boards/croxel/croxel_cx1825/Kconfig.defconfig b/boards/croxel/croxel_cx1825/Kconfig.defconfig index 3e83179e5861da..c96e14fea0649c 100644 --- a/boards/croxel/croxel_cx1825/Kconfig.defconfig +++ b/boards/croxel/croxel_cx1825/Kconfig.defconfig @@ -6,4 +6,13 @@ if BOARD_CROXEL_CX1825 config BT_CTLR default BT +if LOG + +# Logger cannot use itself to log +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +endif # LOG + endif # BOARD_CROXEL_CX1825 From 25eb0b05200a523ab986831a6e4efd4211e9a249 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0198/1389] net: ipv6: mld: allow to send unsolicited MLDv2 reports on demand This commit exposes net_ipv6_mld_send_single() function to be used by other modules. Signed-off-by: Konrad Derda --- subsys/net/ip/ipv6.h | 23 +++++++++++++++++++++++ subsys/net/ip/ipv6_mld.c | 8 +++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/subsys/net/ip/ipv6.h b/subsys/net/ip/ipv6.h index 0079b8b48159d8..63f0dc36a09a25 100644 --- a/subsys/net/ip/ipv6.h +++ b/subsys/net/ip/ipv6.h @@ -240,6 +240,29 @@ net_ipv6_mld_leave(struct net_if *iface, const struct in6_addr *addr) } #endif /* CONFIG_NET_IPV6_MLD */ +/** + * @brief Send MLDv2 report message with a single entry. + * + * @param iface Network interface where message is sent + * @param addr Mutlicast group + * @param mode MLDv2 mode (NET_IPV6_MLDv2_MODE_IS_INCLUDE NET_IPV6_MLDv2_MODE_IS_EXCLUDE) + * + * @return Return 0 if leaving is done, <0 otherwise. + */ +#if defined(CONFIG_NET_IPV6_MLD) +int net_ipv6_mld_send_single(struct net_if *iface, const struct in6_addr *addr, uint8_t mode); +#else +static inline int +net_ipv6_mld_send_single(struct net_if *iface, const struct in6_addr *addr, uint8_t mode) +{ + ARG_UNUSED(iface); + ARG_UNUSED(addr); + ARG_UNUSED(mode); + + return -ENOTSUP; +} +#endif /* CONFIG_NET_IPV6_MLD */ + /** * @typedef net_nbr_cb_t * @brief Callback used while iterating over neighbors. diff --git a/subsys/net/ip/ipv6_mld.c b/subsys/net/ip/ipv6_mld.c index f2ae80e0f10553..0ca02027edded8 100644 --- a/subsys/net/ip/ipv6_mld.c +++ b/subsys/net/ip/ipv6_mld.c @@ -145,9 +145,7 @@ static int mld_send(struct net_pkt *pkt) return 0; } -static int mld_send_generic(struct net_if *iface, - const struct in6_addr *addr, - uint8_t mode) +int net_ipv6_mld_send_single(struct net_if *iface, const struct in6_addr *addr, uint8_t mode) { struct net_pkt *pkt; int ret; @@ -206,7 +204,7 @@ int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr) return -ENETDOWN; } - ret = mld_send_generic(iface, addr, NET_IPV6_MLDv2_MODE_IS_EXCLUDE); + ret = net_ipv6_mld_send_single(iface, addr, NET_IPV6_MLDv2_MODE_IS_EXCLUDE); if (ret < 0) { return ret; } @@ -240,7 +238,7 @@ int net_ipv6_mld_leave(struct net_if *iface, const struct in6_addr *addr) return 0; } - ret = mld_send_generic(iface, addr, NET_IPV6_MLDv2_MODE_IS_INCLUDE); + ret = net_ipv6_mld_send_single(iface, addr, NET_IPV6_MLDv2_MODE_IS_INCLUDE); if (ret < 0) { return ret; } From 9c2d5efcf3869317bf33007bb7ef6bee27b2cd48 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0199/1389] net: ipv6: mld: add option to include multicast routes in MLDv2 reports This commit introduces a new option CONFIG_NET_MCAST_ROUTE_MLD_REPORTS which appends multiacst routes to MLDv2 reports. These records are intended to inform reports' recipients about potential listeners on the other interfaces. Signed-off-by: Konrad Derda --- subsys/net/ip/Kconfig | 8 ++++ subsys/net/ip/ipv6_mld.c | 87 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index 4c44d59d4cb059..b8907125109a42 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -435,6 +435,14 @@ config NET_MCAST_ROUTE_MAX_IFACES Determines how many network interfaces can be assigned to a single multicast route entry. +config NET_MCAST_ROUTE_MLD_REPORTS + bool "Report multicast routes as a part of MLDv2 reports" + depends on NET_ROUTE_MCAST + depends on NET_IPV6_MLD + help + Determines whether a multicast route entry should be advertised + in MLDv2 reports. + source "subsys/net/ip/Kconfig.tcp" config NET_TEST_PROTOCOL diff --git a/subsys/net/ip/ipv6_mld.c b/subsys/net/ip/ipv6_mld.c index 0ca02027edded8..25f7b42bdafb9f 100644 --- a/subsys/net/ip/ipv6_mld.c +++ b/subsys/net/ip/ipv6_mld.c @@ -34,9 +34,18 @@ LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL); #define MLDv2_MCAST_RECORD_LEN sizeof(struct net_icmpv6_mld_mcast_record) #define IPV6_OPT_HDR_ROUTER_ALERT_LEN 8 +#define MLDV2_REPORT_RESERVED_BYTES 2 #define MLDv2_LEN (MLDv2_MCAST_RECORD_LEN + sizeof(struct in6_addr)) +/* Internal structure used for appending multicast routes to MLDv2 reports */ +struct mcast_route_appending_info { + int status; + struct net_pkt *pkt; + struct net_if *iface; + size_t skipped; +}; + static int mld_create(struct net_pkt *pkt, const struct in6_addr *addr, uint8_t record_type, @@ -145,6 +154,37 @@ static int mld_send(struct net_pkt *pkt) return 0; } +#if defined(CONFIG_NET_MCAST_ROUTE_MLD_REPORTS) +static void count_mcast_routes(struct net_route_entry_mcast *entry, void *user_data) +{ + (*((int *)user_data))++; +} + +static void append_mcast_routes(struct net_route_entry_mcast *entry, void *user_data) +{ + struct mcast_route_appending_info *info = (struct mcast_route_appending_info *)user_data; + struct net_if_mcast_addr *mcasts = info->iface->config.ip.ipv6->mcast; + + if (info->status != 0 || entry->prefix_len != 128) { + return; + } + + for (int i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) { + if (!mcasts[i].is_used || !mcasts[i].is_joined) { + continue; + } + + if (net_ipv6_addr_cmp(&entry->group, &mcasts[i].address.in6_addr)) { + /* Address was already added to the report */ + info->skipped++; + return; + } + } + + info->status = mld_create(info->pkt, &entry->group, NET_IPV6_MLDv2_MODE_IS_EXCLUDE, 0); +} +#endif + int net_ipv6_mld_send_single(struct net_if *iface, const struct in6_addr *addr, uint8_t mode) { struct net_pkt *pkt; @@ -269,6 +309,14 @@ static int send_mld_report(struct net_if *iface) count++; } +#if defined(CONFIG_NET_MCAST_ROUTE_MLD_REPORTS) + /* Increase number of slots by a number of multicast routes that + * can be later added to the report. Checking for duplicates is done + * while appending an entry. + */ + net_route_mcast_foreach(count_mcast_routes, NULL, (void *)&count); +#endif + pkt = net_pkt_alloc_with_buffer(iface, IPV6_OPT_HDR_ROUTER_ALERT_LEN + NET_ICMPV6_UNUSED_LEN + count * MLDv2_MCAST_RECORD_LEN, @@ -295,6 +343,45 @@ static int send_mld_report(struct net_if *iface) } } +#if defined(CONFIG_NET_MCAST_ROUTE_MLD_REPORTS) + /* Append information about multicast routes as packets will be + * forwarded to these interfaces on reception. + */ + struct mcast_route_appending_info info; + + info.status = 0; + info.pkt = pkt; + info.iface = iface; + info.skipped = 0; + + net_route_mcast_foreach(append_mcast_routes, NULL, &info); + + ret = info.status; + if (ret < 0) { + goto drop; + } + + /* We may have skipped duplicated addresses that we reserved space for, + * modify number of records. + */ + if (info.skipped) { + net_pkt_cursor_init(pkt); + net_pkt_set_overwrite(pkt, true); + + net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt) + + sizeof(struct net_icmp_hdr) + MLDV2_REPORT_RESERVED_BYTES); + + count -= info.skipped; + + ret = net_pkt_write_be16(pkt, count); + if (ret < 0) { + goto drop; + } + + net_pkt_remove_tail(pkt, info.skipped * sizeof(struct net_icmpv6_mld_mcast_record)); + } +#endif + ret = mld_send(pkt); if (ret < 0) { goto drop; From cfc7bb541befc8b412de1e38a60a182af9aa1277 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:34 +0200 Subject: [PATCH 0200/1389] net: ipv6: mcast_routing: send MLDv2 reports on changes This commit adds transmission of MLDv2 reports whenever a multicast routing entry is added or removed when suitable (it checks if the given interface itself has joined the group). Signed-off-by: Konrad Derda --- subsys/net/ip/route.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/subsys/net/ip/route.c b/subsys/net/ip/route.c index 184b538b85a751..d2012a17b4c494 100644 --- a/subsys/net/ip/route.c +++ b/subsys/net/ip/route.c @@ -777,6 +777,43 @@ bool net_route_mcast_iface_del(struct net_route_entry_mcast *entry, return true; } +#if defined(CONFIG_NET_MCAST_ROUTE_MLD_REPORTS) +struct mcast_route_mld_event { + struct in6_addr *addr; + uint8_t mode; +}; + +static void send_mld_event(struct net_if *iface, void *user_data) +{ + struct mcast_route_mld_event *event = (struct mcast_route_mld_event *)user_data; + + /* Do not send events for ifaces without IPv6, without MLD, already or still in + * a given group + */ + if (!iface->config.ip.ipv6 || net_if_flag_is_set(iface, NET_IF_IPV6_NO_MLD) || + net_if_ipv6_maddr_lookup(event->addr, &iface)) { + return; + } + + net_ipv6_mld_send_single(iface, event->addr, event->mode); +} + +static void propagate_mld_event(struct net_route_entry_mcast *route, bool route_added) +{ + struct mcast_route_mld_event mld_event; + + /* Apply only for complete addresses */ + if (route->prefix_len == 128) { + mld_event.addr = &route->group; + mld_event.mode = route_added ? NET_IPV6_MLDv2_MODE_IS_EXCLUDE : + NET_IPV6_MLDv2_MODE_IS_INCLUDE; + + net_if_foreach(send_mld_event, &mld_event); + } +} +#else +#define propagate_mld_event(...) +#endif /* CONFIG_NET_MCAST_ROUTE_MLD_REPORTS */ int net_route_mcast_forward_packet(struct net_pkt *pkt, const struct net_ipv6_hdr *hdr) @@ -869,6 +906,8 @@ struct net_route_entry_mcast *net_route_mcast_add(struct net_if *iface, route->ifaces[0] = iface; route->is_used = true; + propagate_mld_event(route, true); + net_ipv6_nbr_unlock(); return route; } @@ -889,6 +928,8 @@ bool net_route_mcast_del(struct net_route_entry_mcast *route) "Multicast route %p to %s was already removed", route, net_sprint_ipv6_addr(&route->group)); + propagate_mld_event(route, false); + route->is_used = false; return true; From adc44ea28a22a3a3eb018591fc698f021253a585 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0201/1389] tests: net: mld: add tests for multicast routes in MLDv2 reports This commit introduces a new test case for veryfing that addition and deletion of multicast routing entries emit MLDv2 reports when needed and if multicast routing entries are appended to MLDv2 records properly. Signed-off-by: Konrad Derda --- tests/net/mld/prj.conf | 3 +- tests/net/mld/src/main.c | 253 ++++++++++++++++++++++++++++++++++++ tests/net/mld/testcase.yaml | 5 + 3 files changed, 260 insertions(+), 1 deletion(-) diff --git a/tests/net/mld/prj.conf b/tests/net/mld/prj.conf index 06e5cd0d23cd0b..a0e0020d729efa 100644 --- a/tests/net/mld/prj.conf +++ b/tests/net/mld/prj.conf @@ -21,5 +21,6 @@ CONFIG_NET_BUF_TX_COUNT=20 CONFIG_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4 -CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=8 CONFIG_NET_SOCKETS=y +CONFIG_NET_IF_MAX_IPV6_COUNT=2 diff --git a/tests/net/mld/src/main.c b/tests/net/mld/src/main.c index 9ca53f6bf3195b..c780d20d8e516a 100644 --- a/tests/net/mld/src/main.c +++ b/tests/net/mld/src/main.c @@ -32,8 +32,10 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #include "icmpv6.h" #include "ipv6.h" +#include "route.h" #define THREAD_SLEEP 50 /* ms */ +#define MLD_REPORT_ADDR_COUNT 8 #define NET_LOG_ENABLED 1 #include "net_private.h" @@ -44,6 +46,25 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #define DBG(fmt, ...) #endif +struct mld_report_mcast_record { + uint8_t record_type; + uint8_t aux_data_len; + uint16_t num_of_sources; + struct in6_addr mcast_addr; +} __packed; + +struct mld_report_info { + uint16_t records_count; + struct mld_report_mcast_record records[MLD_REPORT_ADDR_COUNT]; +}; + +typedef void (*mld_report_callback)(struct net_pkt *pkt, void *user_data); + +struct mld_report_handler { + mld_report_callback fn; + void *user_data; +}; + static struct in6_addr my_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; static struct in6_addr peer_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, @@ -59,6 +80,9 @@ static bool is_leave_msg_ok; static bool is_query_received; static bool is_report_sent; static bool ignore_already; + +static struct mld_report_handler *report_handler; + K_SEM_DEFINE(wait_data, 0, UINT_MAX); #define WAIT_TIME 500 @@ -130,19 +154,47 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt) is_leave_msg_ok = true; is_report_sent = true; + if (report_handler) { + report_handler->fn(pkt, report_handler->user_data); + } + k_sem_give(&wait_data); } return 0; } +static int tester_null_send(const struct device *dev, struct net_pkt *pkt) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pkt); + + return 0; +} + struct net_test_mld net_test_data; +struct net_test_mld net_test_null_data; static struct dummy_api net_test_if_api = { .iface_api.init = net_test_iface_init, .send = tester_send, }; +static void init_null_iface(struct net_if *iface) +{ + struct net_test_mld *context = iface->if_dev->dev->data; + + memset(&context->mac_addr, 0, sizeof(context->mac_addr)); + + net_if_set_link_addr(iface, context->mac_addr, sizeof(struct net_eth_addr), + NET_LINK_ETHERNET); +} + +static struct dummy_api net_test_null_if_api = { + .iface_api.init = init_null_iface, + .send = tester_null_send, +}; + #define _ETH_L2_LAYER DUMMY_L2 #define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2) @@ -152,6 +204,11 @@ NET_DEVICE_INIT(net_test_mld, "net_test_mld", &net_test_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE, 127); +/* Interface without a device or API, only for usage of `struct net_if` */ +NET_DEVICE_INIT(net_test_null_iface, "net_test_null_iface", net_test_dev_init, NULL, + &net_test_null_data, NULL, 99, &net_test_null_if_api, _ETH_L2_LAYER, + _ETH_L2_CTX_TYPE, 127); + static void group_joined(struct net_mgmt_event_callback *cb, uint32_t nm_event, struct net_if *iface) { @@ -205,6 +262,8 @@ static void *test_mld_setup(void) { struct net_if_addr *ifaddr; + report_handler = NULL; + setup_mgmt_events(); net_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); @@ -604,6 +663,200 @@ ZTEST(net_mld_test_suite, test_no_mld_flag) net_if_flag_clear(net_iface, NET_IF_IPV6_NO_MLD); } +static void handle_mld_report(struct net_pkt *pkt, void *user_data) +{ + struct mld_report_info *info = (struct mld_report_info *)user_data; + uint16_t res_bytes; + + net_pkt_set_overwrite(pkt, true); + net_pkt_skip(pkt, sizeof(struct net_icmp_hdr)); + + zassert_ok(net_pkt_read_be16(pkt, &res_bytes), "Failed to read reserved bytes"); + zassert_equal(0, res_bytes, "Reserved bytes must be zeroed"); + + zassert_ok(net_pkt_read_be16(pkt, &info->records_count), "Failed to read addr count"); + zexpect_between_inclusive(info->records_count, 0, MLD_REPORT_ADDR_COUNT, + "Cannot decode all addresses"); + + for (size_t i = 0; i < info->records_count; ++i) { + net_pkt_read(pkt, &info->records[i], sizeof(struct mld_report_mcast_record)); + } +} + +static size_t get_mcast_addr_count(struct net_if *iface) +{ + size_t ret = 0; + + ARRAY_FOR_EACH_PTR(iface->config.ip.ipv6->mcast, mcast_addr) { + if (mcast_addr->is_used) { + ret++; + } + } + + return ret; +} + +static void add_mcast_route_and_verify(struct net_if *iface, struct in6_addr *addr, + struct mld_report_info *info) +{ + k_sem_reset(&wait_data); + + zassert_not_null(net_route_mcast_add(iface, addr, 128), "Failed to add multicast route"); + + k_msleep(THREAD_SLEEP); + + zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report"); + + zassert_equal(info->records_count, 1, "Invalid number of reported addresses"); + zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_MODE_IS_EXCLUDE, + "Invalid MLDv2 record type"); + zassert_mem_equal(&info->records[0].mcast_addr, addr, + sizeof(struct in6_addr), "Invalid reported address"); +} + +static void del_mcast_route_and_verify(struct net_if *iface, struct in6_addr *addr, + struct mld_report_info *info) +{ + struct net_route_entry_mcast *entry; + + k_sem_reset(&wait_data); + + entry = net_route_mcast_lookup(addr); + + zassert_not_null(entry, "Could not find the multicast route entry"); + zassert_true(net_route_mcast_del(entry), "Failed to delete a route"); + + k_msleep(THREAD_SLEEP); + + zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report"); + + zassert_equal(info->records_count, 1, "Invalid number of reported addresses"); + zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_MODE_IS_INCLUDE, + "Invalid MLDv2 record type"); + zassert_mem_equal(&info->records[0].mcast_addr, addr, + sizeof(struct in6_addr), "Invalid reported address"); +} + +static void verify_mcast_routes_in_mld(struct mld_report_info *info) +{ + struct net_if *dummy_iface = net_if_get_by_index(net_if_get_by_name("dummy0")); + struct net_if *null_iface = net_if_get_by_index(net_if_get_by_name("dummy1")); + struct in6_addr site_local_mcast_addr_abcd; + struct in6_addr site_local_mcast_addr_beef; + struct in6_addr site_local_mcast_addr_cafe; + + zassert_not_null(dummy_iface, "Invalid dummy iface"); + zassert_not_null(null_iface, "Invalid null iface"); + + net_if_flag_set(null_iface, NET_IF_FORWARD_MULTICASTS); + + net_ipv6_addr_create(&site_local_mcast_addr_abcd, 0xff05, 0, 0, 0, 0, 0, 0, 0xabcd); + net_ipv6_addr_create(&site_local_mcast_addr_beef, 0xff05, 0, 0, 0, 0, 0, 0, 0xbeef); + net_ipv6_addr_create(&site_local_mcast_addr_cafe, 0xff05, 0, 0, 0, 0, 0, 0, 0xcafe); + + /* Next steps: verify that adding a multicast routes to a complete IPv6 address emits + * MLDv2 reports with a single entries. + */ + add_mcast_route_and_verify(null_iface, &site_local_mcast_addr_abcd, info); + add_mcast_route_and_verify(null_iface, &site_local_mcast_addr_beef, info); + + /* Next steps: verify that report is not sent to an iface if it has already joined + * the group. + */ + zassert_ok(net_ipv6_mld_join(dummy_iface, &site_local_mcast_addr_cafe), + "Failed to join a group"); + + k_msleep(THREAD_SLEEP); + + k_sem_reset(&wait_data); + + zassert_not_null(net_route_mcast_add(null_iface, &site_local_mcast_addr_cafe, 128), + "Failed to add multicast route"); + + k_msleep(THREAD_SLEEP); + + zassert_equal(-EAGAIN, k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Expected a timeout"); + + k_sem_reset(&wait_data); + + /* Verify that multicast routes can be found in MLDv2 report and that there are + * no duplicates. + */ + send_query(dummy_iface); + + k_msleep(THREAD_SLEEP); + + zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Expected a report"); + + /* Expect 2 additional addresses as 3rd is a duplicate of iface's multicast address */ + zassert_equal(info->records_count, get_mcast_addr_count(dummy_iface) + 2, + "Different number of reported addresses"); + + /* Next steps: Remove routes and expect MLDv2 reports as these addresses are not + * used by the interface. + */ + del_mcast_route_and_verify(dummy_iface, &site_local_mcast_addr_abcd, info); + del_mcast_route_and_verify(dummy_iface, &site_local_mcast_addr_beef, info); + + /* Next steps: Remove the last route and verify that report is NOT sent as this address + * is joined by the interface itself. + */ + k_sem_reset(&wait_data); + + zassert_true(net_route_mcast_del(net_route_mcast_lookup(&site_local_mcast_addr_cafe)), + "Failed to cleanup route to ff05::cafe"); + + k_msleep(THREAD_SLEEP); + + zassert_equal(-EAGAIN, k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Expected a timeout"); + + /* Finalize cleanup */ + net_ipv6_mld_leave(dummy_iface, &site_local_mcast_addr_cafe); +} + +ZTEST(net_mld_test_suite, test_mcast_routes_in_mld) +{ + struct mld_report_info info; + struct mld_report_handler handler = { .fn = handle_mld_report, .user_data = &info}; + struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); + char str[INET6_ADDRSTRLEN], *addr_str; + + memset(&info, 0, sizeof(info)); + + join_mldv2_capable_routers_group(); + + /* Enable report handler */ + report_handler = &handler; + + k_msleep(THREAD_SLEEP); + + k_sem_reset(&wait_data); + + send_query(iface); + + k_msleep(THREAD_SLEEP); + + zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report"); + + for (int i = 0; i < info.records_count; ++i) { + addr_str = zsock_inet_ntop(AF_INET6, &info.records[i].mcast_addr, str, sizeof(str)); + } + + /* 1. Expect that report contains all iface's multicast addressses and no route */ + zassert_equal(info.records_count, get_mcast_addr_count(iface), + "Different number of reported addresses"); + + /* 2. If CONFIG_NET_MCAST_ROUTE_MLD_REPORTS is enabled check that funtionality works */ + if (IS_ENABLED(CONFIG_NET_MCAST_ROUTE_MLD_REPORTS)) { + verify_mcast_routes_in_mld(&info); + } + + /* Disable report handler */ + report_handler = NULL; + + leave_mldv2_capable_routers_group(); +} + static void socket_group_with_index(const struct in6_addr *local_addr, bool do_join) { struct ipv6_mreq mreq = { 0 }; diff --git a/tests/net/mld/testcase.yaml b/tests/net/mld/testcase.yaml index 5367b6691836cf..8bd91eeff3c7e0 100644 --- a/tests/net/mld/testcase.yaml +++ b/tests/net/mld/testcase.yaml @@ -10,3 +10,8 @@ tests: net.mld.preempt: extra_configs: - CONFIG_NET_TC_THREAD_PREEMPTIVE=y + net.mld.mcast_routes: + extra_configs: + - CONFIG_NET_ROUTE_MCAST=y + - CONFIG_NET_MAX_MCAST_ROUTES=5 + - CONFIG_NET_MCAST_ROUTE_MLD_REPORTS=y From afab8ebdc0b16009fd9da286f4c1c31db09234f6 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0202/1389] net: ipv6: Generate an event for deprecated address If IPv6 address expires and moves to deprecated state, then send a mgmt event so that listeners can act on it. One such action is to close a socket bound to that source address so that the address can be released. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_event.h | 4 ++++ subsys/net/lib/shell/events.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index 881bb8dc2769d6..6198fc28bfbb3a 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -81,6 +81,7 @@ enum net_event_ipv6_cmd { NET_EVENT_IPV6_CMD_DHCP_START, NET_EVENT_IPV6_CMD_DHCP_BOUND, NET_EVENT_IPV6_CMD_DHCP_STOP, + NET_EVENT_IPV6_CMD_ADDR_DEPRECATED, }; #define NET_EVENT_IPV6_ADDR_ADD \ @@ -140,6 +141,9 @@ enum net_event_ipv6_cmd { #define NET_EVENT_IPV6_DHCP_STOP \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_STOP) +#define NET_EVENT_IPV6_ADDR_DEPRECATED \ + (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEPRECATED) + /* IPv4 Events*/ #define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 #define _NET_IPV4_CORE_CODE 0x004 diff --git a/subsys/net/lib/shell/events.c b/subsys/net/lib/shell/events.c index 44037a76f3f67a..27bd5a46e98f16 100644 --- a/subsys/net/lib/shell/events.c +++ b/subsys/net/lib/shell/events.c @@ -98,6 +98,12 @@ static char *get_l3_desc(struct event_msg *msg, info = net_addr_ntop(AF_INET6, msg->data, extra_info, extra_info_len); break; + case NET_EVENT_IPV6_ADDR_DEPRECATED: + *desc = "IPv6 address"; + *desc2 = "deprecated"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; case NET_EVENT_IPV6_ADDR_DEL: *desc = "IPv6 address"; *desc2 = "del"; From 5aac16bcd6074252b5853230b53d0e3cc7722811 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0203/1389] net: ipv6: Initial support for privacy extension This creates support for IPv6 privacy extensions which is described in RFC 8981. This will also add API that can be used to add IPv6 prefixes to a allow or deny list privacy extension filter. The code will create temporary IPv6 addresses from prefixes that are advertised by Router Advertisement messages. The temporary IPv6 addresses are then expired according to lifetime and removed. Fixes #9349 Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_if.h | 50 ++- include/zephyr/net/net_ip.h | 41 ++ subsys/net/ip/CMakeLists.txt | 4 +- subsys/net/ip/Kconfig.ipv6 | 64 +++ subsys/net/ip/ipv6.h | 89 +++++ subsys/net/ip/ipv6_nbr.c | 23 +- subsys/net/ip/ipv6_pe.c | 727 +++++++++++++++++++++++++++++++++++ subsys/net/ip/net_if.c | 35 +- subsys/net/ip/net_private.h | 6 + 9 files changed, 1025 insertions(+), 14 deletions(-) create mode 100644 subsys/net/ip/ipv6_pe.c diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 03a936626d1dd3..8bf41153d77d32 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -68,12 +68,31 @@ struct net_if_addr { /** What is the current state of the address */ enum net_addr_state addr_state; -#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6) +#if defined(CONFIG_NET_NATIVE_IPV6) +#if defined(CONFIG_NET_IPV6_PE) + /** Address creation time. This is used to determine if the maximum + * lifetime for this address is reached or not. The value is in seconds. + */ + uint32_t addr_create_time; + + /** Preferred lifetime for the address in seconds. + */ + uint32_t addr_preferred_lifetime; + + /** Address timeout value. This is only used if DAD needs to be redone + * for this address because of earlier DAD failure. This value is in + * seconds. + */ + int32_t addr_timeout; +#endif + +#if defined(CONFIG_NET_IPV6_DAD) /** How many times we have done DAD */ uint8_t dad_count; /* What interface the DAD is running */ uint8_t ifindex; #endif +#endif /* CONFIG_NET_NATIVE_IPV6 */ /** Is the IP address valid forever */ uint8_t is_infinite : 1; @@ -84,7 +103,12 @@ struct net_if_addr { /** Is this IP address usage limited to the subnet (mesh) or not */ uint8_t is_mesh_local : 1; - uint8_t _unused : 5; + /** Is this IP address temporary and generated for example by + * IPv6 privacy extension (RFC 8981) + */ + uint8_t is_temporary : 1; + + uint8_t _unused : 4; }; /** @@ -279,6 +303,15 @@ struct net_if_ipv6 { /** Retransmit timer (RFC 4861, page 52) */ uint32_t retrans_timer; + +#if defined(CONFIG_NET_IPV6_PE) + /** Privacy extension DESYNC_FACTOR value from RFC 8981 ch 3.4. + * "DESYNC_FACTOR is a random value within the range 0 - MAX_DESYNC_FACTOR. + * It is computed every time a temporary address is created. + */ + uint32_t desync_factor; +#endif /* CONFIG_NET_IPV6_PE */ + #if defined(CONFIG_NET_IPV6_ND) && defined(CONFIG_NET_NATIVE_IPV6) /** Router solicitation timer node */ sys_snode_t rs_node; @@ -653,6 +686,19 @@ struct net_if { struct k_mutex lock; struct k_mutex tx_lock; + + /** Network interface specific flags */ + /** Enable IPv6 privacy extension (RFC 8981), this is enabled + * by default if PE support is enabled in configuration. + */ + uint8_t pe_enabled : 1; + + /* If PE is enabled, then this tells whether public addresses + * are preferred over temporary ones for this interface. + */ + uint8_t pe_prefer_public : 1; + + uint8_t _unused : 6; }; static inline void net_if_lock(struct net_if *iface) diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index 02bbd9edb2cbc3..cf5bc56f1da432 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -1709,6 +1709,47 @@ static inline uint8_t net_priority2vlan(enum net_priority priority) */ const char *net_family2str(sa_family_t family); +/** + * @brief Add IPv6 prefix as a privacy extension filter. + * + * @details Note that the filters can either allow or deny listing. + * + * @param addr IPv6 prefix + * @param is_denylist Tells if this filter is for allowing or denying listing. + * + * @return 0 if ok, <0 if error + */ +#if defined(CONFIG_NET_IPV6_PE) +int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_denylist); +#else +static inline int net_ipv6_pe_add_filter(struct in6_addr *addr, + bool is_denylist) +{ + ARG_UNUSED(addr); + ARG_UNUSED(is_denylist); + + return -ENOTSUP; +} +#endif /* CONFIG_NET_IPV6_PE */ + +/** + * @brief Delete IPv6 prefix from privacy extension filter list. + * + * @param addr IPv6 prefix + * + * @return 0 if ok, <0 if error + */ +#if defined(CONFIG_NET_IPV6_PE) +int net_ipv6_pe_del_filter(struct in6_addr *addr); +#else +static inline int net_ipv6_pe_del_filter(struct in6_addr *addr) +{ + ARG_UNUSED(addr); + + return -ENOTSUP; +} +#endif /* CONFIG_NET_IPV6_PE */ + #ifdef __cplusplus } #endif diff --git a/subsys/net/ip/CMakeLists.txt b/subsys/net/ip/CMakeLists.txt index dd15c21906d6af..abb26e3dafe0cd 100644 --- a/subsys/net/ip/CMakeLists.txt +++ b/subsys/net/ip/CMakeLists.txt @@ -37,8 +37,10 @@ zephyr_library_sources_ifdef(CONFIG_NET_IPV4_IGMP igmp.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV6 icmpv6.c nbr.c ipv6.c ipv6_nbr.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV6_MLD ipv6_mld.c) +zephyr_library_sources_ifdef(CONFIG_NET_IPV6_PE ipv6_pe.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV6_FRAGMENT ipv6_fragment.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV4_FRAGMENT ipv4_fragment.c) +zephyr_library_sources_ifdef(CONFIG_NET_MGMT_EVENT net_mgmt.c) zephyr_library_sources_ifdef(CONFIG_NET_ROUTE route.c) zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS net_stats.c) zephyr_library_sources_ifdef(CONFIG_NET_TCP tcp.c) @@ -51,7 +53,7 @@ zephyr_library_sources_ifdef(CONFIG_NET_CONNECTION_SOCKETS connection.c) zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_PACKET packet_socket.c) zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_CAN canbus_socket.c) -if(CONFIG_NET_TCP_ISN_RFC6528) +if(CONFIG_NET_TCP_ISN_RFC6528 OR CONFIG_NET_IPV6_PE) zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) endif() endif() diff --git a/subsys/net/ip/Kconfig.ipv6 b/subsys/net/ip/Kconfig.ipv6 index c321bfc9b659d1..9d6079a2803376 100644 --- a/subsys/net/ip/Kconfig.ipv6 +++ b/subsys/net/ip/Kconfig.ipv6 @@ -165,6 +165,64 @@ config NET_IPV6_RA_RDNSS Support Router Advertisement Recursive DNS Server option. See RFC 6106 for details. The value depends on your network needs. +config NET_IPV6_PE + bool "Privacy extension (RFC 8981) support [EXPERIMENTAL]" + select MBEDTLS + select EXPERIMENTAL + select NET_MGMT + select NET_MGMT_EVENT + select NET_MGMT_EVENT_INFO + help + This enables IPv6 privacy extension (RFC 8981) support. + The interface identifier is randomized and SLAAC addresses + generated from it will expire. This requires that applications are + prepared to use new IPv6 addresses when old ones will expire. + Note that you should make sure that the value of config option + CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT should be large enough so that + two PE generated IPv6 addresses can be added to the network interface + at the same time. + +if NET_IPV6_PE + +config NET_IPV6_PE_FILTER_PREFIX_COUNT + int "Size of the IPv6 prefix filter list" + default 0 + help + Size of the allow/deny filter list of IPv6 prefixes. User can + set filters at runtime and it is possible to enable or disable + privacy extension support according to this filter list. + By default no filters are enabled. + +config NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES + bool "Prefer public preferred address over temporary one" + help + Prefer public addresses over temporary addresses. + +config NET_IPV6_PE_TEMP_VALID_LIFETIME + int "Max lifetime for temporary address (in minutes)" + default 1800 + help + No temporary address should ever remain valid for longer than this + value. The value is in minutes. Default value is 2 days (2*24*60). + +config NET_IPV6_PE_TEMP_PREFERRED_LIFETIME + int "Max preferred lifetime for temporary address (in minutes)" + default 1440 + help + No temporary address should ever remain preferred for longer than this + value. The value is in minutes. Default value is 1 day (24*60). + +config NET_IPV6_PE_TEMP_IDGEN_RETRIES + int "Max amount of failed DAD attempts" + default 3 + help + The node MUST perform duplicate address detection (DAD) on the + generated temporary address. If after TEMP_IDGEN_RETRIES consecutive + attempts no non-unique address was generated then there will be no + attempt to generate temporary addresses for that interface. + +endif + config NET_6LO bool "6lowpan IPv6 Compression library" default y if NET_L2_IEEE802154 @@ -211,6 +269,12 @@ module-str = Log level for IPv6 Neighbor Discovery module-help = Enables IPv6 Neighbor Discovery code to output debug messages. source "subsys/net/Kconfig.template.log_config.net" +module = NET_IPV6_PE +module-dep = NET_LOG +module-str = Log level for IPv6 Privacy Extension +module-help = Enables IPv6 Privacy Extension code to output debug messages. +source "subsys/net/Kconfig.template.log_config.net" + module = NET_ICMPV6 module-dep = NET_LOG module-str = Log level for ICMPv6 diff --git a/subsys/net/ip/ipv6.h b/subsys/net/ip/ipv6.h index 63f0dc36a09a25..3319582ce19e38 100644 --- a/subsys/net/ip/ipv6.h +++ b/subsys/net/ip/ipv6.h @@ -618,5 +618,94 @@ static inline void net_ipv6_set_ecn(uint8_t *tc, uint8_t ecn) *tc |= ecn & NET_IPV6_ECN_MASK; } +/** + * @brief Start IPv6 privacy extension procedure. + * + * @param iface Interface to use. + * @param prefix IPv6 prefix to use. + * @param vlifetime Lifetime of this IPv6 prefix (in seconds). + * @param preferred_lifetime Preferred lifetime of this IPv6 prefix (in seconds) + */ +#if defined(CONFIG_NET_IPV6_PE) +void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix, + uint32_t vlifetime, uint32_t preferred_lifetime); + +#else +static inline void net_ipv6_pe_start(struct net_if *iface, + const struct in6_addr *prefix, + uint32_t vlifetime, + uint32_t preferred_lifetime) +{ + ARG_UNUSED(iface); + ARG_UNUSED(prefix); + ARG_UNUSED(vlifetime); + ARG_UNUSED(preferred_lifetime); +} +#endif /* CONFIG_NET_IPV6_PE */ + +/** + * @brief Check if maximum number of Duplicate Address Detection (DAD) requests + * have been done. + * + * @param count Number of DAD requests done. + * + * @return Return True if DAD can continue, False if max amount of DAD + * requests have been done. + */ +#if defined(CONFIG_NET_IPV6_PE) +bool net_ipv6_pe_check_dad(int count); +#else +static inline bool net_ipv6_pe_check_dad(int count) +{ + ARG_UNUSED(count); + + return false; +} +#endif /* CONFIG_NET_IPV6_PE */ + +/** + * @brief Initialize IPv6 privacy extension support for a network interface. + * + * @param iface Network interface + * + * @return Return 0 if ok or <0 if there is an error. + */ +#if defined(CONFIG_NET_IPV6_PE) +int net_ipv6_pe_init(struct net_if *iface); +#else +static inline int net_ipv6_pe_init(struct net_if *iface) +{ + iface->pe_enabled = false; + iface->pe_prefer_public = false; + + return 0; +} +#endif /* CONFIG_NET_IPV6_PE */ + +typedef void (*net_ipv6_pe_filter_cb_t)(struct in6_addr *prefix, + bool is_blacklist, + void *user_data); + +/** + * @brief Go through all the IPv6 privacy extension filters and call callback + * for each IPv6 prefix. + * + * @param cb User supplied callback function to call. + * @param user_data User specified data. + * + * @return Total number of filters found. + */ +#if defined(CONFIG_NET_IPV6_PE) +int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb, void *user_data); +#else +static inline int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb, + void *user_data) +{ + ARG_UNUSED(cb); + ARG_UNUSED(user_data); + + return 0; +} +#endif #endif /* __IPV6_H */ diff --git a/subsys/net/ip/ipv6_nbr.c b/subsys/net/ip/ipv6_nbr.c index 34979eeb87d701..aea731dade8f3e 100644 --- a/subsys/net/ip/ipv6_nbr.c +++ b/subsys/net/ip/ipv6_nbr.c @@ -2231,6 +2231,7 @@ static inline uint32_t remaining_lifetime(struct net_if_addr *ifaddr) static inline void handle_prefix_autonomous(struct net_pkt *pkt, struct net_icmpv6_nd_opt_prefix_info *prefix_info) { + struct net_if *iface = net_pkt_iface(pkt); struct in6_addr addr = { }; struct net_if_addr *ifaddr; @@ -2238,9 +2239,8 @@ static inline void handle_prefix_autonomous(struct net_pkt *pkt, * setup link local address, and then copy prefix over first 8 * bytes of that address. */ - net_ipv6_addr_create_iid(&addr, - net_if_get_link_addr(net_pkt_iface(pkt))); - memcpy(&addr, prefix_info->prefix, sizeof(prefix_info->prefix) / 2); + net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface)); + memcpy(&addr, prefix_info->prefix, sizeof(struct in6_addr) / 2); ifaddr = net_if_ipv6_addr_lookup(&addr, NULL); if (ifaddr && ifaddr->addr_type == NET_ADDR_AUTOCONF) { @@ -2274,14 +2274,23 @@ static inline void handle_prefix_autonomous(struct net_pkt *pkt, } else { if (prefix_info->valid_lifetime == NET_IPV6_ND_INFINITE_LIFETIME) { - net_if_ipv6_addr_add(net_pkt_iface(pkt), - &addr, NET_ADDR_AUTOCONF, 0); + net_if_ipv6_addr_add(iface, &addr, + NET_ADDR_AUTOCONF, 0); } else { - net_if_ipv6_addr_add(net_pkt_iface(pkt), - &addr, NET_ADDR_AUTOCONF, + net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF, prefix_info->valid_lifetime); } } + + /* If privacy extensions are enabled, then start the procedure for that + * too. + */ + if (IS_ENABLED(CONFIG_NET_IPV6_PE) && iface->pe_enabled) { + net_ipv6_pe_start(iface, + (const struct in6_addr *)prefix_info->prefix, + prefix_info->valid_lifetime, + prefix_info->preferred_lifetime); + } } static inline bool handle_ra_prefix(struct net_pkt *pkt) diff --git a/subsys/net/ip/ipv6_pe.c b/subsys/net/ip/ipv6_pe.c new file mode 100644 index 00000000000000..a2de2ddc786361 --- /dev/null +++ b/subsys/net/ip/ipv6_pe.c @@ -0,0 +1,727 @@ +/** @file + * @brief IPv6 privacy extension (RFC 8981) + */ + +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(net_ipv6_pe, CONFIG_NET_IPV6_PE_LOG_LEVEL); + +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include "net_private.h" +#include "ipv6.h" + +/* From RFC 5453 */ +static const struct in6_addr reserved_anycast_subnet = { { { + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + } } }; + +/* RFC 8981 ch 3.8 preferred lifetime must be smaller than valid lifetime */ +BUILD_ASSERT(CONFIG_NET_IPV6_PE_TEMP_PREFERRED_LIFETIME < + CONFIG_NET_IPV6_PE_TEMP_VALID_LIFETIME); + +/* IPv6 privacy extension (RFC 8981) constants. Note that the code uses + * seconds value internally for applicaple options. These are also values + * that can be changed at runtime if needed as recommended in RFC 8981 + * chapter 3.6. + */ +static uint32_t temp_valid_lifetime = + CONFIG_NET_IPV6_PE_TEMP_VALID_LIFETIME * SEC_PER_MIN; +#define TEMP_VALID_LIFETIME temp_valid_lifetime + +static uint32_t temp_preferred_lifetime = + CONFIG_NET_IPV6_PE_TEMP_PREFERRED_LIFETIME * SEC_PER_MIN; +#define TEMP_PREFERRED_LIFETIME temp_preferred_lifetime + +/* This is the upper bound on DESYNC_FACTOR. The value is in seconds. + * See RFC 8981 ch 3.8 for details. + */ +#define MAX_DESYNC_FACTOR ((TEMP_PREFERRED_LIFETIME * 2U) / 5U) +#define DESYNC_FACTOR(ipv6) ((ipv6)->desync_factor) + +#define TEMP_IDGEN_RETRIES CONFIG_NET_IPV6_PE_TEMP_IDGEN_RETRIES + +/* The REGEN_ADVANCE is in seconds + * retrans_timer (in ms) is specified in RFC 4861 + * dup_addr_detect_transmits (in ms) is specified in RFC 4862 + */ +static inline uint32_t REGEN_ADVANCE(uint32_t retrans_timer, + uint32_t dup_addr_detect_transmits) +{ + return (2U + (uint32_t)((uint64_t)TEMP_IDGEN_RETRIES * + (uint64_t)retrans_timer * + (uint64_t)dup_addr_detect_transmits / + (uint64_t)1000U)); +} + +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 +/* Is this denylisting filter or not */ +static bool ipv6_pe_denylist; +static struct in6_addr ipv6_pe_filter[CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT]; + +static K_MUTEX_DEFINE(lock); +#endif + +/* We need to periodically update the private address. */ +static struct k_work_delayable temp_lifetime; + +static bool ipv6_pe_use_this_prefix(const struct in6_addr *prefix) +{ +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 + int filter_found = false; + bool ret = true; + + k_mutex_lock(&lock, K_FOREVER); + + ARRAY_FOR_EACH(ipv6_pe_filter, i) { + if (net_ipv6_is_addr_unspecified(&ipv6_pe_filter[i])) { + continue; + } + + filter_found = true; + + if (net_ipv6_addr_cmp(prefix, &ipv6_pe_filter[i])) { + if (ipv6_pe_denylist) { + ret = false; + } + + goto out; + } + } + + if (filter_found) { + /* There was no match so if we are deny listing, then this + * address must be acceptable. + */ + if (!ipv6_pe_denylist) { + ret = false; + goto out; + } + } + +out: + k_mutex_unlock(&lock); + + return ret; +#else + ARG_UNUSED(prefix); + + return true; +#endif +} + +static bool ipv6_pe_prefix_already_exists(struct net_if_ipv6 *ipv6, + const struct in6_addr *prefix) +{ + ARRAY_FOR_EACH(ipv6->unicast, i) { + if (!ipv6->unicast[i].is_used || + ipv6->unicast[i].address.family != AF_INET6 || + !ipv6->unicast[i].is_temporary || + ipv6->unicast[i].addr_state == NET_ADDR_DEPRECATED) { + continue; + } + + if (net_ipv6_is_prefix( + (uint8_t *)&ipv6->unicast[i].address.in6_addr, + (uint8_t *)prefix, 64)) { + return true; + } + } + + return false; +} + +static int ipv6_pe_prefix_remove(struct net_if *iface, + struct net_if_ipv6 *ipv6, + const struct in6_addr *prefix) +{ + int count = 0; + + ARRAY_FOR_EACH(ipv6->unicast, i) { + if (ipv6->unicast[i].is_used && + ipv6->unicast[i].address.family == AF_INET6 && + ipv6->unicast[i].is_temporary && + net_ipv6_is_prefix( + (uint8_t *)&ipv6->unicast[i].address.in6_addr, + (uint8_t *)prefix, 64)) { + net_if_ipv6_addr_rm(iface, + &ipv6->unicast[i].address.in6_addr); + count++; + } + } + + return count; +} + +static bool ipv6_pe_prefix_update_lifetimes(struct net_if_ipv6 *ipv6, + const struct in6_addr *prefix, + uint32_t vlifetime) +{ + int32_t addr_age, new_age; + + ARRAY_FOR_EACH(ipv6->unicast, i) { + if (!(ipv6->unicast[i].is_used && + ipv6->unicast[i].address.family == AF_INET6 && + ipv6->unicast[i].is_temporary && + ipv6->unicast[i].addr_state == NET_ADDR_PREFERRED && + net_ipv6_is_prefix( + (uint8_t *)&ipv6->unicast[i].address.in6_addr, + (uint8_t *)prefix, 64))) { + continue; + } + + addr_age = (uint32_t)(k_uptime_get() / 1000UL) - + ipv6->unicast[i].addr_create_time; + new_age = abs(addr_age) + vlifetime; + + if ((new_age >= TEMP_VALID_LIFETIME) || + (new_age >= (TEMP_PREFERRED_LIFETIME - + DESYNC_FACTOR(ipv6)))) { + break; + } + + net_if_ipv6_addr_update_lifetime(&ipv6->unicast[i], vlifetime); + + /* RFC 8981 ch 3.5, "... at most one temporary address per + * prefix should be in a non-deprecated state at any given + * time on a given interface." + * Because of this there is no need to continue the loop. + */ + return true; + } + + return false; +} + +/* RFC 8981 ch 3.3.2 */ +static void gen_temporary_iid(struct net_if *iface, + const struct in6_addr *prefix, + uint8_t *network_id, size_t network_id_len, + uint8_t dad_counter, + uint8_t *temporary_iid, + size_t temporary_iid_len) +{ + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + mbedtls_md_context_t ctx; + uint8_t digest[32]; + static bool once; + static uint8_t secret_key[16]; /* Min 128 bits, RFC 8981 ch 3.3.2 */ + struct { + struct in6_addr prefix; + uint32_t current_time; + uint8_t network_id[16]; + uint8_t mac[6]; + uint8_t dad_counter; + } buf = { + .current_time = k_uptime_get_32(), + .dad_counter = dad_counter, + }; + + memcpy(&buf.prefix, prefix, sizeof(struct in6_addr)); + + if (network_id != NULL && network_id_len > 0) { + memcpy(buf.network_id, network_id, + MIN(network_id_len, sizeof(buf.network_id))); + } + + memcpy(buf.mac, net_if_get_link_addr(iface)->addr, + MIN(sizeof(buf.mac), net_if_get_link_addr(iface)->len)); + + if (!once) { + sys_rand_get(&secret_key, sizeof(secret_key)); + once = true; + } + + mbedtls_md_init(&ctx); + mbedtls_md_setup(&ctx, md_info, true); + mbedtls_md_hmac_starts(&ctx, secret_key, sizeof(secret_key)); + mbedtls_md_hmac_update(&ctx, (uint8_t *)&buf, sizeof(buf)); + mbedtls_md_hmac_finish(&ctx, digest); + mbedtls_md_free(&ctx); + + memcpy(temporary_iid, digest, MIN(sizeof(digest), temporary_iid_len)); +} + +void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix, + uint32_t vlifetime, uint32_t preferred_lifetime) +{ + struct net_if_addr *ifaddr; + struct net_if_ipv6 *ipv6; + struct in6_addr addr; + k_ticks_t remaining; + k_timeout_t vlifetimeout; + int i, dad_count = 1; + int32_t lifetime; + bool valid = false; + + net_if_lock(iface); + + if (net_if_config_ipv6_get(iface, &ipv6) < 0) { + NET_WARN("Cannot do DAD IPv6 config is not valid."); + goto out; + } + + if (!ipv6) { + goto out; + } + + /* Check if user agrees to use this prefix */ + if (!ipv6_pe_use_this_prefix(prefix)) { + NET_DBG("Prefix %s/64 is not to be used", + net_sprint_ipv6_addr(prefix)); + goto out; + } + + /* If the prefix is already added and it is still valid and is not + * deprecated, then we do not try to add it again. + */ + if (ipv6_pe_prefix_already_exists(ipv6, prefix)) { + if (vlifetime == 0) { + i = ipv6_pe_prefix_remove(iface, ipv6, prefix); + + NET_DBG("Removed %d addresses using prefix %s/64", + i, net_sprint_ipv6_addr(prefix)); + } else { + ipv6_pe_prefix_update_lifetimes(ipv6, prefix, vlifetime); + } + + goto out; + } + + preferred_lifetime = MIN(preferred_lifetime, + TEMP_PREFERRED_LIFETIME - + DESYNC_FACTOR(ipv6)); + if (preferred_lifetime == 0 || + preferred_lifetime <= REGEN_ADVANCE(ipv6->retrans_timer, 1U)) { + NET_DBG("Too short preferred lifetime (%u <= %u), temp address not " + "created for prefix %s/64", preferred_lifetime, + REGEN_ADVANCE(ipv6->retrans_timer, 1U), + net_sprint_ipv6_addr(prefix)); + goto out; + } + + NET_DBG("Starting PE process for prefix %s/64", + net_sprint_ipv6_addr(prefix)); + + net_ipaddr_copy(&addr, prefix); + + do { + gen_temporary_iid(iface, prefix, + COND_CODE_1(CONFIG_NET_INTERFACE_NAME, + (iface->config.name, + sizeof(iface->config.name)), + (net_if_get_device(iface)->name, + strlen(net_if_get_device(iface)->name))), + dad_count, + &addr.s6_addr[8], 8U); + + ifaddr = net_if_ipv6_addr_lookup(&addr, NULL); + if (ifaddr == NULL && !net_ipv6_is_addr_unspecified(&addr) && + memcmp(&addr, &reserved_anycast_subnet, + sizeof(struct in6_addr)) != 0) { + valid = true; + break; + } + + } while (dad_count++ < TEMP_IDGEN_RETRIES); + + if (valid == false) { + NET_WARN("Could not create a valid iid for prefix %s/64 for interface %d", + net_sprint_ipv6_addr(prefix), + net_if_get_by_iface(iface)); + NET_WARN("Disabling IPv6 PE for interface %d", + net_if_get_by_iface(iface)); + iface->pe_enabled = false; + goto out; + } + + vlifetime = MIN(TEMP_VALID_LIFETIME, vlifetime); + + ifaddr = net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF, vlifetime); + if (!ifaddr) { + NET_ERR("Cannot add %s address to interface %d", + net_sprint_ipv6_addr(&addr), + net_if_get_by_iface(iface)); + goto out; + } + + lifetime = TEMP_VALID_LIFETIME - + REGEN_ADVANCE(net_if_ipv6_get_retrans_timer(iface), 1U); + + DESYNC_FACTOR(ipv6) = sys_rand32_get() % MAX_DESYNC_FACTOR; + + /* Make sure that the address timeout happens at least two seconds + * after the deprecation. + */ + DESYNC_FACTOR(ipv6) = MIN(DESYNC_FACTOR(ipv6) + 2U, lifetime); + + ifaddr->is_temporary = true; + ifaddr->addr_preferred_lifetime = preferred_lifetime; + ifaddr->addr_timeout = ifaddr->addr_preferred_lifetime - DESYNC_FACTOR(ipv6); + ifaddr->addr_create_time = (uint32_t)(k_uptime_get() / 1000UL); + + NET_DBG("Lifetime %d desync %d timeout %d preferred %d valid %d", + lifetime, DESYNC_FACTOR(ipv6), ifaddr->addr_timeout, + ifaddr->addr_preferred_lifetime, vlifetime); + + NET_DBG("Starting DAD for %s iface %d", net_sprint_ipv6_addr(&addr), + net_if_get_by_iface(iface)); + + net_if_ipv6_start_dad(iface, ifaddr); + + vlifetimeout = K_SECONDS(ifaddr->addr_timeout); + + remaining = k_work_delayable_remaining_get(&temp_lifetime); + if (remaining == 0 || remaining > vlifetimeout.ticks) { + NET_DBG("Next check for temp addresses in %d seconds", + ifaddr->addr_timeout); + k_work_schedule(&temp_lifetime, vlifetimeout); + } + +out: + net_if_unlock(iface); +} + +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 + +static void iface_cb(struct net_if *iface, void *user_data) +{ + bool is_new_filter_denylist = !ipv6_pe_denylist; + struct in6_addr *prefix = user_data; + struct net_if_ipv6 *ipv6; + int ret; + + net_if_lock(iface); + + if (net_if_config_ipv6_get(iface, &ipv6) < 0) { + goto out; + } + + if (!ipv6) { + goto out; + } + + ARRAY_FOR_EACH(ipv6->unicast, i) { + if (!ipv6->unicast[i].is_used || + ipv6->unicast[i].address.family != AF_INET6 || + !ipv6->unicast[i].is_temporary) { + continue; + } + + ret = net_ipv6_is_prefix( + (uint8_t *)&ipv6->unicast[i].address.in6_addr, + (uint8_t *)prefix, 64); + + /* TODO: Do this removal gracefully so that applications + * have time to cope with this change. + */ + if (is_new_filter_denylist) { + if (ret) { + net_if_ipv6_addr_rm(iface, + &ipv6->unicast[i].address.in6_addr); + } + } else { + if (!ret) { + net_if_ipv6_addr_rm(iface, + &ipv6->unicast[i].address.in6_addr); + } + } + } + +out: + net_if_unlock(iface); +} + +/* If we change filter value, then check if existing IPv6 prefixes will + * conflict with the new filter. + */ +static void ipv6_pe_recheck_filters(bool is_denylist) +{ + k_mutex_lock(&lock, K_FOREVER); + + ARRAY_FOR_EACH(ipv6_pe_filter, i) { + if (net_ipv6_is_addr_unspecified(&ipv6_pe_filter[i])) { + continue; + } + + net_if_foreach(iface_cb, &ipv6_pe_filter[i]); + } + + k_mutex_unlock(&lock); +} +#endif /* CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 */ + +int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_denylist) +{ +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 + bool found = false; + int free_slot = -1; + int ret = 0; + + k_mutex_lock(&lock, K_FOREVER); + + ARRAY_FOR_EACH(ipv6_pe_filter, i) { + if (free_slot < 0 && + net_ipv6_is_addr_unspecified(&ipv6_pe_filter[i])) { + free_slot = i; + continue; + } + + if (net_ipv6_is_prefix((uint8_t *)addr, + (uint8_t *)&ipv6_pe_filter[i], + 64)) { + found = true; + break; + } + } + + if (found) { + NET_DBG("Filter %s already in the list", + net_sprint_ipv6_addr(addr)); + ret = -EALREADY; + goto out; + } + + if (free_slot < 0) { + NET_DBG("All filters in use"); + ret = -ENOMEM; + goto out; + } + + net_ipaddr_copy(&ipv6_pe_filter[free_slot], addr); + + if (ipv6_pe_denylist != is_denylist) { + ipv6_pe_recheck_filters(is_denylist); + } + + ipv6_pe_denylist = is_denylist ? true : false; + + NET_DBG("Adding %s list filter %s", + ipv6_pe_denylist ? "deny" : "allow", + net_sprint_ipv6_addr(&ipv6_pe_filter[free_slot])); + +out: + k_mutex_unlock(&lock); + + return ret; +#else + ARG_UNUSED(addr); + ARG_UNUSED(is_denylist); + + return -ENOTSUP; +#endif +} + +int net_ipv6_pe_del_filter(struct in6_addr *addr) +{ +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 + int ret = -ENOENT; + + k_mutex_lock(&lock, K_FOREVER); + + ARRAY_FOR_EACH(ipv6_pe_filter, i) { + if (net_ipv6_addr_cmp(&ipv6_pe_filter[i], addr)) { + NET_DBG("Removing %s list filter %s", + ipv6_pe_denylist ? "deny" : "allow", + net_sprint_ipv6_addr(&ipv6_pe_filter[i])); + + net_ipaddr_copy(&ipv6_pe_filter[i], + net_ipv6_unspecified_address()); + ret = 0; + goto out; + } + } + +out: + k_mutex_unlock(&lock); + + return ret; +#else + ARG_UNUSED(addr); + + return -ENOTSUP; +#endif +} + +bool net_ipv6_pe_check_dad(int count) +{ + return count <= TEMP_IDGEN_RETRIES; +} + +int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb, void *user_data) +{ +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 + int i, count = 0; + + k_mutex_lock(&lock, K_FOREVER); + + for (i = 0; i < CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT; i++) { + if (net_ipv6_is_addr_unspecified(&ipv6_pe_filter[i])) { + continue; + } + + cb(&ipv6_pe_filter[i], ipv6_pe_denylist, user_data); + + count++; + } + + k_mutex_unlock(&lock); + + return count; +#else + ARG_UNUSED(cb); + ARG_UNUSED(user_data); + + return 0; +#endif +} + +struct deprecated_work { + struct k_work_delayable work; + struct net_if *iface; + struct in6_addr addr; +}; + +static struct deprecated_work trigger_deprecated_event; + +static void send_deprecated_event(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct deprecated_work *dw = CONTAINER_OF(dwork, + struct deprecated_work, + work); + + net_mgmt_event_notify_with_info(NET_EVENT_IPV6_ADDR_DEPRECATED, + dw->iface, &dw->addr, + sizeof(struct in6_addr)); +} + +static void renewal_cb(struct net_if *iface, void *user_data) +{ + struct net_if_ipv6 *ipv6; + struct in6_addr prefix; + + if (net_if_config_ipv6_get(iface, &ipv6) < 0) { + return; + } + + if (!ipv6) { + return; + } + + ARRAY_FOR_EACH(ipv6->unicast, i) { + int32_t diff; + + if (!ipv6->unicast[i].is_used || + ipv6->unicast[i].address.family != AF_INET6 || + !ipv6->unicast[i].is_temporary || + ipv6->unicast[i].addr_state == NET_ADDR_DEPRECATED) { + continue; + } + + /* If the address is too old, then generate a new one + * and remove the old address. + */ + diff = (int32_t)(ipv6->unicast[i].addr_create_time - + ((uint32_t)(k_uptime_get() / 1000UL))); + diff = abs(diff); + + if (diff < (ipv6->unicast[i].addr_preferred_lifetime - + REGEN_ADVANCE(ipv6->retrans_timer, 1U) - + DESYNC_FACTOR(ipv6))) { + continue; + } + + net_ipaddr_copy(&prefix, &ipv6->unicast[i].address.in6_addr); + memset(prefix.s6_addr + 8, 0, sizeof(prefix) - 8); + + NET_DBG("IPv6 address %s is deprecated", + net_sprint_ipv6_addr(&ipv6->unicast[i].address.in6_addr)); + + ipv6->unicast[i].addr_state = NET_ADDR_DEPRECATED; + + /* Create a new temporary address and then notify users + * that the old address is deprecated so that they can + * re-connect to use the new address. We cannot send deprecated + * event immediately because the new IPv6 will need to do DAD + * and that takes a bit time. + */ + net_ipv6_pe_start(iface, &prefix, + TEMP_VALID_LIFETIME, + TEMP_PREFERRED_LIFETIME); + + /* It is very unlikely but still a small possibility that there + * could be another work already pending. + * Fixing this would require allocating space for the work + * somewhere. Currently this does not look like worth fixing. + * Print a warning if there is a work already pending. + */ + if (k_work_delayable_is_pending(&trigger_deprecated_event.work)) { + NET_WARN("Work already pending for deprecated event sending."); + } + + trigger_deprecated_event.iface = iface; + memcpy(&trigger_deprecated_event.addr, + &ipv6->unicast[i].address.in6_addr, + sizeof(struct in6_addr)); + + /* 500ms should be enough for DAD to pass */ + k_work_schedule(&trigger_deprecated_event.work, K_MSEC(500)); + } +} + +static void ipv6_pe_renew(struct k_work *work) +{ + ARG_UNUSED(work); + + net_if_foreach(renewal_cb, NULL); +} + +int net_ipv6_pe_init(struct net_if *iface) +{ + int32_t lifetime; + int ret = 0; + + lifetime = TEMP_VALID_LIFETIME - + REGEN_ADVANCE(net_if_ipv6_get_retrans_timer(iface), 1U); + + if (lifetime <= 0) { + iface->pe_enabled = false; + ret = -EINVAL; + goto out; + } + + iface->pe_enabled = true; + iface->pe_prefer_public = + IS_ENABLED(CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES) ? + true : false; + + k_work_init_delayable(&temp_lifetime, ipv6_pe_renew); + k_work_init_delayable(&trigger_deprecated_event.work, + send_deprecated_event); + +out: + NET_DBG("pe %s prefer %s lifetime %d sec", + iface->pe_enabled ? "enabled" : "disabled", + iface->pe_prefer_public ? "public" : "temporary", + lifetime); + + return ret; +} diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index e7306acd878aba..157e9345c68c9a 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -431,6 +431,8 @@ static inline void init_iface(struct net_if *iface) k_mutex_init(&iface->tx_lock); api->init(iface); + + net_ipv6_pe_init(iface); } enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt) @@ -1232,8 +1234,8 @@ static void dad_timeout(struct k_work *work) } } -static void net_if_ipv6_start_dad(struct net_if *iface, - struct net_if_addr *ifaddr) +void net_if_ipv6_start_dad(struct net_if *iface, + struct net_if_addr *ifaddr) { ifaddr->addr_state = NET_ADDR_TENTATIVE; @@ -1324,6 +1326,7 @@ void net_if_start_dad(struct net_if *iface) void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr) { struct net_if_addr *ifaddr; + uint32_t timeout, preferred_lifetime; net_if_lock(iface); @@ -1335,12 +1338,36 @@ void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr) } + if (IS_ENABLED(CONFIG_NET_IPV6_PE)) { + ifaddr->dad_count++; + + timeout = COND_CODE_1(CONFIG_NET_IPV6_PE, + (ifaddr->addr_timeout), (0)); + preferred_lifetime = COND_CODE_1(CONFIG_NET_IPV6_PE, + (ifaddr->addr_preferred_lifetime), (0U)); + + if (!net_ipv6_pe_check_dad(ifaddr->dad_count)) { + NET_ERR("Cannot generate PE address for interface %p", + iface); + iface->pe_enabled = false; + net_mgmt_event_notify(NET_EVENT_IPV6_PE_DISABLED, iface); + } + } + net_mgmt_event_notify_with_info(NET_EVENT_IPV6_DAD_FAILED, iface, &ifaddr->address.in6_addr, sizeof(struct in6_addr)); + /* The old address needs to be removed from the interface before we can + * start new DAD for the new PE address as the amount of address slots + * is limited. + */ net_if_ipv6_addr_rm(iface, addr); + if (IS_ENABLED(CONFIG_NET_IPV6_PE) && iface->pe_enabled) { + net_ipv6_pe_start(iface, addr, timeout, preferred_lifetime); + } + out: net_if_unlock(iface); } @@ -1671,8 +1698,6 @@ static void address_expired(struct net_if_addr *ifaddr) NET_DBG("IPv6 address %s is deprecated", net_sprint_ipv6_addr(&ifaddr->address.in6_addr)); - ifaddr->addr_state = NET_ADDR_DEPRECATED; - sys_slist_find_and_remove(&active_address_lifetime_timers, &ifaddr->lifetime.node); @@ -1782,8 +1807,10 @@ static inline void net_if_addr_init(struct net_if_addr *ifaddr, uint32_t vlifetime) { ifaddr->is_used = true; + ifaddr->is_temporary = false; ifaddr->address.family = AF_INET6; ifaddr->addr_type = addr_type; + net_ipaddr_copy(&ifaddr->address.in6_addr, addr); /* FIXME - set the mcast addr for this node */ diff --git a/subsys/net/ip/net_private.h b/subsys/net/ip/net_private.h index 0cd007595f6259..6d425c0518893d 100644 --- a/subsys/net/ip/net_private.h +++ b/subsys/net/ip/net_private.h @@ -174,6 +174,12 @@ struct sock_obj { }; #endif /* CONFIG_NET_SOCKETS_OBJ_CORE */ +#if defined(CONFIG_NET_IPV6_PE) +/* This is needed by ipv6_pe.c when privacy extension support is enabled */ +void net_if_ipv6_start_dad(struct net_if *iface, + struct net_if_addr *ifaddr); +#endif + #if defined(CONFIG_NET_GPTP) /** * @brief Initialize Precision Time Protocol Layer. From 6ec98a0258a7569537bf82a27995692c1b54c3ca Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0204/1389] net: ipv6: Select proper IPv6 source address for privacy extension If IPv6 privacy extension is enabled, then we need to select proper public or temporary IPv6 source address when sending the packet. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_if.h | 2 +- subsys/net/ip/net_if.c | 71 +++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 8bf41153d77d32..90ecea43882158 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -1611,7 +1611,7 @@ void net_if_ipv6_maddr_leave(struct net_if *iface, * @return Pointer to prefix, NULL if not found. */ struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface, - struct in6_addr *addr); + const struct in6_addr *addr); /** * @brief Check if this IPv6 prefix belongs to this interface diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 157e9345c68c9a..43f493e7c1d654 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -2592,7 +2592,7 @@ bool net_if_ipv6_prefix_rm(struct net_if *iface, struct in6_addr *addr, } struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface, - struct in6_addr *addr) + const struct in6_addr *addr) { struct net_if_ipv6_prefix *prefix = NULL; struct net_if_ipv6 *ipv6; @@ -2986,13 +2986,29 @@ static inline bool is_proper_ipv6_address(struct net_if_addr *addr) return false; } +static bool use_public_address(bool prefer_public, bool is_temporary) +{ + if (IS_ENABLED(CONFIG_NET_IPV6_PE)) { + if (!prefer_public && is_temporary) { + return false; + } + } + + return true; +} + static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, const struct in6_addr *dst, + uint8_t prefix_len, uint8_t *best_so_far) { - struct net_if_ipv6 *ipv6; + struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6; + struct net_if_addr *public_addr = NULL; struct in6_addr *src = NULL; - uint8_t len; + uint8_t public_addr_len = 0; + struct in6_addr *temp_addr; + uint8_t len, temp_addr_len; + bool ret; net_if_lock(iface); @@ -3001,12 +3017,24 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, goto out; } + if (IS_ENABLED(CONFIG_NET_IPV6_PE)) { + temp_addr = NULL; + temp_addr_len = 0; + } else { + ARG_UNUSED(temp_addr); + ARG_UNUSED(temp_addr_len); + } + ARRAY_FOR_EACH(ipv6->unicast, i) { if (!is_proper_ipv6_address(&ipv6->unicast[i])) { continue; } len = get_diff_ipv6(dst, &ipv6->unicast[i].address.in6_addr); + if (len >= prefix_len) { + len = prefix_len; + } + if (len >= *best_so_far) { /* Mesh local address can only be selected for the same * subnet. @@ -3016,11 +3044,38 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, continue; } + ret = use_public_address(iface->pe_prefer_public, + ipv6->unicast[i].is_temporary); + if (!ret) { + temp_addr = &ipv6->unicast[i].address.in6_addr; + temp_addr_len = len; + continue; + } + + if (!ipv6->unicast[i].is_temporary) { + public_addr = &ipv6->unicast[i]; + public_addr_len = len; + } + *best_so_far = len; src = &ipv6->unicast[i].address.in6_addr; } } + if (IS_ENABLED(CONFIG_NET_IPV6_PE) && !iface->pe_prefer_public && temp_addr) { + if (temp_addr_len >= *best_so_far) { + *best_so_far = temp_addr_len; + src = temp_addr; + } + } else { + /* By default prefer always public address if found */ + if (public_addr && + !net_ipv6_addr_cmp(&public_addr->address.in6_addr, src)) { + src = &public_addr->address.in6_addr; + *best_so_far = public_addr_len; + } + } + out: net_if_unlock(iface); @@ -3036,15 +3091,25 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, NET_ASSERT(dst); if (!net_ipv6_is_ll_addr(dst) && !net_ipv6_is_addr_mcast_link(dst)) { + struct net_if_ipv6_prefix *prefix; + uint8_t prefix_len = 128; + + prefix = net_if_ipv6_prefix_get(dst_iface, dst); + if (prefix) { + prefix_len = prefix->len; + } + /* If caller has supplied interface, then use that */ if (dst_iface) { src = net_if_ipv6_get_best_match(dst_iface, dst, + prefix_len, &best_match); } else { STRUCT_SECTION_FOREACH(net_if, iface) { struct in6_addr *addr; addr = net_if_ipv6_get_best_match(iface, dst, + prefix_len, &best_match); if (addr) { src = addr; From f38354935958f4f134c1389a28ed64d3a3aa5198 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0205/1389] tests: net: ipv6: Add privacy extension tests Add tests that will make sure IPv6 privacy extension code works as expected. Signed-off-by: Jukka Rissanen --- tests/net/all/prj.conf | 5 + tests/net/ipv6/prj.conf | 7 ++ tests/net/ipv6/src/main.c | 218 ++++++++++++++++++++++++++++++++++- tests/net/ipv6/testcase.yaml | 17 +++ 4 files changed, 244 insertions(+), 3 deletions(-) diff --git a/tests/net/all/prj.conf b/tests/net/all/prj.conf index fc88e5979a4f28..1ab45c3ef6dbd1 100644 --- a/tests/net/all/prj.conf +++ b/tests/net/all/prj.conf @@ -158,6 +158,11 @@ CONFIG_NET_IPV6_ND_LOG_LEVEL_DBG=y CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG=y CONFIG_NET_ICMPV6_LOG_LEVEL_DBG=y +# IPv6 privacy extension +CONFIG_NET_IPV6_PE=y +CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES=n +CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT=2 + # 6lo CONFIG_NET_6LO=y CONFIG_NET_6LO_CONTEXT=y diff --git a/tests/net/ipv6/prj.conf b/tests/net/ipv6/prj.conf index c2f80f6ead4e88..e6a4a365e2bc18 100644 --- a/tests/net/ipv6/prj.conf +++ b/tests/net/ipv6/prj.conf @@ -28,3 +28,10 @@ CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=9 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=7 CONFIG_NET_IF_IPV6_PREFIX_COUNT=3 CONFIG_NET_UDP_CHECKSUM=n +CONFIG_NET_IF_MAX_IPV6_COUNT=2 +CONFIG_NET_IPV6_PE=y +CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT=2 +CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES=n + +# Increase the stack a bit for mps2/an385 +CONFIG_NET_RX_STACK_SIZE=1700 diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index 06939fb47d53a7..ffdd263e603fdb 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -36,6 +36,12 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #define NET_LOG_ENABLED 1 #include "net_private.h" +#if defined(CONFIG_NET_IPV6_PE) +#define NET_IPV6_PE_FILTER_PREFIX_COUNT CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT +#else +#define NET_IPV6_PE_FILTER_PREFIX_COUNT 0 +#endif + #define TEST_NET_IF net_if_lookup_by_dev(DEVICE_GET(eth_ipv6_net)) static struct in6_addr my_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, @@ -98,9 +104,9 @@ static const unsigned char icmpv6_ra[] = { 0x01, 0x01, 0x00, 0x60, 0x97, 0x07, 0x69, 0xea, /* MTU */ 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xdc, -/* Prefix info */ - 0x03, 0x04, 0x40, 0xc0, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +/* Prefix info*/ + 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0xFF, 0xFF, + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Route info */ @@ -1682,4 +1688,210 @@ ZTEST(net_ipv6, test_nd_reachability_hint) zassert_equal(net_ipv6_nbr_data(nbr)->state, NET_IPV6_NBR_STATE_REACHABLE); } +static bool is_pe_address_found(struct net_if *iface, struct in6_addr *prefix) +{ + struct net_if_ipv6 *ipv6; + + ipv6 = iface->config.ip.ipv6; + + zassert_not_null(ipv6, "IPv6 configuration is wrong for iface %p", + iface); + + ARRAY_FOR_EACH(ipv6->unicast, i) { + if (!ipv6->unicast[i].is_used || + ipv6->unicast[i].address.family != AF_INET6 || + !ipv6->unicast[i].is_temporary) { + continue; + } + + if (net_ipv6_is_prefix( + (uint8_t *)&ipv6->unicast[i].address.in6_addr, + (uint8_t *)prefix, 64)) { + return true; + } + } + + return false; +} + +static void get_pe_addresses(struct net_if *iface, + struct in6_addr **public_addr, + struct in6_addr **temp_addr) +{ + struct in6_addr prefix = { { { 0x3f, 0xfe, 0x05, 0x07, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; + struct net_if_ipv6 *ipv6; + + ipv6 = iface->config.ip.ipv6; + + zassert_not_null(ipv6, "IPv6 configuration is wrong for iface %p", + iface); + + ARRAY_FOR_EACH(ipv6->unicast, i) { + if (!ipv6->unicast[i].is_used || + ipv6->unicast[i].address.family != AF_INET6) { + continue; + } + + if (net_ipv6_is_prefix( + (uint8_t *)&ipv6->unicast[i].address.in6_addr, + (uint8_t *)&prefix, 64)) { + if (ipv6->unicast[i].is_temporary) { + *temp_addr = + &ipv6->unicast[i].address.in6_addr; + } else { + *public_addr = + &ipv6->unicast[i].address.in6_addr; + } + } + } +} + +/* The privacy extension tests need to be run after the RA tests so name + * the tests like this. + */ +ZTEST(net_ipv6, test_z_privacy_extension_01) +{ + struct in6_addr prefix = { { { 0x3f, 0xfe, 0x05, 0x07, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; + struct net_if *iface = net_if_get_default(); + bool found; + + if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) { + return; + } + + zassert_true(iface->pe_enabled, + "Privacy extension not enabled for iface %d", + net_if_get_by_iface(iface)); + + if (IS_ENABLED(CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES)) { + zassert_true(iface->pe_prefer_public, + "Prefer public flag not set correctly for iface %d", + net_if_get_by_iface(iface)); + } + + /* We received RA message earlier, make sure that temporary address + * is created because of that message. + */ + + found = is_pe_address_found(iface, &prefix); + zassert_true(found, "Temporary address not found for iface %d", + net_if_get_by_iface(iface)); +} + +ZTEST(net_ipv6, test_z_privacy_extension_02_filters) +{ + struct in6_addr prefix1 = { { { 0x3f, 0xfe, 0x05, 0x07, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; + struct in6_addr prefix2 = { { { 0x3f, 0xfe, 0x04, 0x07, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; + struct in6_addr prefix3 = { { { 0x3f, 0xfe, 0x03, 0x07, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; + struct net_if *iface = net_if_get_default(); + bool found; + int ret; + + if (!IS_ENABLED(CONFIG_NET_IPV6_PE) || NET_IPV6_PE_FILTER_PREFIX_COUNT == 0) { + return; + } + + /* First add denylist filters */ + ret = net_ipv6_pe_add_filter(&prefix1, true); + zassert_equal(ret, 0, "Filter cannot be added (%d)", ret); + + ret = net_ipv6_pe_add_filter(&prefix2, true); + zassert_equal(ret, 0, "Filter cannot be added (%d)", ret); + + ret = net_ipv6_pe_add_filter(&prefix3, true); + zassert_true(ret < 0, "Filter could be added"); + + /* Then delete them */ + ret = net_ipv6_pe_del_filter(&prefix1); + zassert_equal(ret, 0, "Filter cannot be deleted (%d)", ret); + + ret = net_ipv6_pe_del_filter(&prefix2); + zassert_equal(ret, 0, "Filter cannot be deleted (%d)", ret); + + ret = net_ipv6_pe_del_filter(&prefix2); + zassert_true(ret < 0, "Filter found (%d)", ret); + + /* Then add allowlist filter */ + ret = net_ipv6_pe_add_filter(&prefix1, false); + zassert_equal(ret, 0, "Filter cannot be added (%d)", ret); + + /* Send RS again as we have now PE allowlist filter in place */ + rs_message(); + + /* IP stack needs to process the packet */ + k_sleep(K_MSEC(150)); + + found = is_pe_address_found(iface, &prefix1); + zassert_true(found, "Temporary address not found for iface %p", iface); + + /* Then try with denylisted filter */ + ret = net_ipv6_pe_del_filter(&prefix1); + zassert_equal(ret, 0, "Filter cannot be deleted (%d)", ret); + + ret = net_ipv6_pe_add_filter(&prefix1, true); + zassert_equal(ret, 0, "Filter cannot be added (%d)", ret); + + k_sleep(K_MSEC(10)); + + /* Send RS again as we have now PE denylist filter in place */ + rs_message(); + + k_sleep(K_MSEC(150)); + + found = is_pe_address_found(iface, &prefix1); + zassert_false(found, "Temporary address found for iface %p", iface); + + ret = net_ipv6_pe_del_filter(&prefix1); + zassert_equal(ret, 0, "Filter cannot be deleted (%d)", ret); + + /* Add the temp address back for the next tests */ + ret = net_ipv6_pe_add_filter(&prefix1, false); + zassert_equal(ret, 0, "Filter cannot be added (%d)", ret); + + k_sleep(K_MSEC(50)); + + /* Send RS again as we have now PE allowlist filter in place */ + rs_message(); + + k_sleep(K_MSEC(150)); + + found = is_pe_address_found(iface, &prefix1); + zassert_true(found, "Temporary address not found for iface %p", iface); +} + +ZTEST(net_ipv6, test_z_privacy_extension_03_get_addr) +{ + struct in6_addr dst_addr = { { { 0x3f, 0xfe, 0x05, 0x07, 0, 0, 0, 1, + 0, 0, 2, 3, 4, 5, 6, 7 } } }; + struct net_if *iface = net_if_get_default(); + struct in6_addr *public_addr = NULL; + struct in6_addr *temp_addr = NULL; + const struct in6_addr *src_addr; + + if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) { + return; + } + + get_pe_addresses(iface, &public_addr, &temp_addr); + + zassert_not_null(public_addr, "No public address found"); + zassert_not_null(temp_addr, "No temporary address found"); + + src_addr = net_if_ipv6_select_src_addr(iface, &dst_addr); + zassert_not_null(src_addr, "No suitable source address found"); + + if (iface->pe_prefer_public) { + zassert_true(net_ipv6_addr_cmp(src_addr, public_addr), + "Non public address selected"); + } else { + zassert_true(net_ipv6_addr_cmp(src_addr, temp_addr), + "Non temporary address selected"); + } +} + ZTEST_SUITE(net_ipv6, NULL, ipv6_setup, NULL, NULL, ipv6_teardown); diff --git a/tests/net/ipv6/testcase.yaml b/tests/net/ipv6/testcase.yaml index 1fbe64f067aba3..78be3c872afd7b 100644 --- a/tests/net/ipv6/testcase.yaml +++ b/tests/net/ipv6/testcase.yaml @@ -2,13 +2,30 @@ common: tags: - net - ipv6 + - ipv6_pe depends_on: netif tests: net.ipv6: extra_configs: - CONFIG_NET_BUF_FIXED_DATA_SIZE=y + - CONFIG_NET_IPV6_PE=n net.ipv6.variable_buf_size: extra_configs: - CONFIG_NET_BUF_VARIABLE_DATA_SIZE=y - CONFIG_NET_PKT_BUF_RX_DATA_POOL_SIZE=4096 - CONFIG_NET_PKT_BUF_TX_DATA_POOL_SIZE=4096 + - CONFIG_NET_IPV6_PE=n + net.ipv6.privacy_extension.prefer_public: + extra_configs: + - CONFIG_NET_IPV6_PE=y + - CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES=y + - CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT=2 + - CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=9 + - CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=7 + net.ipv6.privacy_extension.prefer_temporary: + extra_configs: + - CONFIG_NET_IPV6_PE=y + - CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES=n + - CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT=2 + - CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=9 + - CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=7 From 8bbf3f5b501668cdf51b760d60b0b1dab669eba1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0206/1389] net: shell: Add information about IPv6 privacy extension When executing "net iface" command, print current status of IPv6 privacy extension if it is enabled in config file. The "net ipv6 ..." command prints IPv6 privacy extension information, and can add or delete IPv6 prefix filters. Signed-off-by: Jukka Rissanen --- subsys/net/lib/shell/iface.c | 11 ++- subsys/net/lib/shell/ipv6.c | 170 +++++++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 10 deletions(-) diff --git a/subsys/net/lib/shell/iface.c b/subsys/net/lib/shell/iface.c index c3d3ff404de799..00c681784ed004 100644 --- a/subsys/net/lib/shell/iface.c +++ b/subsys/net/lib/shell/iface.c @@ -321,12 +321,13 @@ static void iface_cb(struct net_if *iface, void *user_data) continue; } - PR("\t%s %s %s%s%s\n", + PR("\t%s %s %s%s%s%s\n", net_sprint_ipv6_addr(&unicast->address.in6_addr), addrtype2str(unicast->addr_type), addrstate2str(unicast->addr_state), unicast->is_infinite ? " infinite" : "", - unicast->is_mesh_local ? " meshlocal" : ""); + unicast->is_mesh_local ? " meshlocal" : "", + unicast->is_temporary ? " temporary" : ""); count++; } @@ -385,6 +386,12 @@ static void iface_cb(struct net_if *iface, void *user_data) skip_ipv6: +#if defined(CONFIG_NET_IPV6_PE) + PR("IPv6 privacy extension : %s (preferring %s addresses)\n", + iface->pe_enabled ? "enabled" : "disabled", + iface->pe_prefer_public ? "public" : "temporary"); +#endif + if (ipv6) { PR("IPv6 hop limit : %d\n", ipv6->hop_limit); diff --git a/subsys/net/lib/shell/ipv6.c b/subsys/net/lib/shell/ipv6.c index 12f4ce66565f53..d432ca730f1950 100644 --- a/subsys/net/lib/shell/ipv6.c +++ b/subsys/net/lib/shell/ipv6.c @@ -56,6 +56,28 @@ void ipv6_frag_cb(struct net_ipv6_reassembly *reass, void *user_data) #if defined(CONFIG_NET_NATIVE_IPV6) +#if defined(CONFIG_NET_IPV6_PE) +static void ipv6_pe_filter_cb(struct in6_addr *prefix, bool is_denylist, + void *user_data) +{ + struct net_shell_user_data *data = user_data; + const struct shell *sh = data->sh; + int *count = data->user_data; + char ipaddr[INET6_ADDRSTRLEN + 1]; + + net_addr_ntop(AF_INET6, prefix, ipaddr, sizeof(ipaddr) - 1); + + if (*count == 0) { + PR("IPv6 privacy extension %s list filters :\n", + is_denylist ? "deny" : "allow"); + } + + PR("[%d] %s/64\n", *count, ipaddr); + + (*count)++; +} +#endif /* CONFIG_NET_IPV6_PE */ + static void address_lifetime_cb(struct net_if *iface, void *user_data) { struct net_shell_user_data *data = user_data; @@ -106,13 +128,13 @@ static void address_lifetime_cb(struct net_if *iface, void *user_data) "%u", (uint32_t)(remaining / 1000U)); } - PR("%s \t%s\t%s \t%s/%d\n", - addrtype2str(ipv6->unicast[i].addr_type), - addrstate2str(ipv6->unicast[i].addr_state), - remaining_str, - net_sprint_ipv6_addr( - &ipv6->unicast[i].address.in6_addr), - prefix_len); + PR("%s \t%s\t%s \t%s/%d%s\n", + addrtype2str(ipv6->unicast[i].addr_type), + addrstate2str(ipv6->unicast[i].addr_state), + remaining_str, + net_sprint_ipv6_addr(&ipv6->unicast[i].address.in6_addr), + prefix_len, + ipv6->unicast[i].is_temporary ? " (temporary)" : ""); } } #endif /* CONFIG_NET_NATIVE_IPV6 */ @@ -160,6 +182,15 @@ static int cmd_net_ipv6(const struct shell *sh, size_t argc, char *argv[]) "disabled"); } + PR("Privacy extension support : %s\n", + IS_ENABLED(CONFIG_NET_IPV6_PE) ? "enabled" : "disabled"); + +#if defined(CONFIG_NET_IPV6_PE) + PR("Max number of IPv6 privacy extension filters " + " : %d\n", + CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT); +#endif + PR("Max number of IPv6 network interfaces " "in the system : %d\n", CONFIG_NET_IF_MAX_IPV6_COUNT); @@ -178,7 +209,8 @@ static int cmd_net_ipv6(const struct shell *sh, size_t argc, char *argv[]) /* Print information about address lifetime */ net_if_foreach(address_lifetime_cb, &user_data); -#endif + +#endif /* CONFIG_NET_NATIVE_IPV6 */ return 0; } @@ -292,6 +324,119 @@ static int cmd_net_ip6_del(const struct shell *sh, size_t argc, char *argv[]) return 0; } +static int cmd_net_ip6_pe(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 + bool do_allowlisting = true; + struct in6_addr prefix; + bool do_add; + int arg = 1; + int ret; + + if (argc == 0) { + PR_ERROR("Correct usage: net ipv6 pe [add | del] [allow | deny] []\n"); + return -EINVAL; + } + + if (argc == 1) { + struct net_shell_user_data user_data; + int count = 0; + + user_data.sh = sh; + user_data.user_data = &count; + + count = net_ipv6_pe_filter_foreach(ipv6_pe_filter_cb, &user_data); + if (count == 0) { + PR("No privacy extension filters found."); + } + + return 0; + } + + if (strcmp(argv[arg], "add") == 0) { + arg++; + do_add = true; + } else if (strcmp(argv[arg], "del") == 0) { + arg++; + do_add = false; + } else { + PR("Unknown sub-option \"%s\"\n", argv[arg]); + return 0; + } + + if (!argv[arg]) { + PR("No sub-options given. See \"help net ipv6\" " + "command for details.\n"); + return 0; + } + + if (strcmp(argv[arg], "allow") == 0) { + arg++; + } else if (strcmp(argv[arg], "deny") == 0) { + arg++; + do_allowlisting = false; + } + + if (!argv[arg]) { + PR("No sub-options given. See \"help net ipv6\" " + "command for details.\n"); + return 0; + } + + ret = net_addr_pton(AF_INET6, argv[arg], &prefix); + if (ret < 0) { + PR("Invalid prefix \"%s\"\n", argv[arg]); + if (strstr(argv[arg], "/")) { + PR("Do not add the prefix length.\n"); + } + + return 0; + } + + if (do_add) { + ret = net_ipv6_pe_add_filter(&prefix, !do_allowlisting); + } else { + ret = net_ipv6_pe_del_filter(&prefix); + } + + if (ret < 0) { + if (ret == -EALREADY) { + PR("Filter %s already in %s list\n", + net_sprint_ipv6_addr(&prefix), + do_allowlisting ? "allow" : "deny"); + } else if (ret == -ENOENT) { + PR("No such filter %s found\n", + net_sprint_ipv6_addr(&prefix)); + } else { + PR("Cannot %s %s %sfilter (%d)\n", + do_add ? "add" : "delete", + argv[arg], + do_add ? + (do_allowlisting ? "allowlist " : + "denylist ") : "", + ret); + } + + return 0; + } + + PR("%s %s%sfilter for %s\n", + do_add ? "Added" : "Deleted", + do_add ? (do_allowlisting ? "allow" : "deny") : "", + do_add ? " list " : "", + argv[arg]); +#else + PR("IPv6 privacy extension filter support is disabled.\n"); + PR("Set CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 to enable it.\n"); +#endif +#else /* CONFIG_NET_NATIVE_IPV6 */ + PR_INFO("Set %s and %s to enable native %s support.\n", + "CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6"); +#endif /* CONFIG_NET_NATIVE_IPV6 */ + return 0; +} + SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ip6, SHELL_CMD(add, NULL, "'net ipv6 add

' adds the address to the interface.", @@ -299,6 +444,15 @@ SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ip6, SHELL_CMD(del, NULL, "'net ipv6 del
' deletes the address from the interface.", cmd_net_ip6_del), + SHELL_CMD(pe, NULL, + "net ipv6 pe add [allow|deny] \n" + "Add IPv6 address to filter list. The allow/deny " + "parameter tells if this is allow listed (accepted) or " + "deny listed (declined) prefix. Default is to allow list " + "the prefix.\n" + "ipv6 pe del \n" + "Delete IPv6 address from filter list.", + cmd_net_ip6_pe), SHELL_SUBCMD_SET_END ); From 2280b9f326c6eeac57074f36b55704d4bcef3261 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0207/1389] net: ipv6: Add Privacy Extension events to net_mgmt Add events to be generated when privacy extension is enabled or disabled, or when allow/deny filter is added or deleted. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_event.h | 31 +++++++++++++++++++++++++++++++ subsys/net/ip/ipv6_pe.c | 32 ++++++++++++++++++++++++++++++++ subsys/net/lib/shell/events.c | 20 ++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index 6198fc28bfbb3a..3d2be01fd9002f 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -82,6 +82,10 @@ enum net_event_ipv6_cmd { NET_EVENT_IPV6_CMD_DHCP_BOUND, NET_EVENT_IPV6_CMD_DHCP_STOP, NET_EVENT_IPV6_CMD_ADDR_DEPRECATED, + NET_EVENT_IPV6_CMD_PE_ENABLED, + NET_EVENT_IPV6_CMD_PE_DISABLED, + NET_EVENT_IPV6_CMD_PE_FILTER_ADD, + NET_EVENT_IPV6_CMD_PE_FILTER_DEL, }; #define NET_EVENT_IPV6_ADDR_ADD \ @@ -144,6 +148,18 @@ enum net_event_ipv6_cmd { #define NET_EVENT_IPV6_ADDR_DEPRECATED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEPRECATED) +#define NET_EVENT_IPV6_PE_ENABLED \ + (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_ENABLED) + +#define NET_EVENT_IPV6_PE_DISABLED \ + (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_DISABLED) + +#define NET_EVENT_IPV6_PE_FILTER_ADD \ + (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_FILTER_ADD) + +#define NET_EVENT_IPV6_PE_FILTER_DEL \ + (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_FILTER_DEL) + /* IPv4 Events*/ #define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 #define _NET_IPV4_CORE_CODE 0x004 @@ -307,6 +323,21 @@ struct net_event_l4_hostname { char hostname[NET_HOSTNAME_SIZE]; }; +/** + * @brief Network Management event information structure + * Used to pass information on network events like + * NET_EVENT_IPV6_PE_FILTER_ADD and + * NET_EVENT_IPV6_PE_FILTER_DEL + * when CONFIG_NET_MGMT_EVENT_INFO is enabled and event generator pass the + * information. + * + * This is only available if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT is >0. + */ +struct net_event_ipv6_pe_filter { + struct in6_addr prefix; + bool is_deny_list; +}; + #ifdef __cplusplus } #endif diff --git a/subsys/net/ip/ipv6_pe.c b/subsys/net/ip/ipv6_pe.c index a2de2ddc786361..b44283ecc0d837 100644 --- a/subsys/net/ip/ipv6_pe.c +++ b/subsys/net/ip/ipv6_pe.c @@ -348,6 +348,7 @@ void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix, net_if_get_by_iface(iface)); NET_WARN("Disabling IPv6 PE for interface %d", net_if_get_by_iface(iface)); + net_mgmt_event_notify(NET_EVENT_IPV6_PE_DISABLED, iface); iface->pe_enabled = false; goto out; } @@ -468,6 +469,26 @@ static void ipv6_pe_recheck_filters(bool is_denylist) } #endif /* CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 */ +#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 +static void send_filter_event(struct in6_addr *addr, bool is_denylist, + int event_type) +{ + if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) { + struct net_event_ipv6_pe_filter info; + + net_ipaddr_copy(&info.prefix, addr); + info.is_deny_list = is_denylist; + + net_mgmt_event_notify_with_info(event_type, + NULL, + (const void *)&info, + sizeof(info)); + } else { + net_mgmt_event_notify(event_type, NULL); + } +} +#endif + int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_denylist) { #if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0 @@ -517,6 +538,9 @@ int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_denylist) ipv6_pe_denylist ? "deny" : "allow", net_sprint_ipv6_addr(&ipv6_pe_filter[free_slot])); + send_filter_event(&ipv6_pe_filter[free_slot], + is_denylist, + NET_EVENT_IPV6_PE_FILTER_ADD); out: k_mutex_unlock(&lock); @@ -542,8 +566,13 @@ int net_ipv6_pe_del_filter(struct in6_addr *addr) ipv6_pe_denylist ? "deny" : "allow", net_sprint_ipv6_addr(&ipv6_pe_filter[i])); + send_filter_event(&ipv6_pe_filter[i], + ipv6_pe_denylist, + NET_EVENT_IPV6_PE_FILTER_DEL); + net_ipaddr_copy(&ipv6_pe_filter[i], net_ipv6_unspecified_address()); + ret = 0; goto out; } @@ -699,11 +728,14 @@ int net_ipv6_pe_init(struct net_if *iface) int32_t lifetime; int ret = 0; + net_mgmt_event_notify(NET_EVENT_IPV6_PE_ENABLED, iface); + lifetime = TEMP_VALID_LIFETIME - REGEN_ADVANCE(net_if_ipv6_get_retrans_timer(iface), 1U); if (lifetime <= 0) { iface->pe_enabled = false; + net_mgmt_event_notify(NET_EVENT_IPV6_PE_DISABLED, iface); ret = -EINVAL; goto out; } diff --git a/subsys/net/lib/shell/events.c b/subsys/net/lib/shell/events.c index 27bd5a46e98f16..f7814982130206 100644 --- a/subsys/net/lib/shell/events.c +++ b/subsys/net/lib/shell/events.c @@ -194,6 +194,26 @@ static char *get_l3_desc(struct event_msg *msg, info = net_addr_ntop(AF_INET6, msg->data, extra_info, extra_info_len); break; + case NET_EVENT_IPV6_PE_ENABLED: + *desc = "IPv6 PE"; + *desc2 = "enabled"; + break; + case NET_EVENT_IPV6_PE_DISABLED: + *desc = "IPv6 PE"; + *desc2 = "disabled"; + break; + case NET_EVENT_IPV6_PE_FILTER_ADD: + *desc = "IPv6 PE filter"; + *desc2 = "add"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV6_PE_FILTER_DEL: + *desc = "IPv6 PE filter"; + *desc2 = "del"; + info = net_addr_ntop(AF_INET6, msg->data, extra_info, + extra_info_len); + break; case NET_EVENT_IPV4_ADDR_ADD: *desc = "IPv4 address"; *desc2 = "add"; From 067f66965ff243d0a7e5772ae7a1b3063f9a34b1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0208/1389] net: if: Remove IPv6 address when it expires No need to keep the expired addresses around, just remove it. Signed-off-by: Jukka Rissanen --- subsys/net/ip/net_if.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 43f493e7c1d654..8ac702b778b70d 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1695,13 +1695,23 @@ static void rejoin_ipv6_mcast_groups(struct net_if *iface) static void address_expired(struct net_if_addr *ifaddr) { - NET_DBG("IPv6 address %s is deprecated", + NET_DBG("IPv6 address %s is expired", net_sprint_ipv6_addr(&ifaddr->address.in6_addr)); sys_slist_find_and_remove(&active_address_lifetime_timers, &ifaddr->lifetime.node); net_timeout_set(&ifaddr->lifetime, 0, 0); + + STRUCT_SECTION_FOREACH(net_if, iface) { + ARRAY_FOR_EACH(iface->config.ip.ipv6->unicast, i) { + if (&iface->config.ip.ipv6->unicast[i] == ifaddr) { + net_if_ipv6_addr_rm(iface, + &iface->config.ip.ipv6->unicast[i].address.in6_addr); + return; + } + } + } } static void address_lifetime_timeout(struct k_work *work) From 778a938a01ccd03257cc48204dc8749ac0931d21 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0209/1389] net: Add ref counting to net_if_addr struct Add reference counting to network interface address (for both IPv4 and IPv6) so that the address is not removed if there are sockets using it. If the interface address is removed while there are sockets using it, the connectivity will fail for the said socket. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_if.h | 30 +++ subsys/net/ip/net_if.c | 440 ++++++++++++++++++++++++++---------- subsys/net/ip/tcp.c | 24 ++ subsys/net/ip/tcp_private.h | 1 + 4 files changed, 378 insertions(+), 117 deletions(-) diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 90ecea43882158..a2da496b122a8b 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -53,6 +53,11 @@ struct net_if_addr { /** IP address */ struct net_addr address; + /** Reference counter. This is used to prevent address removal if there + * are sockets that have bound the local endpoint to this address. + */ + atomic_t atomic_ref; + #if defined(CONFIG_NET_NATIVE_IPV6) struct net_timeout lifetime; #endif @@ -1156,6 +1161,31 @@ static inline int net_if_set_link_addr_unlocked(struct net_if *iface, int net_if_set_link_addr_locked(struct net_if *iface, uint8_t *addr, uint8_t len, enum net_link_type type); + +#if CONFIG_NET_IF_LOG_LEVEL >= LOG_LEVEL_DBG +extern int net_if_addr_unref_debug(struct net_if *iface, + sa_family_t family, + const void *addr, + const char *caller, int line); +#define net_if_addr_unref(iface, family, addr) \ + net_if_addr_unref_debug(iface, family, addr, __func__, __LINE__) + +extern struct net_if_addr *net_if_addr_ref_debug(struct net_if *iface, + sa_family_t family, + const void *addr, + const char *caller, + int line); +#define net_if_addr_ref(iface, family, addr) \ + net_if_addr_ref_debug(iface, family, addr, __func__, __LINE__) +#else +extern int net_if_addr_unref(struct net_if *iface, + sa_family_t family, + const void *addr); +extern struct net_if_addr *net_if_addr_ref(struct net_if *iface, + sa_family_t family, + const void *addr); +#endif /* CONFIG_NET_IF_LOG_LEVEL */ + /** @endcond */ /** diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 8ac702b778b70d..3dafda67bc21b0 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1820,6 +1820,7 @@ static inline void net_if_addr_init(struct net_if_addr *ifaddr, ifaddr->is_temporary = false; ifaddr->address.family = AF_INET6; ifaddr->addr_type = addr_type; + ifaddr->atomic_ref = ATOMIC_INIT(1); net_ipaddr_copy(&ifaddr->address.in6_addr, addr); @@ -1911,105 +1912,28 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface, bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr) { - bool ret = false; struct net_if_ipv6 *ipv6; - struct in6_addr maddr; - int found = -1; - unsigned int maddr_count = 0; + int ret; NET_ASSERT(addr); - net_if_lock(iface); - ipv6 = iface->config.ip.ipv6; if (!ipv6) { - goto out; - } - - net_ipv6_addr_create_solicited_node(addr, &maddr); - - ARRAY_FOR_EACH(ipv6->unicast, i) { - struct in6_addr unicast_maddr; - - if (!ipv6->unicast[i].is_used) { - continue; - } - - /* count how many times this solicited-node multicast address is identical - * for all the used unicast addresses - */ - net_ipv6_addr_create_solicited_node(&ipv6->unicast[i].address.in6_addr, - &unicast_maddr); - if (net_ipv6_addr_cmp(&maddr, &unicast_maddr)) { - maddr_count++; - } - - if (!net_ipv6_addr_cmp(&ipv6->unicast[i].address.in6_addr, - addr)) { - continue; - } - - found = i; + return false; } - if (found >= 0) { - if (!ipv6->unicast[found].is_infinite) { - k_mutex_lock(&lock, K_FOREVER); - - sys_slist_find_and_remove( - &active_address_lifetime_timers, - &ipv6->unicast[found].lifetime.node); - - if (sys_slist_is_empty( - &active_address_lifetime_timers)) { - k_work_cancel_delayable( - &address_lifetime_timer); - } - - k_mutex_unlock(&lock); - } - -#if defined(CONFIG_NET_IPV6_DAD) - if (!net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { - k_mutex_lock(&lock, K_FOREVER); - sys_slist_find_and_remove(&active_dad_timers, - &ipv6->unicast[found].dad_node); - k_mutex_unlock(&lock); - } -#endif - - ipv6->unicast[found].is_used = false; - - if (maddr_count == 1) { - /* remove the solicited-node multicast address only if no other - * unicast address is also using it - */ - net_if_ipv6_maddr_rm(iface, &maddr); - } - - NET_DBG("[%d] interface %d (%p) address %s type %s removed", - found, net_if_get_by_iface(iface), iface, - net_sprint_ipv6_addr(addr), - net_addr_type2str(ipv6->unicast[found].addr_type)); - - /* Using the IPv6 address pointer here can give false - * info if someone adds a new IP address into this position - * in the address array. This is quite unlikely thou. - */ - net_mgmt_event_notify_with_info( - NET_EVENT_IPV6_ADDR_DEL, - iface, - &ipv6->unicast[found].address.in6_addr, - sizeof(struct in6_addr)); + ret = net_if_addr_unref(iface, AF_INET6, addr); + if (ret > 0) { + NET_DBG("Address %s still in use (ref %d)", + net_sprint_ipv6_addr(addr), ret); + return false; - ret = true; - goto out; + } else if (ret < 0) { + NET_DBG("Address %s not found (%d)", + net_sprint_ipv6_addr(addr), ret); } -out: - net_if_unlock(iface); - - return ret; + return true; } bool z_impl_net_if_ipv6_addr_add_by_index(int index, @@ -4192,6 +4116,7 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface, ifaddr->address.in_addr.s4_addr32[0] = addr->s4_addr32[0]; ifaddr->addr_type = addr_type; + ifaddr->atomic_ref = ATOMIC_INIT(1); /* Caller has to take care of timers and their expiry */ if (vlifetime) { @@ -4226,44 +4151,27 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface, bool net_if_ipv4_addr_rm(struct net_if *iface, const struct in_addr *addr) { struct net_if_ipv4 *ipv4; - bool ret = false; + int ret; - net_if_lock(iface); + NET_ASSERT(addr); ipv4 = iface->config.ip.ipv4; if (!ipv4) { - goto out; + return false; } - ARRAY_FOR_EACH(ipv4->unicast, i) { - if (!ipv4->unicast[i].ipv4.is_used) { - continue; - } - - if (!net_ipv4_addr_cmp(&ipv4->unicast[i].ipv4.address.in_addr, - addr)) { - continue; - } - - ipv4->unicast[i].ipv4.is_used = false; - - NET_DBG("[%zu] interface %d (%p) address %s removed", - i, net_if_get_by_iface(iface), iface, - net_sprint_ipv4_addr(addr)); - - net_mgmt_event_notify_with_info( - NET_EVENT_IPV4_ADDR_DEL, iface, - &ipv4->unicast[i].ipv4.address.in_addr, - sizeof(struct in_addr)); + ret = net_if_addr_unref(iface, AF_INET, addr); + if (ret > 0) { + NET_DBG("Address %s still in use (ref %d)", + net_sprint_ipv4_addr(addr), ret); + return false; - ret = true; - goto out; + } else if (ret < 0) { + NET_DBG("Address %s not found (%d)", + net_sprint_ipv4_addr(addr), ret); } -out: - net_if_unlock(iface); - - return ret; + return true; } bool z_impl_net_if_ipv4_addr_add_by_index(int index, @@ -4636,6 +4544,304 @@ struct net_if *net_if_select_src_iface(const struct sockaddr *dst) return iface; } +static struct net_if_addr *get_ifaddr(struct net_if *iface, + sa_family_t family, + const void *addr, + unsigned int *mcast_addr_count) +{ + struct net_if_addr *ifaddr = NULL; + + net_if_lock(iface); + + if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) { + struct net_if_ipv6 *ipv6 = + COND_CODE_1(CONFIG_NET_NATIVE_IPV6, (iface->config.ip.ipv6), (NULL)); + + struct in6_addr maddr; + unsigned int maddr_count = 0; + int found = -1; + + net_ipv6_addr_create_solicited_node((struct in6_addr *)addr, + &maddr); + + ARRAY_FOR_EACH(ipv6->unicast, i) { + struct in6_addr unicast_maddr; + + if (!ipv6->unicast[i].is_used) { + continue; + } + + /* Count how many times this solicited-node multicast address is identical + * for all the used unicast addresses + */ + net_ipv6_addr_create_solicited_node( + &ipv6->unicast[i].address.in6_addr, + &unicast_maddr); + + if (net_ipv6_addr_cmp(&maddr, &unicast_maddr)) { + maddr_count++; + } + + if (!net_ipv6_addr_cmp(&ipv6->unicast[i].address.in6_addr, addr)) { + continue; + } + + found = i; + } + + if (found >= 0) { + ifaddr = &ipv6->unicast[found]; + + if (mcast_addr_count != NULL) { + *mcast_addr_count = maddr_count; + } + } + + goto out; + } + + if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) { + struct net_if_ipv4 *ipv4 = + COND_CODE_1(CONFIG_NET_NATIVE_IPV4, (iface->config.ip.ipv4), (NULL)); + + ARRAY_FOR_EACH(ipv4->unicast, i) { + if (!ipv4->unicast[i].ipv4.is_used) { + continue; + } + + if (!net_ipv4_addr_cmp(&ipv4->unicast[i].ipv4.address.in_addr, + addr)) { + continue; + } + + ifaddr = &ipv4->unicast[i].ipv4; + + goto out; + } + } + +out: + net_if_unlock(iface); + + return ifaddr; +} + +static void remove_ipv6_ifaddr(struct net_if *iface, + struct net_if_addr *ifaddr, + unsigned int maddr_count) +{ + struct net_if_ipv6 *ipv6; + + net_if_lock(iface); + + ipv6 = COND_CODE_1(CONFIG_NET_NATIVE_IPV6, (iface->config.ip.ipv6), (NULL)); + if (!ipv6) { + goto out; + } + + if (!ifaddr->is_infinite) { + k_mutex_lock(&lock, K_FOREVER); + +#if defined(CONFIG_NET_NATIVE_IPV6) + sys_slist_find_and_remove(&active_address_lifetime_timers, + &ifaddr->lifetime.node); + + if (sys_slist_is_empty(&active_address_lifetime_timers)) { + k_work_cancel_delayable(&address_lifetime_timer); + } +#endif + k_mutex_unlock(&lock); + } + +#if defined(CONFIG_NET_IPV6_DAD) + if (!net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { + k_mutex_lock(&lock, K_FOREVER); + sys_slist_find_and_remove(&active_dad_timers, + &ifaddr->dad_node); + k_mutex_unlock(&lock); + } +#endif + + if (maddr_count == 1) { + /* Remove the solicited-node multicast address only if no other + * unicast address is also using it + */ + struct in6_addr maddr; + + net_ipv6_addr_create_solicited_node(&ifaddr->address.in6_addr, + &maddr); + net_if_ipv6_maddr_rm(iface, &maddr); + } + + /* Using the IPv6 address pointer here can give false + * info if someone adds a new IP address into this position + * in the address array. This is quite unlikely thou. + */ + net_mgmt_event_notify_with_info(NET_EVENT_IPV6_ADDR_DEL, + iface, + &ifaddr->address.in6_addr, + sizeof(struct in6_addr)); +out: + net_if_unlock(iface); +} + +static void remove_ipv4_ifaddr(struct net_if *iface, + struct net_if_addr *ifaddr) +{ + struct net_if_ipv4 *ipv4; + + net_if_lock(iface); + + ipv4 = COND_CODE_1(CONFIG_NET_NATIVE_IPV4, (iface->config.ip.ipv4), (NULL)); + if (!ipv4) { + goto out; + } + + net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ADDR_DEL, + iface, + &ifaddr->address.in_addr, + sizeof(struct in_addr)); +out: + net_if_unlock(iface); +} + +#if defined(CONFIG_NET_IF_LOG_LEVEL) +#define NET_LOG_LEVEL CONFIG_NET_IF_LOG_LEVEL +#else +#define NET_LOG_LEVEL 0 +#endif + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG +struct net_if_addr *net_if_addr_ref_debug(struct net_if *iface, + sa_family_t family, + const void *addr, + const char *caller, + int line) +#else +struct net_if_addr *net_if_addr_ref(struct net_if *iface, + sa_family_t family, + const void *addr) +#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */ +{ + struct net_if_addr *ifaddr; + atomic_val_t ref; + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + char addr_str[IS_ENABLED(CONFIG_NET_IPV6) ? + INET6_ADDRSTRLEN : INET_ADDRSTRLEN]; + + __ASSERT(iface, "iface is NULL (%s():%d)", caller, line); +#endif + + ifaddr = get_ifaddr(iface, family, addr, NULL); + + do { + ref = ifaddr ? atomic_get(&ifaddr->atomic_ref) : 0; + if (!ref) { +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + NET_ERR("iface %d addr %s (%s():%d)", + net_if_get_by_iface(iface), + net_addr_ntop(family, + addr, + addr_str, sizeof(addr_str)), + caller, line); +#endif + return NULL; + } + } while (!atomic_cas(&ifaddr->atomic_ref, ref, ref + 1)); + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + NET_DBG("[%d] ifaddr %s state %d ref %ld (%s():%d)", + net_if_get_by_iface(iface), + net_addr_ntop(ifaddr->address.family, + (void *)&ifaddr->address.in_addr, + addr_str, sizeof(addr_str)), + ifaddr->addr_state, + ref + 1, + caller, line); +#endif + + return ifaddr; +} + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG +int net_if_addr_unref_debug(struct net_if *iface, + sa_family_t family, + const void *addr, + const char *caller, int line) +#else +int net_if_addr_unref(struct net_if *iface, + sa_family_t family, + const void *addr) +#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */ +{ + struct net_if_addr *ifaddr; + unsigned int maddr_count = 0; + atomic_val_t ref; + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + char addr_str[IS_ENABLED(CONFIG_NET_IPV6) ? + INET6_ADDRSTRLEN : INET_ADDRSTRLEN]; + + __ASSERT(iface, "iface is NULL (%s():%d)", caller, line); +#endif + + ifaddr = get_ifaddr(iface, family, addr, &maddr_count); + + if (!ifaddr) { +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + NET_ERR("iface %d addr %s (%s():%d)", + net_if_get_by_iface(iface), + net_addr_ntop(family, + addr, + addr_str, sizeof(addr_str)), + caller, line); +#endif + return -EINVAL; + } + + do { + ref = atomic_get(&ifaddr->atomic_ref); + if (!ref) { +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + NET_ERR("*** ERROR *** iface %d ifaddr %p " + "is freed already (%s():%d)", + net_if_get_by_iface(iface), + ifaddr, + caller, line); +#endif + return -EINVAL; + } + + } while (!atomic_cas(&ifaddr->atomic_ref, ref, ref - 1)); + +#if NET_LOG_LEVEL >= LOG_LEVEL_DBG + NET_DBG("[%d] ifaddr %s state %d ref %ld (%s():%d)", + net_if_get_by_iface(iface), + net_addr_ntop(ifaddr->address.family, + (void *)&ifaddr->address.in_addr, + addr_str, sizeof(addr_str)), + ifaddr->addr_state, + ref - 1, caller, line); +#endif + + if (ref > 1) { + return ref - 1; + } + + ifaddr->is_used = false; + + if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6 && addr != NULL) { + remove_ipv6_ifaddr(iface, ifaddr, maddr_count); + } + + if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET && addr != NULL) { + remove_ipv4_ifaddr(iface, ifaddr); + } + + return 0; +} + enum net_verdict net_if_recv_data(struct net_if *iface, struct net_pkt *pkt) { if (IS_ENABLED(CONFIG_NET_PROMISCUOUS_MODE) && diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 8d72e45c164727..2002b7d32c008f 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -731,6 +731,16 @@ static void tcp_conn_release(struct k_work *work) conn->context->conn_handler = NULL; } + /* As the TCP socket could be closed without connect being called, + * check if the address reference is done before releasing the address. + */ + if (conn->iface != NULL && conn->addr_ref_done) { + net_if_addr_unref(conn->iface, conn->src.sa.sa_family, + conn->src.sa.sa_family == AF_INET ? + (const void *)&conn->src.sin.sin_addr : + (const void *)&conn->src.sin6.sin6_addr); + } + conn->context->tcp = NULL; conn->state = TCP_UNUSED; @@ -2060,6 +2070,7 @@ static struct tcp *tcp_conn_alloc(void) conn->send_win_max = MAX(tcp_tx_window, NET_IPV6_MTU); conn->send_win = conn->send_win_max; conn->tcp_nodelay = false; + conn->addr_ref_done = false; #ifdef CONFIG_NET_TCP_FAST_RETRANSMIT conn->dup_ack_cnt = 0; #endif @@ -2413,6 +2424,13 @@ static struct tcp *tcp_conn_new(struct net_pkt *pkt) conn = NULL; goto err; } + + net_if_addr_ref(conn->iface, conn->dst.sa.sa_family, + conn->src.sa.sa_family == AF_INET ? + (const void *)&conn->src.sin.sin_addr : + (const void *)&conn->src.sin6.sin6_addr); + conn->addr_ref_done = true; + err: if (!conn) { net_stats_update_tcp_seg_conndrop(net_pkt_iface(pkt)); @@ -3833,6 +3851,12 @@ int net_tcp_connect(struct net_context *context, goto out; } + net_if_addr_ref(conn->iface, conn->src.sa.sa_family, + conn->src.sa.sa_family == AF_INET ? + (const void *)&conn->src.sin.sin_addr : + (const void *)&conn->src.sin6.sin6_addr); + conn->addr_ref_done = true; + conn->connect_cb = cb; context->user_data = user_data; diff --git a/subsys/net/ip/tcp_private.h b/subsys/net/ip/tcp_private.h index 3c4462292ade7b..b125331eec274b 100644 --- a/subsys/net/ip/tcp_private.h +++ b/subsys/net/ip/tcp_private.h @@ -336,6 +336,7 @@ struct tcp { /* TCP connection */ bool keep_alive : 1; #endif /* CONFIG_NET_TCP_KEEPALIVE */ bool tcp_nodelay : 1; + bool addr_ref_done : 1; }; #define _flags(_fl, _op, _mask, _cond) \ From 1d0255f0e5683721304433f3dd92adaea102a4f1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0210/1389] tests: net: udp: Add address reference counting tests Make sure that address reference counting works as expected. Signed-off-by: Jukka Rissanen --- tests/net/socket/udp/src/main.c | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/net/socket/udp/src/main.c b/tests/net/socket/udp/src/main.c index 3046630906d2db..42cfe6b43a598e 100644 --- a/tests/net/socket/udp/src/main.c +++ b/tests/net/socket/udp/src/main.c @@ -2408,6 +2408,47 @@ ZTEST_USER(net_socket_udp, test_35_recvmsg_msg_controllen_update) zassert_equal(rv, 0, "close failed"); } +ZTEST(net_socket_udp, test_36_v6_address_removal) +{ + int ret; + bool status; + int client_sock; + struct sockaddr_in6 client_addr; + struct net_if_addr *ifaddr; + struct net_if *iface; + + if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) { + return; + } + + ifaddr = net_if_ipv6_addr_lookup(&my_addr1, &iface); + zassert_equal(ifaddr->atomic_ref, 1, "Ref count is wrong (%ld vs %ld)", + ifaddr->atomic_ref, 1); + + prepare_sock_udp_v6(MY_IPV6_ADDR_ETH, CLIENT_PORT, &client_sock, &client_addr); + + ret = zsock_bind(client_sock, + (struct sockaddr *)&client_addr, + sizeof(client_addr)); + zassert_equal(ret, 0, "client bind failed"); + + status = net_if_ipv6_addr_rm(eth_iface, &my_addr1); + zassert_false(status, "Address could be removed"); + + ifaddr = net_if_ipv6_addr_lookup(&my_addr1, &iface); + zassert_not_null(ifaddr, "Address %s not found", + net_sprint_ipv6_addr(&my_addr1)); + + ret = zsock_close(client_sock); + zassert_equal(ret, 0, "close failed"); + + ifaddr = net_if_ipv6_addr_lookup(&my_addr1, &iface); + zassert_equal(iface, eth_iface, "Invalid interface %p vs %p", + iface, eth_iface); + zassert_is_null(ifaddr, "Address %s found", + net_sprint_ipv6_addr(&my_addr1)); +} + static void after(void *arg) { ARG_UNUSED(arg); From 3b3539e9a3dfa5ca2be36c4d3e8cc064a4976283 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0211/1389] net: shell: Print ref count information for IPv4 and IPv6 addresses When printing IPv4 and IPv6 address information in "net ipv4" and "net ipv6" commands, print also reference count of the IP address. This is useful for debugging purposes. Signed-off-by: Jukka Rissanen --- subsys/net/lib/shell/ipv4.c | 17 +++++++++-------- subsys/net/lib/shell/ipv6.c | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/subsys/net/lib/shell/ipv4.c b/subsys/net/lib/shell/ipv4.c index cc2e7e30d70b9f..2e6d4ccf7d6fd7 100644 --- a/subsys/net/lib/shell/ipv4.c +++ b/subsys/net/lib/shell/ipv4.c @@ -32,7 +32,7 @@ static void ip_address_lifetime_cb(struct net_if *iface, void *user_data) return; } - PR("Type \tState \tLifetime (sec)\tAddress\n"); + PR("Type \tState \tRef\tAddress\n"); ARRAY_FOR_EACH(ipv4->unicast, i) { if (!ipv4->unicast[i].ipv4.is_used || @@ -40,13 +40,14 @@ static void ip_address_lifetime_cb(struct net_if *iface, void *user_data) continue; } - PR("%s \t%s \t%12s/%12s\n", - addrtype2str(ipv4->unicast[i].ipv4.addr_type), - addrstate2str(ipv4->unicast[i].ipv4.addr_state), - net_sprint_ipv4_addr( - &ipv4->unicast[i].ipv4.address.in_addr), - net_sprint_ipv4_addr( - &ipv4->unicast[i].netmask)); + PR("%s \t%s \t%ld\t%s/%s\n", + addrtype2str(ipv4->unicast[i].ipv4.addr_type), + addrstate2str(ipv4->unicast[i].ipv4.addr_state), + atomic_get(&ipv4->unicast[i].ipv4.atomic_ref), + net_sprint_ipv4_addr( + &ipv4->unicast[i].ipv4.address.in_addr), + net_sprint_ipv4_addr( + &ipv4->unicast[i].netmask)); } } #endif /* CONFIG_NET_NATIVE_IPV4 */ diff --git a/subsys/net/lib/shell/ipv6.c b/subsys/net/lib/shell/ipv6.c index d432ca730f1950..b9a9252f1acce6 100644 --- a/subsys/net/lib/shell/ipv6.c +++ b/subsys/net/lib/shell/ipv6.c @@ -96,12 +96,12 @@ static void address_lifetime_cb(struct net_if *iface, void *user_data) return; } - PR("Type \tState \tLifetime (sec)\tAddress\n"); + PR("Type \tState \tLifetime (sec)\tRef\tAddress\n"); ARRAY_FOR_EACH(ipv6->unicast, i) { struct net_if_ipv6_prefix *prefix; char remaining_str[sizeof("01234567890")]; - uint64_t remaining; + uint32_t remaining; uint8_t prefix_len; if (!ipv6->unicast[i].is_used || @@ -125,13 +125,13 @@ static void address_lifetime_cb(struct net_if *iface, void *user_data) "infinite"); } else { snprintk(remaining_str, sizeof(remaining_str) - 1, - "%u", (uint32_t)(remaining / 1000U)); + "%u", remaining); } - PR("%s \t%s\t%s \t%s/%d%s\n", + PR("%s \t%s\t%14s\t%ld\t%s/%d%s\n", addrtype2str(ipv6->unicast[i].addr_type), addrstate2str(ipv6->unicast[i].addr_state), - remaining_str, + remaining_str, atomic_get(&ipv6->unicast[i].atomic_ref), net_sprint_ipv6_addr(&ipv6->unicast[i].address.in6_addr), prefix_len, ipv6->unicast[i].is_temporary ? " (temporary)" : ""); From d0ff77a2b91e2c7c175d142acd580055bfc89cab Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0212/1389] net: Add IPv6 source address selection support Add support for IPv6 Source Address Selection defined in RFC 5014. This commit does not add any address selection support to getaddrinfo() as described in the RFC. The AI_EXTFLAGS symbol and also the ai_eflags to hints is added but they are not used by the code. The public/temporary address selection is only done internally by the net_if_ipv6_select_src_addr_hint() according to flags set by setsockopt(). Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_context.h | 8 ++++ include/zephyr/net/net_if.h | 29 +++++++++++++ include/zephyr/net/socket.h | 24 +++++++++++ subsys/net/ip/net_context.c | 48 +++++++++++++++++++-- subsys/net/ip/net_if.c | 72 ++++++++++++++++++++++---------- subsys/net/lib/sockets/sockets.c | 32 ++++++++++++++ 6 files changed, 188 insertions(+), 25 deletions(-) diff --git a/include/zephyr/net/net_context.h b/include/zephyr/net/net_context.h index 658a0767c02cae..7c0de1eccd662e 100644 --- a/include/zephyr/net/net_context.h +++ b/include/zephyr/net/net_context.h @@ -348,6 +348,13 @@ __net_socket struct net_context { #if defined(CONFIG_NET_CONTEXT_RECV_PKTINFO) /** Receive network packet information in recvmsg() call */ bool recv_pktinfo; +#endif +#if defined(CONFIG_NET_IPV6) + /** + * Source address selection preferences. Currently used only for IPv6, + * see RFC 5014 for details. + */ + uint16_t addr_preferences; #endif } options; @@ -1268,6 +1275,7 @@ enum net_context_option { NET_OPT_MCAST_HOP_LIMIT = 14, NET_OPT_UNICAST_HOP_LIMIT = 15, NET_OPT_TTL = 16, + NET_OPT_ADDR_PREFERENCES = 17, }; /** diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index a2da496b122a8b..9c27e08d2c26a7 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -1995,6 +1995,35 @@ static inline const struct in6_addr *net_if_ipv6_select_src_addr( } #endif +/** + * @brief Get a IPv6 source address that should be used when sending + * network data to destination. Use a hint set to the socket to select + * the proper address. + * + * @param iface Interface that was used when packet was received. + * If the interface is not known, then NULL can be given. + * @param dst IPv6 destination address + * @param flags Hint from the related socket. See RFC 5014 for value details. + * + * @return Pointer to IPv6 address to use, NULL if no IPv6 address + * could be found. + */ +#if defined(CONFIG_NET_NATIVE_IPV6) +const struct in6_addr *net_if_ipv6_select_src_addr_hint(struct net_if *iface, + const struct in6_addr *dst, + int flags); +#else +static inline const struct in6_addr *net_if_ipv6_select_src_addr_hint( + struct net_if *iface, const struct in6_addr *dst, int flags) +{ + ARG_UNUSED(iface); + ARG_UNUSED(dst); + ARG_UNUSED(flags); + + return NULL; +} +#endif + /** * @brief Get a network interface that should be used when sending * IPv6 network data to destination. diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 1800533a25062f..7dfa893477473c 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -283,6 +283,7 @@ struct zsock_addrinfo { int ai_family; /**< Address family of the returned addresses */ int ai_socktype; /**< Socket type, for example SOCK_STREAM or SOCK_DGRAM */ int ai_protocol; /**< Protocol for addresses, 0 means any protocol */ + int ai_eflags; /**< Extended flags for special usage */ socklen_t ai_addrlen; /**< Length of the socket address */ struct sockaddr *ai_addr; /**< Pointer to the address */ char *ai_canonname; /**< Optional official name of the host */ @@ -765,6 +766,8 @@ __syscall int z_zsock_getaddrinfo_internal(const char *host, #define AI_ADDRCONFIG 0x20 /** Assume service (port) is numeric */ #define AI_NUMERICSERV 0x400 +/** Extra flags present (see RFC 5014) */ +#define AI_EXTFLAGS 0x800 /** @} */ /** @@ -1278,6 +1281,27 @@ struct ipv6_mreq { */ #define IPV6_RECVPKTINFO 49 +/** RFC5014: Source address selection. */ +#define IPV6_ADDR_PREFERENCES 72 + +/** Prefer temporary address as source. */ +#define IPV6_PREFER_SRC_TMP 0x0001 +/** Prefer public address as source. */ +#define IPV6_PREFER_SRC_PUBLIC 0x0002 +/** Either public or temporary address is selected as a default source + * depending on the output interface configuration (this is the default value). + * This is Linux specific option not found in the RFC. + */ +#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 +/** Prefer Care-of address as source. Ignored in Zephyr. */ +#define IPV6_PREFER_SRC_COA 0x0004 +/** Prefer Home address as source. Ignored in Zephyr. */ +#define IPV6_PREFER_SRC_HOME 0x0400 +/** Prefer CGA (Cryptographically Generated Address) address as source. Ignored in Zephyr. */ +#define IPV6_PREFER_SRC_CGA 0x0008 +/** Prefer non-CGA address as source. Ignored in Zephyr. */ +#define IPV6_PREFER_SRC_NONCGA 0x0800 + /** * @brief Incoming IPv6 packet information. * diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 5ec66ee7240197..84edc97edf3983 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -468,6 +468,10 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto, net_context_set_type(&contexts[i], type); net_context_set_proto(&contexts[i], proto); +#if defined(CONFIG_NET_IPV6) + contexts[i].options.addr_preferences = IPV6_PREFER_SRC_PUBTMP_DEFAULT; +#endif + #if defined(CONFIG_NET_CONTEXT_RCVTIMEO) contexts[i].options.rcvtimeo = K_FOREVER; #endif @@ -1131,10 +1135,10 @@ int net_context_create_ipv6_new(struct net_context *context, src = ((struct sockaddr_in6_ptr *)&context->local)->sin6_addr; } - if (net_ipv6_is_addr_unspecified(src) - || net_ipv6_is_addr_mcast(src)) { - src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt), - (struct in6_addr *)dst); + if (net_ipv6_is_addr_unspecified(src) || net_ipv6_is_addr_mcast(src)) { + src = net_if_ipv6_select_src_addr_hint(net_pkt_iface(pkt), + (struct in6_addr *)dst, + context->options.addr_preferences); } #if defined(CONFIG_NET_CONTEXT_DSCP_ECN) @@ -1711,6 +1715,21 @@ static int get_context_recv_pktinfo(struct net_context *context, #endif } +static int get_context_addr_preferences(struct net_context *context, + void *value, size_t *len) +{ +#if defined(CONFIG_NET_IPV6) + return get_uint16_option(context->options.addr_preferences, + value, len); +#else + ARG_UNUSED(context); + ARG_UNUSED(value); + ARG_UNUSED(len); + + return -ENOTSUP; +#endif +} + /* If buf is not NULL, then use it. Otherwise read the data to be written * to net_pkt from msghdr. */ @@ -3001,6 +3020,21 @@ static int set_context_recv_pktinfo(struct net_context *context, #endif } +static int set_context_addr_preferences(struct net_context *context, + const void *value, size_t len) +{ +#if defined(CONFIG_NET_IPV6) + return set_uint16_option(&context->options.addr_preferences, + value, len); +#else + ARG_UNUSED(context); + ARG_UNUSED(value); + ARG_UNUSED(len); + + return -ENOTSUP; +#endif +} + int net_context_set_option(struct net_context *context, enum net_context_option option, const void *value, size_t len) @@ -3064,6 +3098,9 @@ int net_context_set_option(struct net_context *context, case NET_OPT_RECV_PKTINFO: ret = set_context_recv_pktinfo(context, value, len); break; + case NET_OPT_ADDR_PREFERENCES: + ret = set_context_addr_preferences(context, value, len); + break; } k_mutex_unlock(&context->lock); @@ -3134,6 +3171,9 @@ int net_context_get_option(struct net_context *context, case NET_OPT_RECV_PKTINFO: ret = get_context_recv_pktinfo(context, value, len); break; + case NET_OPT_ADDR_PREFERENCES: + ret = get_context_addr_preferences(context, value, len); + break; } k_mutex_unlock(&context->lock); diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 3dafda67bc21b0..0316faa498535a 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -24,6 +24,7 @@ LOG_MODULE_REGISTER(net_if, CONFIG_NET_IF_LOG_LEVEL); #include #include #include +#include #include #include "net_private.h" @@ -2920,28 +2921,40 @@ static inline bool is_proper_ipv6_address(struct net_if_addr *addr) return false; } -static bool use_public_address(bool prefer_public, bool is_temporary) +static bool use_public_address(bool prefer_public, bool is_temporary, + int flags) { if (IS_ENABLED(CONFIG_NET_IPV6_PE)) { if (!prefer_public && is_temporary) { + + /* Allow socket to override the kconfig option */ + if (flags & IPV6_PREFER_SRC_PUBLIC) { + return true; + } + return false; } } + if (flags & IPV6_PREFER_SRC_TMP) { + return false; + } + return true; } static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, const struct in6_addr *dst, uint8_t prefix_len, - uint8_t *best_so_far) + uint8_t *best_so_far, + int flags) { struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6; struct net_if_addr *public_addr = NULL; struct in6_addr *src = NULL; uint8_t public_addr_len = 0; - struct in6_addr *temp_addr; - uint8_t len, temp_addr_len; + struct in6_addr *temp_addr = NULL; + uint8_t len, temp_addr_len = 0; bool ret; net_if_lock(iface); @@ -2951,14 +2964,6 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, goto out; } - if (IS_ENABLED(CONFIG_NET_IPV6_PE)) { - temp_addr = NULL; - temp_addr_len = 0; - } else { - ARG_UNUSED(temp_addr); - ARG_UNUSED(temp_addr_len); - } - ARRAY_FOR_EACH(ipv6->unicast, i) { if (!is_proper_ipv6_address(&ipv6->unicast[i])) { continue; @@ -2979,10 +2984,14 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, } ret = use_public_address(iface->pe_prefer_public, - ipv6->unicast[i].is_temporary); + ipv6->unicast[i].is_temporary, + flags); if (!ret) { temp_addr = &ipv6->unicast[i].address.in6_addr; temp_addr_len = len; + + *best_so_far = len; + src = &ipv6->unicast[i].address.in6_addr; continue; } @@ -3003,10 +3012,20 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, } } else { /* By default prefer always public address if found */ - if (public_addr && - !net_ipv6_addr_cmp(&public_addr->address.in6_addr, src)) { - src = &public_addr->address.in6_addr; - *best_so_far = public_addr_len; + if (flags & IPV6_PREFER_SRC_PUBLIC) { +use_public: + if (public_addr && + !net_ipv6_addr_cmp(&public_addr->address.in6_addr, src)) { + src = &public_addr->address.in6_addr; + *best_so_far = public_addr_len; + } + } else if (flags & IPV6_PREFER_SRC_TMP) { + if (temp_addr && !net_ipv6_addr_cmp(temp_addr, src)) { + src = temp_addr; + *best_so_far = temp_addr_len; + } + } else if (flags & IPV6_PREFER_SRC_PUBTMP_DEFAULT) { + goto use_public; } } @@ -3016,8 +3035,9 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface, return src; } -const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, - const struct in6_addr *dst) +const struct in6_addr *net_if_ipv6_select_src_addr_hint(struct net_if *dst_iface, + const struct in6_addr *dst, + int flags) { const struct in6_addr *src = NULL; uint8_t best_match = 0U; @@ -3037,14 +3057,16 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, if (dst_iface) { src = net_if_ipv6_get_best_match(dst_iface, dst, prefix_len, - &best_match); + &best_match, + flags); } else { STRUCT_SECTION_FOREACH(net_if, iface) { struct in6_addr *addr; addr = net_if_ipv6_get_best_match(iface, dst, prefix_len, - &best_match); + &best_match, + flags); if (addr) { src = addr; } @@ -3082,6 +3104,14 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, return src; } +const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface, + const struct in6_addr *dst) +{ + return net_if_ipv6_select_src_addr_hint(dst_iface, + dst, + IPV6_PREFER_SRC_PUBTMP_DEFAULT); +} + struct net_if *net_if_ipv6_select_src_iface(const struct in6_addr *dst) { struct net_if *iface = NULL; diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index e153cd173bbb5c..aa435a0ed049f0 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -2692,6 +2692,22 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname, break; + case IPV6_ADDR_PREFERENCES: + if (IS_ENABLED(CONFIG_NET_IPV6)) { + ret = net_context_get_option(ctx, + NET_OPT_ADDR_PREFERENCES, + optval, + optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + + break; + case IPV6_TCLASS: if (IS_ENABLED(CONFIG_NET_CONTEXT_DSCP_ECN)) { ret = net_context_get_option(ctx, @@ -3276,6 +3292,22 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname, break; + case IPV6_ADDR_PREFERENCES: + if (IS_ENABLED(CONFIG_NET_IPV6)) { + ret = net_context_set_option(ctx, + NET_OPT_ADDR_PREFERENCES, + optval, + optlen); + if (ret < 0) { + errno = -ret; + return -1; + } + + return 0; + } + + break; + case IPV6_TCLASS: if (IS_ENABLED(CONFIG_NET_CONTEXT_DSCP_ECN)) { ret = net_context_set_option(ctx, From 054e51b1afcd4a638c40d5b59f3f72a508f3289f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0213/1389] tests: net: ipv6: Add address selection tests Make sure the IPv6 source address selection works as expected when using the IPV6_ADDR_PREFERENCES socket option. Signed-off-by: Jukka Rissanen --- tests/net/socket/udp/src/main.c | 79 +++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tests/net/socket/udp/src/main.c b/tests/net/socket/udp/src/main.c index 42cfe6b43a598e..f13a8e3c9829e0 100644 --- a/tests/net/socket/udp/src/main.c +++ b/tests/net/socket/udp/src/main.c @@ -945,6 +945,8 @@ static ZTEST_BMEM bool test_failed; static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; static struct in_addr my_addr2 = { { { 192, 0, 2, 2 } } }; +static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x3 } } }; static uint8_t server_lladdr[] = { 0x01, 0x02, 0x03, 0xff, 0xfe, 0x04, 0x05, 0x06 }; static struct net_linkaddr server_link_addr = { @@ -2449,6 +2451,83 @@ ZTEST(net_socket_udp, test_36_v6_address_removal) net_sprint_ipv6_addr(&my_addr1)); } +static void check_ipv6_address_preferences(struct net_if *iface, + uint16_t preference, + const struct in6_addr *addr, + const struct in6_addr *dest) +{ + const struct in6_addr *selected; + size_t optlen; + int optval; + int sock; + int ret; + + sock = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + zassert_true(sock >= 0, "Cannot create socket (%d)", -errno); + + optval = preference; + ret = zsock_setsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, + &optval, sizeof(optval)); + zassert_equal(ret, 0, "setsockopt failed (%d)", errno); + + optval = 0; optlen = 0U; + ret = zsock_getsockopt(sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, + &optval, &optlen); + zassert_equal(ret, 0, "setsockopt failed (%d)", errno); + zassert_equal(optlen, sizeof(optval), "invalid optlen %d vs %d", + optlen, sizeof(optval)); + zassert_equal(optval, preference, + "getsockopt address preferences"); + + selected = net_if_ipv6_select_src_addr_hint(iface, + dest, + preference); + ret = net_ipv6_addr_cmp(addr, selected); + zassert_true(ret, "Wrong address %s selected, expected %s", + net_sprint_ipv6_addr(selected), + net_sprint_ipv6_addr(addr)); + + ret = zsock_close(sock); + zassert_equal(sock, 0, "Cannot close socket (%d)", -errno); +} + +ZTEST(net_socket_udp, test_37_ipv6_src_addr_select) +{ + struct net_if_addr *ifaddr; + const struct in6_addr dest = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; + + net_if_foreach(iface_cb, ð_iface); + zassert_not_null(eth_iface, "No ethernet interface found"); + + ifaddr = net_if_ipv6_addr_add(eth_iface, &my_addr1, + NET_ADDR_AUTOCONF, 0); + if (!ifaddr) { + DBG("Cannot add IPv6 address %s\n", + net_sprint_ipv6_addr(&my_addr1)); + zassert_not_null(ifaddr, "addr1"); + } + + ifaddr->is_temporary = false; + + ifaddr = net_if_ipv6_addr_add(eth_iface, &my_addr3, + NET_ADDR_AUTOCONF, 0); + if (!ifaddr) { + DBG("Cannot add IPv6 address %s\n", + net_sprint_ipv6_addr(&my_addr3)); + zassert_not_null(ifaddr, "addr1"); + } + + ifaddr->is_temporary = true; + + net_if_up(eth_iface); + + check_ipv6_address_preferences(NULL, IPV6_PREFER_SRC_PUBLIC, + &my_addr1, &dest); + check_ipv6_address_preferences(NULL, IPV6_PREFER_SRC_TMP, + &my_addr3, &dest); +} + static void after(void *arg) { ARG_UNUSED(arg); From b5cc685d3a8888b082ac9aaf69e51e19966b8469 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0214/1389] samples: net: echo-client: Prefer temporary IPv6 addresses As a client it makes sense to prefer temporary IPv6 addresses so mark the socket so. Signed-off-by: Jukka Rissanen --- samples/net/sockets/echo_client/src/tcp.c | 9 +++++++++ samples/net/sockets/echo_client/src/udp.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/samples/net/sockets/echo_client/src/tcp.c b/samples/net/sockets/echo_client/src/tcp.c index 5833d399088a9f..1c52a761323edc 100644 --- a/samples/net/sockets/echo_client/src/tcp.c +++ b/samples/net/sockets/echo_client/src/tcp.c @@ -88,6 +88,7 @@ static int compare_tcp_data(struct data *data, const char *buf, uint32_t receive static int start_tcp_proto(struct data *data, struct sockaddr *addr, socklen_t addrlen) { + int optval; int ret; #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) @@ -159,6 +160,14 @@ static int start_tcp_proto(struct data *data, struct sockaddr *addr, } #endif + /* Prefer IPv6 temporary addresses */ + if (addr->sa_family == AF_INET6) { + optval = IPV6_PREFER_SRC_TMP; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, + IPV6_ADDR_PREFERENCES, + &optval, sizeof(optval)); + } + ret = connect(data->tcp.sock, addr, addrlen); if (ret < 0) { LOG_ERR("Cannot connect to TCP remote (%s): %d", data->proto, diff --git a/samples/net/sockets/echo_client/src/udp.c b/samples/net/sockets/echo_client/src/udp.c index e5b7ea1dae067a..61052337bdb749 100644 --- a/samples/net/sockets/echo_client/src/udp.c +++ b/samples/net/sockets/echo_client/src/udp.c @@ -191,6 +191,7 @@ static void wait_transmit(struct k_timer *timer) static int start_udp_proto(struct data *data, struct sockaddr *addr, socklen_t addrlen) { + int optval; int ret; #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) @@ -229,6 +230,14 @@ static int start_udp_proto(struct data *data, struct sockaddr *addr, } #endif + /* Prefer IPv6 temporary addresses */ + if (addr->sa_family == AF_INET6) { + optval = IPV6_PREFER_SRC_TMP; + (void)setsockopt(data->udp.sock, IPPROTO_IPV6, + IPV6_ADDR_PREFERENCES, + &optval, sizeof(optval)); + } + /* Call connect so we can use send and recv. */ ret = connect(data->udp.sock, addr, addrlen); if (ret < 0) { From 5d5a67f120082259feee65097da131c06f445f34 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0215/1389] samples: net: echo-client: Check IPv6 address deprecation If the IPv6 address that our socket is bound to deprecates, then re-create the socket so that we avoid using deprecated IPv6 address. Signed-off-by: Jukka Rissanen --- .../net/sockets/echo_client/src/echo-client.c | 172 ++++++++++++++++-- samples/net/sockets/echo_client/src/tcp.c | 3 +- samples/net/sockets/echo_client/src/udp.c | 3 +- 3 files changed, 164 insertions(+), 14 deletions(-) diff --git a/samples/net/sockets/echo_client/src/echo-client.c b/samples/net/sockets/echo_client/src/echo-client.c index 3e4aff0f2d0bdd..9343b3b408e13c 100644 --- a/samples/net/sockets/echo_client/src/echo-client.c +++ b/samples/net/sockets/echo_client/src/echo-client.c @@ -24,6 +24,8 @@ LOG_MODULE_REGISTER(net_echo_client_sample, LOG_LEVEL_DBG); #include #include +#include + #include #include @@ -46,6 +48,8 @@ struct k_mem_domain app_domain; #define EVENT_MASK (NET_EVENT_L4_CONNECTED | \ NET_EVENT_L4_DISCONNECTED) +#define IPV6_EVENT_MASK (NET_EVENT_IPV6_ADDR_ADD | \ + NET_EVENT_IPV6_ADDR_DEPRECATED) /* Generated by http://www.lipsum.com/ * 2 paragraphs, 179 words, 1160 bytes of Lorem Ipsum @@ -87,16 +91,26 @@ APP_DMEM struct configs conf = { }, }; -static APP_BMEM struct pollfd fds[4]; +static APP_BMEM struct pollfd fds[1 + 4]; static APP_BMEM int nfds; static APP_BMEM bool connected; +static APP_BMEM bool need_restart; + K_SEM_DEFINE(run_app, 0, 1); static struct net_mgmt_event_callback mgmt_cb; +static struct net_mgmt_event_callback ipv6_mgmt_cb; static void prepare_fds(void) { + nfds = 0; + + /* eventfd is used to trigger restart */ + fds[nfds].fd = eventfd(0, 0); + fds[nfds].events = POLLIN; + nfds++; + if (conf.ipv4.udp.sock >= 0) { fds[nfds].fd = conf.ipv4.udp.sock; fds[nfds].events = POLLIN; @@ -124,11 +138,29 @@ static void prepare_fds(void) static void wait(void) { + int ret; + /* Wait for event on any socket used. Once event occurs, * we'll check them all. */ - if (poll(fds, nfds, -1) < 0) { - LOG_ERR("Error in poll:%d", errno); + ret = poll(fds, nfds, -1); + if (ret < 0) { + static bool once; + + if (!once) { + once = true; + LOG_ERR("Error in poll:%d", errno); + } + + return; + } + + if (ret > 0 && fds[0].revents) { + eventfd_t value; + + eventfd_read(fds[0].fd, &value); + LOG_DBG("Received restart event."); + return; } } @@ -193,6 +225,99 @@ static void stop_udp_and_tcp(void) } } +static int check_our_ipv6_sockets(int sock, + struct in6_addr *deprecated_addr) +{ + struct sockaddr_in6 addr = { 0 }; + socklen_t addrlen = sizeof(addr); + int ret; + + if (sock < 0) { + return -EINVAL; + } + + ret = getsockname(sock, (struct sockaddr *)&addr, &addrlen); + if (ret != 0) { + return -errno; + } + + if (!net_ipv6_addr_cmp(deprecated_addr, &addr.sin6_addr)) { + return -ENOENT; + } + + need_restart = true; + + return 0; +} + +static void ipv6_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + static char addr_str[INET6_ADDRSTRLEN]; + + if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) { + return; + } + + if ((mgmt_event & IPV6_EVENT_MASK) != mgmt_event) { + return; + } + + if (cb->info == NULL || + cb->info_length != sizeof(struct in6_addr)) { + return; + } + + if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) { + struct net_if_addr *ifaddr; + struct in6_addr added_addr; + + memcpy(&added_addr, cb->info, sizeof(struct in6_addr)); + + ifaddr = net_if_ipv6_addr_lookup(&added_addr, &iface); + if (ifaddr == NULL) { + return; + } + + /* Wait until we get a temporary address before continuing after + * boot. + */ + if (ifaddr->is_temporary) { + static bool once; + + LOG_INF("Temporary IPv6 address %s added", + inet_ntop(AF_INET6, &added_addr, addr_str, + sizeof(addr_str) - 1)); + + if (!once) { + k_sem_give(&run_app); + once = true; + } + } + } + + if (mgmt_event == NET_EVENT_IPV6_ADDR_DEPRECATED) { + struct in6_addr deprecated_addr; + + memcpy(&deprecated_addr, cb->info, sizeof(struct in6_addr)); + + LOG_INF("IPv6 address %s deprecated", + inet_ntop(AF_INET6, &deprecated_addr, addr_str, + sizeof(addr_str) - 1)); + + (void)check_our_ipv6_sockets(conf.ipv6.tcp.sock, + &deprecated_addr); + (void)check_our_ipv6_sockets(conf.ipv6.udp.sock, + &deprecated_addr); + + if (need_restart) { + eventfd_write(fds[0].fd, 1); + } + + return; + } +} + static void event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) { @@ -206,7 +331,10 @@ static void event_handler(struct net_mgmt_event_callback *cb, connected = true; conf.ipv4.udp.mtu = net_if_get_mtu(iface); conf.ipv6.udp.mtu = conf.ipv4.udp.mtu; - k_sem_give(&run_app); + + if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) { + k_sem_give(&run_app); + } return; } @@ -275,6 +403,10 @@ static void init_app(void) conn_mgr_mon_resend_status(); } + net_mgmt_init_event_callback(&ipv6_mgmt_cb, + ipv6_event_handler, IPV6_EVENT_MASK); + net_mgmt_add_event_callback(&ipv6_mgmt_cb); + init_vlan(); init_udp(); } @@ -293,19 +425,35 @@ static void start_client(void *p1, void *p2, void *p3) /* Wait for the connection. */ k_sem_take(&run_app, K_FOREVER); - ret = start_udp_and_tcp(); + if (IS_ENABLED(CONFIG_NET_IPV6_PE)) { + /* Make sure that we have a temporary address */ + k_sleep(K_SECONDS(1)); + } + + do { + if (need_restart) { + /* Close all sockets and get a fresh restart */ + stop_udp_and_tcp(); + need_restart = false; + } - while (connected && (ret == 0)) { - ret = run_udp_and_tcp(); + ret = start_udp_and_tcp(); - if (iterations > 0) { - i++; - if (i >= iterations) { - break; + while (connected && (ret == 0)) { + ret = run_udp_and_tcp(); + if (iterations > 0) { + i++; + if (i >= iterations) { + break; + } + } + + if (need_restart) { + break; } } - } + } while (need_restart); stop_udp_and_tcp(); } diff --git a/samples/net/sockets/echo_client/src/tcp.c b/samples/net/sockets/echo_client/src/tcp.c index 1c52a761323edc..92cfbbae290630 100644 --- a/samples/net/sockets/echo_client/src/tcp.c +++ b/samples/net/sockets/echo_client/src/tcp.c @@ -239,7 +239,8 @@ int start_tcp(void) inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR, &addr6.sin6_addr); - ret = start_tcp_proto(&conf.ipv6, (struct sockaddr *)&addr6, + ret = start_tcp_proto(&conf.ipv6, + (struct sockaddr *)&addr6, sizeof(addr6)); if (ret < 0) { return ret; diff --git a/samples/net/sockets/echo_client/src/udp.c b/samples/net/sockets/echo_client/src/udp.c index 61052337bdb749..34757fa79c586b 100644 --- a/samples/net/sockets/echo_client/src/udp.c +++ b/samples/net/sockets/echo_client/src/udp.c @@ -308,7 +308,8 @@ int start_udp(void) inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR, &addr6.sin6_addr); - ret = start_udp_proto(&conf.ipv6, (struct sockaddr *)&addr6, + ret = start_udp_proto(&conf.ipv6, + (struct sockaddr *)&addr6, sizeof(addr6)); if (ret < 0) { return ret; From 0281604cf5bab38b19647dbd053ae910d6465288 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0216/1389] samples: net: echo-client: Avoid flooding output Do not print progress report so that makes debugging things a lot harder. It is still possible to enable printouts if needed by setting PRINT_PROGRESS symbol. Signed-off-by: Jukka Rissanen --- samples/net/sockets/echo_client/src/common.h | 5 +++++ samples/net/sockets/echo_client/src/tcp.c | 15 +++++++++------ samples/net/sockets/echo_client/src/udp.c | 12 ++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/samples/net/sockets/echo_client/src/common.h b/samples/net/sockets/echo_client/src/common.h index e0b06b7ee14136..d7a8b6c69e5d74 100644 --- a/samples/net/sockets/echo_client/src/common.h +++ b/samples/net/sockets/echo_client/src/common.h @@ -12,6 +12,11 @@ #define PEER_PORT 4242 +/* Turn off the progress printing so that shell can be used. + * Set to true if you want to see progress output. + */ +#define PRINT_PROGRESS false + #if defined(CONFIG_USERSPACE) #include extern struct k_mem_partition app_partition; diff --git a/samples/net/sockets/echo_client/src/tcp.c b/samples/net/sockets/echo_client/src/tcp.c index 92cfbbae290630..eee8994425ccf5 100644 --- a/samples/net/sockets/echo_client/src/tcp.c +++ b/samples/net/sockets/echo_client/src/tcp.c @@ -63,8 +63,10 @@ static int send_tcp_data(struct data *data) LOG_ERR("%s TCP: Failed to send data, errno %d", data->proto, errno); } else { - LOG_DBG("%s TCP: Sent %d bytes", data->proto, - data->tcp.expecting); + if (PRINT_PROGRESS) { + LOG_DBG("%s TCP: Sent %d bytes", data->proto, + data->tcp.expecting); + } } return ret; @@ -210,10 +212,11 @@ static int process_tcp_proto(struct data *data) continue; } - /* Response complete */ - LOG_DBG("%s TCP: Received and compared %d bytes, all ok", - data->proto, data->tcp.received); - + if (PRINT_PROGRESS) { + /* Response complete */ + LOG_DBG("%s TCP: Received and compared %d bytes, all ok", + data->proto, data->tcp.received); + } if (++data->tcp.counter % 1000 == 0U) { LOG_INF("%s TCP: Exchanged %u packets", data->proto, diff --git a/samples/net/sockets/echo_client/src/udp.c b/samples/net/sockets/echo_client/src/udp.c index 34757fa79c586b..3055c2d03f266d 100644 --- a/samples/net/sockets/echo_client/src/udp.c +++ b/samples/net/sockets/echo_client/src/udp.c @@ -147,7 +147,9 @@ static int send_udp_data(struct data *data) ret = send(data->udp.sock, lorem_ipsum, data->udp.expecting, 0); - LOG_DBG("%s UDP: Sent %d bytes", data->proto, data->udp.expecting); + if (PRINT_PROGRESS) { + LOG_DBG("%s UDP: Sent %d bytes", data->proto, data->udp.expecting); + } k_timer_start(&data->udp.ctrl->rx_timer, UDP_WAIT, K_NO_WAIT); @@ -275,9 +277,11 @@ static int process_udp_proto(struct data *data) return 0; } - /* Correct response received */ - LOG_DBG("%s UDP: Received and compared %d bytes, all ok", - data->proto, received); + if (PRINT_PROGRESS) { + /* Correct response received */ + LOG_DBG("%s UDP: Received and compared %d bytes, all ok", + data->proto, received); + } if (++data->udp.counter % 1000 == 0U) { LOG_INF("%s UDP: Exchanged %u packets", data->proto, From b4de92f645054a0239d29fd356d178c6d8c3591c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0217/1389] samples: net: echo-server: Prefer public IPv6 addresses As a server it makes sense to prefer public IPv6 addresses so mark the socket so. Signed-off-by: Jukka Rissanen --- samples/net/sockets/echo_server/src/tcp.c | 9 +++++++++ samples/net/sockets/echo_server/src/udp.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/samples/net/sockets/echo_server/src/tcp.c b/samples/net/sockets/echo_server/src/tcp.c index 1a6555d43c30c4..3df5ceaec9a76e 100644 --- a/samples/net/sockets/echo_server/src/tcp.c +++ b/samples/net/sockets/echo_server/src/tcp.c @@ -68,6 +68,7 @@ static int start_tcp_proto(struct data *data, struct sockaddr *bind_addr, socklen_t bind_addrlen) { + int optval; int ret; #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) @@ -100,6 +101,14 @@ static int start_tcp_proto(struct data *data, } #endif + /* Prefer IPv6 temporary addresses */ + if (bind_addr->sa_family == AF_INET6) { + optval = IPV6_PREFER_SRC_PUBLIC; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, + IPV6_ADDR_PREFERENCES, + &optval, sizeof(optval)); + } + ret = bind(data->tcp.sock, bind_addr, bind_addrlen); if (ret < 0) { LOG_ERR("Failed to bind TCP socket (%s): %d", data->proto, diff --git a/samples/net/sockets/echo_server/src/udp.c b/samples/net/sockets/echo_server/src/udp.c index 69affd53b691df..6707410381fa5d 100644 --- a/samples/net/sockets/echo_server/src/udp.c +++ b/samples/net/sockets/echo_server/src/udp.c @@ -36,6 +36,7 @@ K_THREAD_DEFINE(udp6_thread_id, STACK_SIZE, static int start_udp_proto(struct data *data, struct sockaddr *bind_addr, socklen_t bind_addrlen) { + int optval; int ret; #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) @@ -77,6 +78,14 @@ static int start_udp_proto(struct data *data, struct sockaddr *bind_addr, } #endif + /* Prefer IPv6 temporary addresses */ + if (bind_addr->sa_family == AF_INET6) { + optval = IPV6_PREFER_SRC_PUBLIC; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, + IPV6_ADDR_PREFERENCES, + &optval, sizeof(optval)); + } + ret = bind(data->udp.sock, bind_addr, bind_addrlen); if (ret < 0) { NET_ERR("Failed to bind UDP socket (%s): %d", data->proto, From cf8ee13380f360bca65a7f5a0e0c0e42d8d1b4e4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:35 +0200 Subject: [PATCH 0218/1389] net: context: Add helpers for figuring out local endpoint address We usually cannot use context->local for established TCP connections because the local address is not updated for TCP if we are bound to any address. So create helper that try to figure out the end point addresses. Signed-off-by: Jukka Rissanen --- subsys/net/ip/net_context.c | 45 ++++++++++++++++++++++++++++++++++++ subsys/net/ip/net_private.h | 14 +++++++++++ subsys/net/ip/tcp.c | 45 ++++++++++++++++++++++++++++++++++++ subsys/net/ip/tcp_internal.h | 15 ++++++++++++ 4 files changed, 119 insertions(+) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 84edc97edf3983..77d829a570fd6f 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -3181,6 +3181,51 @@ int net_context_get_option(struct net_context *context, return ret; } +int net_context_get_local_addr(struct net_context *ctx, + struct sockaddr *addr, + socklen_t *addrlen) +{ + if (ctx == NULL || addr == NULL || addrlen == NULL) { + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_NET_TCP) && + net_context_get_type(ctx) == SOCK_STREAM) { + return net_tcp_endpoint_copy(ctx, addr, NULL, addrlen); + } + + if (IS_ENABLED(CONFIG_NET_UDP) && net_context_get_type(ctx) == SOCK_DGRAM) { + socklen_t newlen; + + if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET) { + newlen = MIN(*addrlen, sizeof(struct sockaddr_in)); + + net_sin(addr)->sin_family = AF_INET; + net_sin(addr)->sin_port = net_sin_ptr(&ctx->local)->sin_port; + memcpy(&net_sin(addr)->sin_addr, + net_sin_ptr(&ctx->local)->sin_addr, + sizeof(struct in_addr)); + + } else if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->local.family == AF_INET6) { + newlen = MIN(*addrlen, sizeof(struct sockaddr_in6)); + + net_sin6(addr)->sin6_family = AF_INET6; + net_sin6(addr)->sin6_port = net_sin6_ptr(&ctx->local)->sin6_port; + memcpy(&net_sin6(addr)->sin6_addr, + net_sin6_ptr(&ctx->local)->sin6_addr, + sizeof(struct in6_addr)); + } else { + return -EAFNOSUPPORT; + } + + *addrlen = newlen; + + return 0; + } + + return -ENOPROTOOPT; +} + void net_context_foreach(net_context_cb_t cb, void *user_data) { int i; diff --git a/subsys/net/ip/net_private.h b/subsys/net/ip/net_private.h index 6d425c0518893d..cb9d8dc396f95b 100644 --- a/subsys/net/ip/net_private.h +++ b/subsys/net/ip/net_private.h @@ -81,6 +81,9 @@ extern bool net_context_is_recv_pktinfo_set(struct net_context *context); extern void net_pkt_init(void); extern void net_tc_tx_init(void); extern void net_tc_rx_init(void); +int net_context_get_local_addr(struct net_context *context, + struct sockaddr *addr, + socklen_t *addrlen); #else static inline void net_context_init(void) { } static inline void net_pkt_init(void) { } @@ -106,6 +109,17 @@ static inline bool net_context_is_recv_pktinfo_set(struct net_context *context) ARG_UNUSED(context); return false; } + +static inline int net_context_get_local_addr(struct net_context *context, + struct sockaddr *addr, + socklen_t *addrlen) +{ + ARG_UNUSED(context); + ARG_UNUSED(addr); + ARG_UNUSED(addrlen); + + return -ENOTSUP; +} #endif #if defined(CONFIG_NET_NATIVE) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 2002b7d32c008f..8e5f7abf652223 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -239,6 +239,51 @@ static int tcp_endpoint_set(union tcp_endpoint *ep, struct net_pkt *pkt, return ret; } +int net_tcp_endpoint_copy(struct net_context *ctx, + struct sockaddr *local, + struct sockaddr *peer, + socklen_t *addrlen) +{ + const struct tcp *conn = ctx->tcp; + socklen_t newlen = ctx->local.family == AF_INET ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6); + + if (local != NULL) { + /* If we are connected, then get the address we are actually + * using, otherwise get the address we are bound as these might + * be different if we are bound to any address. + */ + if (conn->state < TCP_ESTABLISHED) { + if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET) { + memcpy(&net_sin(local)->sin_addr, + net_sin_ptr(&ctx->local)->sin_addr, + sizeof(struct in_addr)); + net_sin(local)->sin_port = net_sin_ptr(&ctx->local)->sin_port; + net_sin(local)->sin_family = AF_INET; + } else if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET6) { + memcpy(&net_sin6(local)->sin6_addr, + net_sin6_ptr(&ctx->local)->sin6_addr, + sizeof(struct in6_addr)); + net_sin6(local)->sin6_port = net_sin6_ptr(&ctx->local)->sin6_port; + net_sin6(local)->sin6_family = AF_INET6; + net_sin6(local)->sin6_scope_id = + net_sin6_ptr(&ctx->local)->sin6_scope_id; + } else { + return -EINVAL; + } + } else { + memcpy(local, &conn->src.sa, newlen); + } + } + + if (peer != NULL) { + memcpy(local, &conn->dst.sa, newlen); + } + + return 0; +} + static const char *tcp_flags(uint8_t flags) { #define BUF_SIZE 25 /* 6 * 4 + 1 */ diff --git a/subsys/net/ip/tcp_internal.h b/subsys/net/ip/tcp_internal.h index a9921bbe91fde9..309ed8cdb0d08e 100644 --- a/subsys/net/ip/tcp_internal.h +++ b/subsys/net/ip/tcp_internal.h @@ -448,6 +448,21 @@ static inline void net_tcp_reply_rst(struct net_pkt *pkt) } #endif +/** + * @brief Get the TCP connection endpoint information. + * + * @param context Network context + * @param local TCP connection local socket information is copied here + * @param peer TCP connection peer socket information is copied here + * @param addrlen Size of the sockaddr struct. Copied size is returned. + * + * @return <0 if there was an error, 0 if ok + */ +int net_tcp_endpoint_copy(struct net_context *ctx, + struct sockaddr *local, + struct sockaddr *peer, + socklen_t *addrlen); + #ifdef __cplusplus } #endif From b7c8be12f48c16a1d9f9a8654dc69ef93fe85e37 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0219/1389] net: sockets: Fix getsockname() for TCP The local address used for established TCP socket needs to be dig out from TCP internals and not from context->local. Signed-off-by: Jukka Rissanen --- subsys/net/lib/sockets/sockets.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index aa435a0ed049f0..1a027e2c83dafa 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -3484,6 +3484,7 @@ int zsock_getsockname_ctx(struct net_context *ctx, struct sockaddr *addr, socklen_t *addrlen) { socklen_t newlen = 0; + int ret; if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET) { struct sockaddr_in addr4 = { 0 }; @@ -3492,27 +3493,33 @@ int zsock_getsockname_ctx(struct net_context *ctx, struct sockaddr *addr, SET_ERRNO(-EINVAL); } - addr4.sin_family = AF_INET; - addr4.sin_port = net_sin_ptr(&ctx->local)->sin_port; - memcpy(&addr4.sin_addr, net_sin_ptr(&ctx->local)->sin_addr, - sizeof(struct in_addr)); newlen = sizeof(struct sockaddr_in); + ret = net_context_get_local_addr(ctx, + (struct sockaddr *)&addr4, + &newlen); + if (ret < 0) { + SET_ERRNO(-ret); + } + memcpy(addr, &addr4, MIN(*addrlen, newlen)); - } else if (IS_ENABLED(CONFIG_NET_IPV6) && - ctx->local.family == AF_INET6) { + + } else if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->local.family == AF_INET6) { struct sockaddr_in6 addr6 = { 0 }; if (net_sin6_ptr(&ctx->local)->sin6_addr == NULL) { SET_ERRNO(-EINVAL); } - addr6.sin6_family = AF_INET6; - addr6.sin6_port = net_sin6_ptr(&ctx->local)->sin6_port; - memcpy(&addr6.sin6_addr, net_sin6_ptr(&ctx->local)->sin6_addr, - sizeof(struct in6_addr)); newlen = sizeof(struct sockaddr_in6); + ret = net_context_get_local_addr(ctx, + (struct sockaddr *)&addr6, + &newlen); + if (ret < 0) { + SET_ERRNO(-ret); + } + memcpy(addr, &addr6, MIN(*addrlen, newlen)); } else { SET_ERRNO(-EINVAL); From a6be075613cbb78814ff5c60b2b18e0cc21e0624 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0220/1389] net: ipv6: Tailor PE values for Zephyr Making default preferred time much closer to default valid time so that the served addresses are much shorter time in deprecated state where they cannot be utilized. This is important in Zephyr as there are limited number of IPv6 addresses that can be allocated to the network interface. Signed-off-by: Jukka Rissanen --- subsys/net/ip/Kconfig.ipv6 | 8 ++++---- subsys/net/ip/ipv6_pe.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/subsys/net/ip/Kconfig.ipv6 b/subsys/net/ip/Kconfig.ipv6 index 9d6079a2803376..21b7aad397b8dc 100644 --- a/subsys/net/ip/Kconfig.ipv6 +++ b/subsys/net/ip/Kconfig.ipv6 @@ -200,17 +200,17 @@ config NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES config NET_IPV6_PE_TEMP_VALID_LIFETIME int "Max lifetime for temporary address (in minutes)" - default 1800 + default 1440 help No temporary address should ever remain valid for longer than this - value. The value is in minutes. Default value is 2 days (2*24*60). + value. The value is in minutes. Default value is 1 day (24*60). config NET_IPV6_PE_TEMP_PREFERRED_LIFETIME int "Max preferred lifetime for temporary address (in minutes)" - default 1440 + default 1380 help No temporary address should ever remain preferred for longer than this - value. The value is in minutes. Default value is 1 day (24*60). + value. The value is in minutes. Default value is 23 hours (23*60). config NET_IPV6_PE_TEMP_IDGEN_RETRIES int "Max amount of failed DAD attempts" diff --git a/subsys/net/ip/ipv6_pe.c b/subsys/net/ip/ipv6_pe.c index b44283ecc0d837..9aef57181678ce 100644 --- a/subsys/net/ip/ipv6_pe.c +++ b/subsys/net/ip/ipv6_pe.c @@ -52,9 +52,15 @@ static uint32_t temp_preferred_lifetime = /* This is the upper bound on DESYNC_FACTOR. The value is in seconds. * See RFC 8981 ch 3.8 for details. + * + * RFC says the DESYNC_FACTOR should be 0.4 times the preferred lifetime. + * This is too short for Zephyr as it means that the address is very long + * time in deprecated state and not being used. Make this 7% of the preferred + * time to deprecate the addresses later. */ -#define MAX_DESYNC_FACTOR ((TEMP_PREFERRED_LIFETIME * 2U) / 5U) -#define DESYNC_FACTOR(ipv6) ((ipv6)->desync_factor) +#define MAX_DESYNC_FACTOR ((uint32_t)((uint64_t)TEMP_PREFERRED_LIFETIME * \ + (uint64_t)7U) / (uint64_t)100U) +#define DESYNC_FACTOR(ipv6) ((ipv6)->desync_factor) #define TEMP_IDGEN_RETRIES CONFIG_NET_IPV6_PE_TEMP_IDGEN_RETRIES From fd49d58785302687cee1ef7e4f848c993a96cf97 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0221/1389] tests: net: coap: Enable loopback interface There needs to be at least one network interface in order to avoid this error. E: There is no network interface to work with! So enable loopback support which creates a loopback interface. Signed-off-by: Jukka Rissanen --- tests/net/lib/coap_server/common/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/net/lib/coap_server/common/prj.conf b/tests/net/lib/coap_server/common/prj.conf index 07cf69355fc080..8daa9205bf4056 100644 --- a/tests/net/lib/coap_server/common/prj.conf +++ b/tests/net/lib/coap_server/common/prj.conf @@ -4,6 +4,7 @@ CONFIG_NETWORKING=y CONFIG_NET_TEST=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_LOOPBACK=y CONFIG_COAP=y CONFIG_COAP_SERVER=y From f7ef19174f573af8d7a81fd079bff39e822c5018 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0222/1389] net: if: ipv6: Do not crash if there are no network interfaces When trying to get IPv6 prefix, if there are no network interfaces then the net_if_get_default() will return NULL but we should not crash at that point but return gracefully. Signed-off-by: Jukka Rissanen --- subsys/net/ip/net_if.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 0316faa498535a..53d2ebb6887cd7 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -2536,6 +2536,10 @@ struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface, iface = net_if_get_default(); } + if (!iface) { + return NULL; + } + net_if_lock(iface); ipv6 = iface->config.ip.ipv6; From bf245ae2caa4202dfb24fd65d76f1d9ce23df37a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0223/1389] net: if: Print warning if there are no network interfaces When calling net_if_get_default(), print a warning if no network interfaces are found. This helps debugging mysterious crashes. Signed-off-by: Jukka Rissanen --- subsys/net/ip/net_if.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 53d2ebb6887cd7..45db9a00f47e5d 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -579,6 +579,7 @@ struct net_if *net_if_get_default(void) struct net_if *iface = NULL; if (&_net_if_list_start[0] == &_net_if_list_end[0]) { + NET_WARN("No default interface found!"); return NULL; } From f7d33f89afb143584d77747327f6549578e7a418 Mon Sep 17 00:00:00 2001 From: Jeronimo Agullo Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0224/1389] drivers: gnss: Air530z: Add new driver Intial driver adding intial script to receive only GGA, RMC and GSV NMEA messages, configuring fix rate, setting enabled system and adding power management with the module on-off pin. Signed-off-by: Jeronimo Agullo --- drivers/gnss/CMakeLists.txt | 1 + drivers/gnss/Kconfig | 1 + drivers/gnss/Kconfig.luatos_air530z | 26 ++ drivers/gnss/gnss_luatos_air530z.c | 364 ++++++++++++++++++++++++++ dts/bindings/gnss/luatos,air530z.yaml | 15 ++ 5 files changed, 407 insertions(+) create mode 100644 drivers/gnss/Kconfig.luatos_air530z create mode 100644 drivers/gnss/gnss_luatos_air530z.c create mode 100644 dts/bindings/gnss/luatos,air530z.yaml diff --git a/drivers/gnss/CMakeLists.txt b/drivers/gnss/CMakeLists.txt index 32346282c04660..77631bcb9710ad 100644 --- a/drivers/gnss/CMakeLists.txt +++ b/drivers/gnss/CMakeLists.txt @@ -11,3 +11,4 @@ zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA_GENERIC gnss_nmea_generic.c) zephyr_library_sources_ifdef(CONFIG_GNSS_QUECTEL_LCX6G gnss_quectel_lcx6g.c) zephyr_library_sources_ifdef(CONFIG_GNSS_U_BLOX_M10 gnss_u_blox_m10.c) zephyr_library_sources_ifdef(CONFIG_GNSS_U_BLOX_PROTOCOL gnss_u_blox_protocol/gnss_u_blox_protocol.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_LUATOS_AIR530Z gnss_luatos_air530z.c) diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig index db9762bd87b2ce..98602d4194997f 100644 --- a/drivers/gnss/Kconfig +++ b/drivers/gnss/Kconfig @@ -73,5 +73,6 @@ source "subsys/logging/Kconfig.template.log_config" rsource "Kconfig.generic" rsource "Kconfig.quectel_lcx6g" rsource "Kconfig.u_blox_m10" +rsource "Kconfig.luatos_air530z" endif diff --git a/drivers/gnss/Kconfig.luatos_air530z b/drivers/gnss/Kconfig.luatos_air530z new file mode 100644 index 00000000000000..958521af1fd087 --- /dev/null +++ b/drivers/gnss/Kconfig.luatos_air530z @@ -0,0 +1,26 @@ +# Copyright 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +config GNSS_LUATOS_AIR530Z + bool "Luatos Air530z GNSS device" + default y + depends on GNSS + depends on DT_HAS_LUATOS_AIR530Z_ENABLED + select MODEM_MODULES + select MODEM_BACKEND_UART + select MODEM_CHAT + select GNSS_PARSE + select GNSS_NMEA0183 + select GNSS_NMEA0183_MATCH + help + Enable Luatos Air530z GNSS driver. + +config GNSS_LUATOS_AIR530Z_SATELLITES_COUNT + int "Maximum satellite count" + depends on GNSS_SATELLITES + default 24 + help + Maximum number of satellites that can be decoded from the + GNSS device. This does not affect the number of devices that + the device is actually tracking, just how many of those can + be reported in the satellites callback. diff --git a/drivers/gnss/gnss_luatos_air530z.c b/drivers/gnss/gnss_luatos_air530z.c new file mode 100644 index 00000000000000..a24c8245ac329f --- /dev/null +++ b/drivers/gnss/gnss_luatos_air530z.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2024 Jerónimo Agulló + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gnss_nmea0183.h" +#include "gnss_nmea0183_match.h" +#include "gnss_parse.h" + +#include +LOG_MODULE_REGISTER(luatos_air530z, CONFIG_GNSS_LOG_LEVEL); + +#define DT_DRV_COMPAT luatos_air530z + +#define UART_RECV_BUF_SZ 128 +#define UART_TRANS_BUF_SZ 64 + +#define CHAT_RECV_BUF_SZ 256 +#define CHAT_ARGV_SZ 32 + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(init_script_cmds, +#if CONFIG_GNSS_SATELLITES + /* receive only GGA, RMC and GSV NMEA messages */ + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("$PCAS03,1,0,0,1,1,0,0,0,0,0,0,0,0*1F", 10), +#else + /* receive only GGA and RMC NMEA messages */ + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("$PCAS03,1,0,0,0,1,0,0,0,0,0,0,0,0*1E", 10), +#endif +); + +MODEM_CHAT_SCRIPT_NO_ABORT_DEFINE(init_script, init_script_cmds, NULL, 5); + +struct gnss_luatos_air530z_config { + const struct device *uart; + const struct gpio_dt_spec on_off_gpio; + const int uart_baudrate; +}; + +struct gnss_luatos_air530z_data { + struct gnss_nmea0183_match_data match_data; +#if CONFIG_GNSS_SATELLITES + struct gnss_satellite satellites[CONFIG_GNSS_LUATOS_AIR530Z_SATELLITES_COUNT]; +#endif + + /* UART backend */ + struct modem_pipe *uart_pipe; + struct modem_backend_uart uart_backend; + uint8_t uart_backend_receive_buf[UART_RECV_BUF_SZ]; + uint8_t uart_backend_transmit_buf[UART_TRANS_BUF_SZ]; + + /* Modem chat */ + struct modem_chat chat; + uint8_t chat_receive_buf[CHAT_RECV_BUF_SZ]; + uint8_t chat_delimiter[2]; + uint8_t *chat_argv[CHAT_ARGV_SZ]; + + /* Dynamic chat script */ + uint8_t dynamic_separators_buf[2]; + uint8_t dynamic_request_buf[32]; + struct modem_chat_script_chat dynamic_script_chat; + struct modem_chat_script dynamic_script; + + struct k_sem lock; +}; + +MODEM_CHAT_MATCHES_DEFINE(unsol_matches, + MODEM_CHAT_MATCH_WILDCARD("$??GGA,", ",*", gnss_nmea0183_match_gga_callback), + MODEM_CHAT_MATCH_WILDCARD("$??RMC,", ",*", gnss_nmea0183_match_rmc_callback), +#if CONFIG_GNSS_SATELLITES + MODEM_CHAT_MATCH_WILDCARD("$??GSV,", ",*", gnss_nmea0183_match_gsv_callback), +#endif +); + +static void luatos_air530z_lock(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + + (void)k_sem_take(&data->lock, K_FOREVER); +} + +static void luatos_air530z_unlock(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + + k_sem_give(&data->lock); +} + +static int gnss_luatos_air530z_init_nmea0183_match(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + + const struct gnss_nmea0183_match_config match_config = { + .gnss = dev, +#if CONFIG_GNSS_SATELLITES + .satellites = data->satellites, + .satellites_size = ARRAY_SIZE(data->satellites), +#endif + }; + + return gnss_nmea0183_match_init(&data->match_data, &match_config); +} + +static void gnss_luatos_air530z_init_pipe(const struct device *dev) +{ + const struct gnss_luatos_air530z_config *config = dev->config; + struct gnss_luatos_air530z_data *data = dev->data; + + const struct modem_backend_uart_config uart_backend_config = { + .uart = config->uart, + .receive_buf = data->uart_backend_receive_buf, + .receive_buf_size = sizeof(data->uart_backend_receive_buf), + .transmit_buf = data->uart_backend_transmit_buf, + .transmit_buf_size = ARRAY_SIZE(data->uart_backend_transmit_buf), + }; + + data->uart_pipe = modem_backend_uart_init(&data->uart_backend, &uart_backend_config); +} + +static int gnss_luatos_air530z_init_chat(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + + const struct modem_chat_config chat_config = { + .user_data = data, + .receive_buf = data->chat_receive_buf, + .receive_buf_size = sizeof(data->chat_receive_buf), + .delimiter = data->chat_delimiter, + .delimiter_size = ARRAY_SIZE(data->chat_delimiter), + .filter = NULL, + .filter_size = 0, + .argv = data->chat_argv, + .argv_size = ARRAY_SIZE(data->chat_argv), + .unsol_matches = unsol_matches, + .unsol_matches_size = ARRAY_SIZE(unsol_matches), + }; + + return modem_chat_init(&data->chat, &chat_config); +} + +static void luatos_air530z_init_dynamic_script(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + + /* Air530z doesn't respond to commands. Thus, response_matches_size = 0; */ + data->dynamic_script_chat.request = data->dynamic_request_buf; + data->dynamic_script_chat.response_matches = NULL; + data->dynamic_script_chat.response_matches_size = 0; + data->dynamic_script_chat.timeout = 0; + + data->dynamic_script.name = "PCAS"; + data->dynamic_script.script_chats = &data->dynamic_script_chat; + data->dynamic_script.script_chats_size = 1; + data->dynamic_script.abort_matches = NULL; + data->dynamic_script.abort_matches_size = 0; + data->dynamic_script.callback = NULL; + data->dynamic_script.timeout = 5; +} + +static int gnss_luatos_air530z_init(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + const struct gnss_luatos_air530z_config *config = dev->config; + int ret; + + k_sem_init(&data->lock, 1, 1); + + ret = gnss_luatos_air530z_init_nmea0183_match(dev); + if (ret < 0) { + return ret; + } + + gnss_luatos_air530z_init_pipe(dev); + + ret = gnss_luatos_air530z_init_chat(dev); + if (ret < 0) { + return ret; + } + + luatos_air530z_init_dynamic_script(dev); + + ret = modem_pipe_open(data->uart_pipe); + if (ret < 0) { + return ret; + } + + ret = modem_chat_attach(&data->chat, data->uart_pipe); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + return ret; + } + + ret = modem_chat_run_script(&data->chat, &init_script); + if (ret < 0) { + LOG_ERR("Failed to run init_script"); + modem_pipe_close(data->uart_pipe); + return ret; + } + + /* setup on-off gpio for power management */ + if (!gpio_is_ready_dt(&config->on_off_gpio)) { + LOG_ERR("on-off GPIO device not ready"); + return -ENODEV; + } + + gpio_pin_configure_dt(&config->on_off_gpio, GPIO_OUTPUT_HIGH); + + return 0; +} + +static int luatos_air530z_pm_resume(const struct device *dev) +{ + struct gnss_luatos_air530z_data *data = dev->data; + int ret; + + ret = modem_pipe_open(data->uart_pipe); + if (ret < 0) { + return ret; + } + + ret = modem_chat_attach(&data->chat, data->uart_pipe); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + return ret; + } + + ret = modem_chat_run_script(&data->chat, &init_script); + if (ret < 0) { + modem_pipe_close(data->uart_pipe); + return ret; + } + + return 0; +} + +static int luatos_air530z_pm_action(const struct device *dev, enum pm_device_action action) +{ + struct gnss_luatos_air530z_data *data = dev->data; + const struct gnss_luatos_air530z_config *config = dev->config; + int ret = -ENOTSUP; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + gpio_pin_set_dt(&config->on_off_gpio, 0); + ret = modem_pipe_close(data->uart_pipe); + break; + + case PM_DEVICE_ACTION_RESUME: + gpio_pin_set_dt(&config->on_off_gpio, 1); + ret = luatos_air530z_pm_resume(dev); + break; + + default: + break; + } + + return ret; +} + +static int luatos_air530z_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + struct gnss_luatos_air530z_data *data = dev->data; + int ret; + + if (fix_interval_ms < 100 || fix_interval_ms > 1000) { + return -EINVAL; + } + + luatos_air530z_lock(dev); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PCAS02,%u", fix_interval_ms); + + data->dynamic_script_chat.request_size = ret; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (ret < 0) { + goto unlock_return; + } + +unlock_return: + luatos_air530z_unlock(dev); + return ret; +} + +static int luatos_air530z_set_enabled_systems(const struct device *dev, gnss_systems_t systems) +{ + struct gnss_luatos_air530z_data *data = dev->data; + gnss_systems_t supported_systems; + uint8_t encoded_systems = 0; + int ret; + + supported_systems = (GNSS_SYSTEM_GPS | GNSS_SYSTEM_GLONASS | GNSS_SYSTEM_BEIDOU); + + if ((~supported_systems) & systems) { + return -EINVAL; + } + + luatos_air530z_lock(dev); + + WRITE_BIT(encoded_systems, 0, systems & GNSS_SYSTEM_GPS); + WRITE_BIT(encoded_systems, 1, systems & GNSS_SYSTEM_GLONASS); + WRITE_BIT(encoded_systems, 2, systems & GNSS_SYSTEM_BEIDOU); + + ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + "PCAS04,%u", encoded_systems); + if (ret < 0) { + goto unlock_return; + } + + data->dynamic_script_chat.request_size = ret; + + ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (ret < 0) { + goto unlock_return; + } + +unlock_return: + luatos_air530z_unlock(dev); + return ret; + +} + +static int luatos_air530z_get_supported_systems(const struct device *dev, gnss_systems_t *systems) +{ + *systems = (GNSS_SYSTEM_GPS | GNSS_SYSTEM_GLONASS | GNSS_SYSTEM_BEIDOU); + return 0; +} + +static struct gnss_driver_api gnss_api = { + .set_fix_rate = luatos_air530z_set_fix_rate, + .set_enabled_systems = luatos_air530z_set_enabled_systems, + .get_supported_systems = luatos_air530z_get_supported_systems, +}; + +#define LUATOS_AIR530Z(inst) \ + static struct gnss_luatos_air530z_config gnss_luatos_air530z_cfg_##inst = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .on_off_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, on_off_gpios, { 0 }), \ + }; \ + \ + static struct gnss_luatos_air530z_data gnss_luatos_air530z_data_##inst = { \ + .chat_delimiter = {'\r', '\n'}, \ + .dynamic_separators_buf = {',', '*'}, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, luatos_air530z_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, gnss_luatos_air530z_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &gnss_luatos_air530z_data_##inst, \ + &gnss_luatos_air530z_cfg_##inst, \ + POST_KERNEL, CONFIG_GNSS_INIT_PRIORITY, &gnss_api); + +DT_INST_FOREACH_STATUS_OKAY(LUATOS_AIR530Z) diff --git a/dts/bindings/gnss/luatos,air530z.yaml b/dts/bindings/gnss/luatos,air530z.yaml new file mode 100644 index 00000000000000..c70a96690f5e94 --- /dev/null +++ b/dts/bindings/gnss/luatos,air530z.yaml @@ -0,0 +1,15 @@ +# Copyright 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +description: AIR530Z Luatos GNSS modem + +compatible: "luatos,air530z" + +include: + - uart-device.yaml + +properties: + on-off-gpios: + type: phandle-array + description: | + Identifies the On-Off pin for entering into low-power mode. From 7d50fedea7a91604d5fc261d2c0912a509c68b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0225/1389] mgmt: hawkbit: change the tls certificate tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be able to change the tls certicicate tag. Signed-off-by: Fin Maaß --- include/zephyr/mgmt/hawkbit.h | 34 ++++++++++++++++++-- samples/subsys/mgmt/hawkbit/overlay-tls.conf | 1 + samples/subsys/mgmt/hawkbit/sample.yaml | 1 + subsys/mgmt/hawkbit/Kconfig | 34 ++++++++++++++++++++ subsys/mgmt/hawkbit/hawkbit.c | 31 ++++++++++++------ 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/include/zephyr/mgmt/hawkbit.h b/include/zephyr/mgmt/hawkbit.h index 55bc0e8411c41f..08da3df1b1c595 100644 --- a/include/zephyr/mgmt/hawkbit.h +++ b/include/zephyr/mgmt/hawkbit.h @@ -13,6 +13,8 @@ #ifndef ZEPHYR_INCLUDE_MGMT_HAWKBIT_H_ #define ZEPHYR_INCLUDE_MGMT_HAWKBIT_H_ +#include + #define HAWKBIT_JSON_URL "/default/controller/v1" /** @@ -47,6 +49,7 @@ struct hawkbit_runtime_config { char *server_addr; uint16_t server_port; char *auth_token; + sec_tag_t tls_tag; }; /** @@ -160,7 +163,7 @@ struct hawkbit_runtime_config hawkbit_get_config(void); static inline int hawkbit_set_server_addr(char *addr_str) { struct hawkbit_runtime_config set_config = { - .server_addr = addr_str, .server_port = 0, .auth_token = NULL}; + .server_addr = addr_str, .server_port = 0, .auth_token = NULL, .tls_tag = 0}; return hawkbit_set_config(&set_config); } @@ -175,7 +178,7 @@ static inline int hawkbit_set_server_addr(char *addr_str) static inline int hawkbit_set_server_port(uint16_t port) { struct hawkbit_runtime_config set_config = { - .server_addr = NULL, .server_port = port, .auth_token = NULL}; + .server_addr = NULL, .server_port = port, .auth_token = NULL, .tls_tag = 0}; return hawkbit_set_config(&set_config); } @@ -190,7 +193,22 @@ static inline int hawkbit_set_server_port(uint16_t port) static inline int hawkbit_set_ddi_security_token(char *token) { struct hawkbit_runtime_config set_config = { - .server_addr = NULL, .server_port = 0, .auth_token = token}; + .server_addr = NULL, .server_port = 0, .auth_token = token, .tls_tag = 0}; + + return hawkbit_set_config(&set_config); +} + +/** + * @brief Set the hawkBit TLS tag + * + * @param tag TLS tag to set. + * @retval 0 on success. + * @retval -EAGAIN if probe is currently running. + */ +static inline int hawkbit_set_tls_tag(sec_tag_t tag) +{ + struct hawkbit_runtime_config set_config = { + .server_addr = NULL, .server_port = 0, .auth_token = NULL, .tls_tag = tag}; return hawkbit_set_config(&set_config); } @@ -225,6 +243,16 @@ static inline char *hawkbit_get_ddi_security_token(void) return hawkbit_get_config().auth_token; } +/** + * @brief Get the hawkBit TLS tag. + * + * @return TLS tag. + */ +static inline sec_tag_t hawkbit_get_tls_tag(void) +{ + return hawkbit_get_config().tls_tag; +} + /** * @brief Get the hawkBit action id. * diff --git a/samples/subsys/mgmt/hawkbit/overlay-tls.conf b/samples/subsys/mgmt/hawkbit/overlay-tls.conf index e2b6db68494ed6..c550fcbb89de6e 100644 --- a/samples/subsys/mgmt/hawkbit/overlay-tls.conf +++ b/samples/subsys/mgmt/hawkbit/overlay-tls.conf @@ -8,3 +8,4 @@ CONFIG_MBEDTLS_HEAP_SIZE=60000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_HAWKBIT_USE_TLS=y diff --git a/samples/subsys/mgmt/hawkbit/sample.yaml b/samples/subsys/mgmt/hawkbit/sample.yaml index bce283490f822c..4a7bf0db6c7535 100644 --- a/samples/subsys/mgmt/hawkbit/sample.yaml +++ b/samples/subsys/mgmt/hawkbit/sample.yaml @@ -29,6 +29,7 @@ tests: - CONFIG_HAWKBIT_DDI_SECURITY_TOKEN="abcd1234" sample.net.hawkbit.tls: extra_configs: + - CONFIG_HAWKBIT_USE_TLS=y - CONFIG_NET_SOCKETS_SOCKOPT_TLS=y sample.net.hawkbit.set_settings_runtime: extra_configs: diff --git a/subsys/mgmt/hawkbit/Kconfig b/subsys/mgmt/hawkbit/Kconfig index 70808ec9ce67e6..b0c3b35c1aff09 100644 --- a/subsys/mgmt/hawkbit/Kconfig +++ b/subsys/mgmt/hawkbit/Kconfig @@ -111,6 +111,40 @@ config HAWKBIT_DEVICE_ID_MAX_LENGTH help Maximum length of the device id. +config HAWKBIT_USE_TLS + bool "Use TLS for hawkBit server connection" + depends on NET_SOCKETS_SOCKOPT_TLS + help + Use TLS for hawkBit connection. + +if HAWKBIT_USE_TLS + +choice HAWKBIT_CERT_TAG + prompt "hawkBit certificate tag" + default HAWKBIT_USE_STATIC_CERT_TAG + +config HAWKBIT_USE_STATIC_CERT_TAG + bool "Use static certificate tag" + help + Use static certificate tag for TLS connection to the hawkBit server. + +config HAWKBIT_USE_DYNAMIC_CERT_TAG + bool "Use dynamic certificate tag" + depends on HAWKBIT_SET_SETTINGS_RUNTIME + help + Use dynamic certificate tag for TLS connection to the hawkBit server. + +endchoice + +config HAWKBIT_STATIC_CERT_TAG + int "Static certificate tag" + depends on HAWKBIT_USE_STATIC_CERT_TAG + default 1 + help + Static certificate tag for TLS connection to the hawkBit server. + +endif + module = HAWKBIT module-str = Log Level for hawkbit module-help = Enables logging for hawkBit code. diff --git a/subsys/mgmt/hawkbit/hawkbit.c b/subsys/mgmt/hawkbit/hawkbit.c index f9da2ddd31a195..854500850b6e20 100644 --- a/subsys/mgmt/hawkbit/hawkbit.c +++ b/subsys/mgmt/hawkbit/hawkbit.c @@ -31,11 +31,6 @@ #include "hawkbit_firmware.h" #include "hawkbit_priv.h" -#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) -#define CA_CERTIFICATE_TAG 1 -#include -#endif - LOG_MODULE_REGISTER(hawkbit, CONFIG_HAWKBIT_LOG_LEVEL); #define CANCEL_BASE_SIZE 50 @@ -82,6 +77,9 @@ static struct hawkbit_config { #ifndef CONFIG_HAWKBIT_DDI_NO_SECURITY char ddi_security_token[DDI_SECURITY_TOKEN_SIZE + 1]; #endif +#ifdef CONFIG_HAWKBIT_USE_DYNAMIC_CERT_TAG + sec_tag_t tls_tag; +#endif #endif /* CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME */ } hb_cfg; @@ -103,6 +101,14 @@ static struct hawkbit_config { #define HAWKBIT_DDI_SECURITY_TOKEN CONFIG_HAWKBIT_DDI_SECURITY_TOKEN #endif /* CONFIG_HAWKBIT_DDI_NO_SECURITY */ +#ifdef CONFIG_HAWKBIT_USE_DYNAMIC_CERT_TAG +#define HAWKBIT_CERT_TAG hb_cfg.tls_tag +#elif defined(HAWKBIT_USE_STATIC_CERT_TAG) +#define HAWKBIT_CERT_TAG CONFIG_HAWKBIT_STATIC_CERT_TAG +#else +#define HAWKBIT_CERT_TAG 0 +#endif /* CONFIG_HAWKBIT_USE_DYNAMIC_CERT_TAG */ + struct hawkbit_download { int download_status; int download_progress; @@ -341,7 +347,7 @@ static bool start_http_client(void) struct zsock_addrinfo *addr; struct zsock_addrinfo hints = {0}; int resolve_attempts = 10; - int protocol = IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS) ? IPPROTO_TLS_1_2 : IPPROTO_TCP; + int protocol = IS_ENABLED(CONFIG_HAWKBIT_USE_TLS) ? IPPROTO_TLS_1_2 : IPPROTO_TCP; if (IS_ENABLED(CONFIG_NET_IPV6)) { hints.ai_family = AF_INET6; @@ -371,9 +377,9 @@ static bool start_http_client(void) goto err; } -#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) +#ifdef CONFIG_HAWKBIT_USE_TLS sec_tag_t sec_tag_opt[] = { - CA_CERTIFICATE_TAG, + HAWKBIT_CERT_TAG, }; if (zsock_setsockopt(hb_context.sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, @@ -385,7 +391,7 @@ static bool start_http_client(void) sizeof(HAWKBIT_SERVER)) < 0) { goto err_sock; } -#endif +#endif /* CONFIG_HAWKBIT_USE_TLS */ if (zsock_connect(hb_context.sock, addr->ai_addr, addr->ai_addrlen) < 0) { LOG_ERR("Failed to connect to server"); @@ -759,6 +765,12 @@ int hawkbit_set_config(struct hawkbit_runtime_config *config) hb_cfg.ddi_security_token); } #endif /* CONFIG_HAWKBIT_DDI_NO_SECURITY */ +#ifdef CONFIG_HAWKBIT_USE_DYNAMIC_CERT_TAG + if (config->tls_tag != 0) { + hb_cfg.tls_tag = config->tls_tag; + LOG_DBG("configured %s: %d", "hawkbit/tls_tag", hb_cfg.tls_tag); + } +#endif /* CONFIG_HAWKBIT_USE_DYNAMIC_CERT_TAG */ settings_save(); k_sem_give(&probe_sem); } else { @@ -776,6 +788,7 @@ struct hawkbit_runtime_config hawkbit_get_config(void) .server_addr = HAWKBIT_SERVER, .server_port = HAWKBIT_PORT_INT, .auth_token = HAWKBIT_DDI_SECURITY_TOKEN, + .tls_tag = HAWKBIT_CERT_TAG, }; return config; From 05100961f4b9d54767156eef99b27a9a266d2a1e Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0226/1389] soc/intel_adsp: ipc: initialize semaphore in driver init The ipc driver device data (struct intel_adsp_ipc_data) contains a semaphore. Upon device init, the device data is zeroed out. This is safe for other fields, but the semaphore should be properly initialized before use. This lack of initialization leads to a system crash when CONFIG_POLL is enabled (e.g. to enable CONFIG_SHELL), IPC driver handles an interrupt and executes k_sem_give() on a uninitialized semaphore object. This will eventually lead to null dereference in z_handle_obj_poll_events(). Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/common/ipc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soc/intel/intel_adsp/common/ipc.c b/soc/intel/intel_adsp/common/ipc.c index a33c03ebfde3ac..04503ca35e8f2d 100644 --- a/soc/intel/intel_adsp/common/ipc.c +++ b/soc/intel/intel_adsp/common/ipc.c @@ -100,6 +100,8 @@ int intel_adsp_ipc_init(const struct device *dev) memset(devdata, 0, sizeof(*devdata)); + k_sem_init(&devdata->sem, 0, 1); + /* ACK any latched interrupts (including TDA to clear IDA on * the other side!), then enable. */ From a3f48dd4d188596fd87e5b9bea1abc1a62eaa17d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0227/1389] net: config: correct dependency of NET_CONFIG* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrects the dependencies of NET_CONFIG* Signed-off-by: Fin Maaß --- subsys/net/lib/config/Kconfig | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/subsys/net/lib/config/Kconfig b/subsys/net/lib/config/Kconfig index d4d0584b997b96..64083eb3fc1cc3 100644 --- a/subsys/net/lib/config/Kconfig +++ b/subsys/net/lib/config/Kconfig @@ -3,6 +3,25 @@ # Copyright (c) 2017 Intel Corporation. # SPDX-License-Identifier: Apache-2.0 +module = NET_CONFIG +module-dep = NET_LOG +module-str = Log level for network config library +module-help = Enables net config library to output debug messages. +source "subsys/net/Kconfig.template.log_config.net" + +menuconfig NET_CONFIG_SETTINGS + bool "Set network settings for applications" + select NET_MGMT + select NET_MGMT_EVENT + help + Allow IP addresses to be set in config file for + networking client/server sample applications, or + some link-layer dedicated settings like the channel. + Beware this is not meant to be used for proper + provisioning but quick sampling/testing. + +if NET_CONFIG_SETTINGS + config NET_CONFIG_AUTO_INIT bool "Init networking support automatically during device startup" default n if USB_DEVICE_NETWORK @@ -12,22 +31,14 @@ config NET_CONFIG_AUTO_INIT initialized when the device is started. If you do not wish to do this, then disable this and call net_config_init() in your application. +if NET_CONFIG_AUTO_INIT + config NET_CONFIG_INIT_PRIO int "Startup priority for the network application init" default 95 - depends on NET_CONFIG_AUTO_INIT - -config NET_CONFIG_INIT_TIMEOUT - int "How long to wait for networking to be ready and available" - default 30 - help - The value is in seconds. If for example IPv4 address from DHCPv4 is not - received within this limit, then the net_config_init() call will fail - during the device startup. config NET_CONFIG_NEED_IPV6 bool "This application wants IPv6 support" - depends on NET_CONFIG_AUTO_INIT select NET_IPV6 help The network application needs IPv6 support to function properly. @@ -36,7 +47,6 @@ config NET_CONFIG_NEED_IPV6 config NET_CONFIG_NEED_IPV6_ROUTER bool "This application wants IPv6 router to exists" - depends on NET_CONFIG_AUTO_INIT depends on NET_IPV6 help The network application needs IPv6 router to exists before continuing. @@ -45,31 +55,21 @@ config NET_CONFIG_NEED_IPV6_ROUTER config NET_CONFIG_NEED_IPV4 bool "This application wants IPv4 support" - depends on NET_CONFIG_AUTO_INIT select NET_IPV4 help The network application needs IPv4 support to function properly. This option makes sure the network application is initialized properly in order to use IPv4. -module = NET_CONFIG -module-dep = NET_LOG -module-str = Log level for network config library -module-help = Enables net config library to output debug messages. -source "subsys/net/Kconfig.template.log_config.net" +endif # NET_CONFIG_AUTO_INIT -menuconfig NET_CONFIG_SETTINGS - bool "Set network settings for applications" - select NET_MGMT - select NET_MGMT_EVENT +config NET_CONFIG_INIT_TIMEOUT + int "How long to wait for networking to be ready and available" + default 30 help - Allow IP addresses to be set in config file for - networking client/server sample applications, or - some link-layer dedicated settings like the channel. - Beware this is not meant to be used for proper - provisioning but quick sampling/testing. - -if NET_CONFIG_SETTINGS + The value is in seconds. If for example IPv4 address from DHCPv4 is not + received within this limit, then the net_config_init() call will fail + during the device startup. config NET_CONFIG_MY_VLAN_ID int "My VLAN identifier" From 9e871a91da910aa288e893f5e7244888a107a067 Mon Sep 17 00:00:00 2001 From: Thibo Verheyde Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0228/1389] dts: bindings: Add Sequans GM02S Modem Add Sequans GM02S modem binding using the sqn vendor prefix. The modem has an active low reset signal. Signed-off-by: Thibo Verheyde --- dts/bindings/modem/sqn,gm02s.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 dts/bindings/modem/sqn,gm02s.yaml diff --git a/dts/bindings/modem/sqn,gm02s.yaml b/dts/bindings/modem/sqn,gm02s.yaml new file mode 100644 index 00000000000000..223b8c102a30fd --- /dev/null +++ b/dts/bindings/modem/sqn,gm02s.yaml @@ -0,0 +1,13 @@ +# Copyright(c) 2024 DPTechnics bv +# SPDX-License-Identifier: Apache-2.0 + +description: Sequans Monarch 2 GM02S Modem + +compatible: "sqn,gm02s" + +include: uart-device.yaml + +properties: + mdm-reset-gpios: + type: phandle-array + required: true From dcc6d1e68d71ce533864a51a0776150cefe7b556 Mon Sep 17 00:00:00 2001 From: Thibo Verheyde Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0229/1389] drivers: modem: modem_cellular: Add Sequans GM02S Modem Adds the necessary defines with init, dial and periodic chat scripts to support the Sequans GM02S Modem. Modification to cxreg handler to process GM02S +CEREG response. Signed-off-by: Thibo Verheyde --- drivers/modem/Kconfig.cellular | 2 +- drivers/modem/modem_cellular.c | 77 +++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/drivers/modem/Kconfig.cellular b/drivers/modem/Kconfig.cellular index aacf4449d28620..23446c62b728e7 100644 --- a/drivers/modem/Kconfig.cellular +++ b/drivers/modem/Kconfig.cellular @@ -16,7 +16,7 @@ config MODEM_CELLULAR DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \ DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \ DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_QUECTEL_EG25_G_ENABLED || \ - DT_HAS_NORDIC_NRF91_SLM_ENABLED) + DT_HAS_NORDIC_NRF91_SLM_ENABLED || DT_HAS_SQN_GM02S_ENABLED) help This driver uses the generic 3gpp AT commands, along with the standard protocols CMUX and PPP, to configure diff --git a/drivers/modem/modem_cellular.c b/drivers/modem/modem_cellular.c index c66264d349fbb2..7f646f4e789511 100644 --- a/drivers/modem/modem_cellular.c +++ b/drivers/modem/modem_cellular.c @@ -408,7 +408,7 @@ static void modem_cellular_chat_on_cxreg(struct modem_chat *chat, char **argv, u if (argc == 2) { registration_status = atoi(argv[1]); - } else if (argc == 3) { + } else if (argc == 3 || argc == 6) { registration_status = atoi(argv[2]); } else { return; @@ -458,7 +458,7 @@ MODEM_CHAT_MATCHES_DEFINE(dial_abort_matches, MODEM_CHAT_MATCH("NO CARRIER", "", NULL), MODEM_CHAT_MATCH("NO DIALTONE", "", NULL)); -#if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800) +#if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800) || DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s) MODEM_CHAT_MATCH_DEFINE(connect_match, "CONNECT", "", NULL); #endif @@ -2038,6 +2038,45 @@ MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_periodic_chat_script, modem_cellular_chat_callback_handler, 4); #endif +#if DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s) +MODEM_CHAT_SCRIPT_CMDS_DEFINE(sqn_gm02s_init_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match), + MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_init_chat_script, sqn_gm02s_init_chat_script_cmds, + abort_matches, modem_cellular_chat_callback_handler, 10); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(sqn_gm02s_dial_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\"," + "\""CONFIG_MODEM_CELLULAR_APN"\"", + ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CFUN=1", 10000), + MODEM_CHAT_SCRIPT_CMD_RESP("ATD*99***1#", connect_match)); + +MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_dial_chat_script, sqn_gm02s_dial_chat_script_cmds, + dial_abort_matches, modem_cellular_chat_callback_handler, 15); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(sqn_gm02s_periodic_chat_script_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, + sqn_gm02s_periodic_chat_script_cmds, abort_matches, + modem_cellular_chat_callback_handler, 4); +#endif + #define MODEM_CELLULAR_INST_NAME(name, inst) \ _CONCAT(_CONCAT(_CONCAT(name, _), DT_DRV_COMPAT), inst) @@ -2302,6 +2341,36 @@ MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_periodic_chat_script, &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, \ &modem_cellular_api); +#define MODEM_CELLULAR_DEVICE_SQN_GM02S(inst) \ + MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + \ + static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ + .chat_delimiter = "\r", \ + .chat_filter = "\n", \ + .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ + }; \ + \ + static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ + .autostarts = true, \ + .power_pulse_duration_ms = 1500, \ + .reset_pulse_duration_ms = 100, \ + .startup_time_ms = 2000, \ + .shutdown_time_ms = 5000, \ + .init_chat_script = &sqn_gm02s_init_chat_script, \ + .dial_chat_script = &sqn_gm02s_dial_chat_script, \ + .periodic_chat_script = &sqn_gm02s_periodic_chat_script, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ + &MODEM_CELLULAR_INST_NAME(data, inst), \ + &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, \ + &modem_cellular_api); + #define DT_DRV_COMPAT quectel_bg95 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_BG95) #undef DT_DRV_COMPAT @@ -2337,3 +2406,7 @@ DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_TELIT_ME910G1) #define DT_DRV_COMPAT nordic_nrf91_slm DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_NORDIC_NRF91_SLM) #undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT sqn_gm02s +DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SQN_GM02S) +#undef DT_DRV_COMPAT From 891ffbf1ab77b759c909f2987c7d06312366420a Mon Sep 17 00:00:00 2001 From: Thibo Verheyde Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0230/1389] tests: build_all: modem: Add Sequans GM02S Modem test Added test definition for Sequans GM02S Modem to build_all test. Signed-off-by: Thibo Verheyde --- tests/drivers/build_all/modem/uart.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/drivers/build_all/modem/uart.dtsi b/tests/drivers/build_all/modem/uart.dtsi index 08da2c325d39d6..96077f329ca234 100644 --- a/tests/drivers/build_all/modem/uart.dtsi +++ b/tests/drivers/build_all/modem/uart.dtsi @@ -76,3 +76,9 @@ test_nordic_nrf91_slm: nordic_nrf91_slm { mdm-power-gpios = <&test_gpio 0 0>; }; + +test_sqn_gm02s: sqn_gm02s { + compatible = "sqn,gm02s"; + + mdm-reset-gpios = <&test_gpio 0 0>; +}; From 8ae81dabc5fb18573722d11f1e8d205809fb7017 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0231/1389] arch: x86: coding guidelines: cast unused arguments to void - added missing ARG_UNUSED - added void to cast where ARG_UNUSED macro is not available Signed-off-by: frei tycho --- arch/x86/core/intel64/fatal.c | 2 ++ arch/x86/core/intel64/thread.c | 7 +++++++ arch/x86/core/x86_mmu.c | 7 +++++++ arch/x86/include/x86_mmu.h | 2 ++ arch/x86/zefi/zefi.c | 2 ++ 5 files changed, 20 insertions(+) diff --git a/arch/x86/core/intel64/fatal.c b/arch/x86/core/intel64/fatal.c index 5772234a0d9ccc..9dd97614dc1e3c 100644 --- a/arch/x86/core/intel64/fatal.c +++ b/arch/x86/core/intel64/fatal.c @@ -15,6 +15,8 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); */ __weak bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf) { + ARG_UNUSED(esf); + return false; } diff --git a/arch/x86/core/intel64/thread.c b/arch/x86/core/intel64/thread.c index f26f25ab5f1562..49cb58ec9c6878 100644 --- a/arch/x86/core/intel64/thread.c +++ b/arch/x86/core/intel64/thread.c @@ -37,6 +37,8 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, * which is only needed if the stack is not memory mapped. */ z_x86_set_stack_guard(stack); +#else + ARG_UNUSED(stack); #endif #ifdef CONFIG_USERSPACE switch_entry = z_x86_userspace_prepare_thread(thread); @@ -68,11 +70,16 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, int arch_float_disable(struct k_thread *thread) { /* x86-64 always has FP/SSE enabled so cannot be disabled */ + ARG_UNUSED(thread); + return -ENOTSUP; } int arch_float_enable(struct k_thread *thread, unsigned int options) { /* x86-64 always has FP/SSE enabled so nothing to do here */ + ARG_UNUSED(thread); + ARG_UNUSED(options); + return 0; } diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index c8735f43dd9251..5540cebce7061b 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -450,6 +450,8 @@ static inline void assert_addr_aligned(uintptr_t addr) #if __ASSERT_ON __ASSERT((addr & (CONFIG_MMU_PAGE_SIZE - 1)) == 0U, "unaligned address 0x%" PRIxPTR, addr); +#else + ARG_UNUSED(addr); #endif } @@ -481,6 +483,8 @@ static inline void assert_size_aligned(size_t size) #if __ASSERT_ON __ASSERT((size & (CONFIG_MMU_PAGE_SIZE - 1)) == 0U, "unaligned size %zu", size); +#else + ARG_UNUSED(size); #endif } @@ -828,6 +832,9 @@ static inline pentry_t pte_finalize_value(pentry_t val, bool user_table, get_entry_phys(val, level) != shared_phys_addr) { val = ~val; } +#else + ARG_UNUSED(user_table); + ARG_UNUSED(level); #endif return val; } diff --git a/arch/x86/include/x86_mmu.h b/arch/x86/include/x86_mmu.h index 0328e98d735382..31c8526cb7a0b1 100644 --- a/arch/x86/include/x86_mmu.h +++ b/arch/x86/include/x86_mmu.h @@ -217,6 +217,8 @@ static inline pentry_t *z_x86_thread_page_tables_get(struct k_thread *thread) */ return z_mem_virt_addr(thread->arch.ptables); } +#else + ARG_UNUSED(thread); #endif return z_x86_kernel_ptables; } diff --git a/arch/x86/zefi/zefi.c b/arch/x86/zefi/zefi.c index 0f81398f4a8b5b..015a6ff50a26e7 100644 --- a/arch/x86/zefi/zefi.c +++ b/arch/x86/zefi/zefi.c @@ -134,6 +134,8 @@ static void disable_hpet(void) */ uintptr_t __abi efi_entry(void *img_handle, struct efi_system_table *sys_tab) { + (void)img_handle; + efi = sys_tab; z_putchar = efi_putchar; printf("*** Zephyr EFI Loader ***\n"); From 24a31ce962e9337bba2d3338b7f93a0b022c0a5f Mon Sep 17 00:00:00 2001 From: Russ Webber Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0232/1389] fs: fuse: fix fuse include path This commit fixes the incorrect include path for the fuse library. pkg_search_module populates the _INCLUDE_DIRS cmake var. Signed-off-by: Russ Webber --- subsys/fs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/fs/CMakeLists.txt b/subsys/fs/CMakeLists.txt index e6c66d304ceee8..fb774711543a7b 100644 --- a/subsys/fs/CMakeLists.txt +++ b/subsys/fs/CMakeLists.txt @@ -30,7 +30,7 @@ if(CONFIG_FUSE_FS_ACCESS) zephyr_library_named(FS_FUSE) find_package(PkgConfig REQUIRED) pkg_search_module(FUSE REQUIRED fuse) - zephyr_include_directories(${FUSE_INCLUDE_DIR}) + zephyr_include_directories(${FUSE_INCLUDE_DIRS}) if (CONFIG_NATIVE_LIBRARY) target_link_options(native_simulator INTERFACE "-l${FUSE_LIBRARIES}") else() From 5af6e4000b3cf3edc8b9631c2b1c1fbab331aca3 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0233/1389] MAINTAINERS: Add collaborator for ethernet drivers (OA TC6 and T1S) I can help as a collaborator for the network's ethernet subsystem (especially the OA TC6 driver). Signed-off-by: Lukasz Majewski --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index e20c8ef4d894da..3f5c638347c443 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1233,6 +1233,7 @@ Release Notes: status: odd fixes collaborators: - decsny + - lmajewski files: - drivers/ethernet/ - include/zephyr/dt-bindings/ethernet/ From 35eb34a0a28b8b76f4df75438435aba833d2c9dc Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0234/1389] mgmt: updatehub: Fix mark for update This fixes compatibility with recent bootutils API. Signed-off-by: Gerson Fernando Budke --- subsys/mgmt/updatehub/updatehub_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/mgmt/updatehub/updatehub_storage.c b/subsys/mgmt/updatehub/updatehub_storage.c index d18b24be4bc91a..81886a9044e239 100644 --- a/subsys/mgmt/updatehub/updatehub_storage.c +++ b/subsys/mgmt/updatehub/updatehub_storage.c @@ -73,7 +73,7 @@ int updatehub_storage_mark_partition_to_upgrade(struct updatehub_storage_context return -EINVAL; } - return boot_request_upgrade_multi(partition_id, BOOT_UPGRADE_TEST); + return boot_request_upgrade(BOOT_UPGRADE_TEST); } int updatehub_storage_mark_partition_as_confirmed(const uint32_t partition_id) From 098e244927b259d95a76790c468041c0e023e87a Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0235/1389] Documentation: Update Polling API Changes: 1. the number of events being checked did not equal those defined in the `events` array. 2. Use `k_poll_signal_check()` instead of accessing fields directly. 3. Use `k_poll_signal_reset()` to reset the signal instead of accessing fields directly. I'm assuming the examples predate `k_poll_signal_check()` and `k_poll_signal_reset()` Signed-off-by: Glenn Andrews --- doc/kernel/services/polling.rst | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/doc/kernel/services/polling.rst b/doc/kernel/services/polling.rst index 71937648a93199..46e586badb6e99 100644 --- a/doc/kernel/services/polling.rst +++ b/doc/kernel/services/polling.rst @@ -156,7 +156,7 @@ In case of success, :c:func:`k_poll` returns 0. If it times out, it returns void do_stuff(void) { - rc = k_poll(events, 2, 1000); + rc = k_poll(events, ARRAY_SIZE(events), K_MSEC(1000)); if (rc == 0) { if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) { k_sem_take(events[0].sem, 0); @@ -183,7 +183,7 @@ to :c:macro:`K_POLL_STATE_NOT_READY` by the user. void do_stuff(void) { for(;;) { - rc = k_poll(events, 2, K_FOREVER); + rc = k_poll(events, ARRAY_SIZE(events), K_FOREVER); if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) { k_sem_take(events[0].sem, 0); } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) { @@ -243,7 +243,11 @@ pass extra information to the thread waiting on the event. k_poll(events, 1, K_FOREVER); - if (events.signal->result == 0x1337) { + int signaled, result; + + k_poll_signal_check(&signal, &signaled, &result); + + if (signaled && (result == 0x1337)) { // A-OK! } else { // weird error @@ -256,8 +260,10 @@ pass extra information to the thread waiting on the event. k_poll_signal_raise(&signal, 0x1337); } -If the signal is to be polled in a loop, *both* its event state and its -**signaled** field *must* be reset on each iteration if it has been signaled. +If the signal is to be polled in a loop, *both* its event state must be +reset to :c:macro:`K_POLL_STATE_NOT_READY` *and* its ``result`` must be +reset using :c:func:`k_poll_signal_reset()` on each iteration if it has +been signaled. .. code-block:: c @@ -275,13 +281,17 @@ If the signal is to be polled in a loop, *both* its event state and its for (;;) { k_poll(events, 1, K_FOREVER); - if (events[0].signal->result == 0x1337) { + int signaled, result; + + k_poll_signal_check(&signal, &signaled, &result); + + if (signaled && (result == 0x1337)) { // A-OK! } else { // weird error } - events[0].signal->signaled = 0; + k_poll_signal_reset(signal); events[0].state = K_POLL_STATE_NOT_READY; } } From a88ac90b84daff48206176a842df3d9ed83cbe74 Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0236/1389] cmake: llvm: arm: Remove '--specs' when building with clang for arm Currently, clang produces a warning that the '--specs=nosys.specs' argument is unused. Remove this flag to fix the warning as clang will generally not honor '--specs' when targeting arm baremetal. While this flag has been present for some time, I think this should be safe to do. For background, clang does not seem to handle '--specs' [1] besides possibly passing it through to GCC if GCC is used as the driver for linking. However, whether GCC will be used for linking as a fallback depends on the "Toolchain" [1] clang uses internally, which in turn depends on the triple. For arm/thumb baremetal triples, the Toolchain clang uses will not fall back to GCC to drive linking, so '--specs' will never be used here. I believe this behavior in clang is fairly longstanding as well (since ~2017/LLVM 5 [2]). While there isn't a minimum required clang version for Zephyr, Zephyr currently requires lld >= 14.0.0. So, I don't think removing this flag should impact current users (besides preventing the warning). [1] https://clang.llvm.org/docs/DriverInternals.html [2] https://reviews.llvm.org/D33259 Signed-off-by: Jonathon Penix --- cmake/toolchain/llvm/target.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/toolchain/llvm/target.cmake b/cmake/toolchain/llvm/target.cmake index a2240c023643a8..8446e22ced8fbe 100644 --- a/cmake/toolchain/llvm/target.cmake +++ b/cmake/toolchain/llvm/target.cmake @@ -25,8 +25,6 @@ if("${ARCH}" STREQUAL "arm") # Default ARM target supported by all processors. set(triple arm-none-eabi) endif() - - set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs") elseif("${ARCH}" STREQUAL "x86") if(CONFIG_64BIT) set(triple x86_64-pc-none-elf) From e8e51175137378dfea08d723afb150ff78a0b6b7 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Sun, 26 May 2024 22:38:36 +0200 Subject: [PATCH 0237/1389] Bluetooth: CAP: Commander Reception start procedure Add the CAP commander reception start procedure which starts reception on one or more CAP acceptors With the implementation of broadcast reception start procedure we also need some mockups for unit testing Signed-off-by: Andries Kruithof --- include/zephyr/bluetooth/audio/cap.h | 16 +- subsys/bluetooth/audio/bap_internal.h | 13 + subsys/bluetooth/audio/bap_scan_delegator.c | 13 - subsys/bluetooth/audio/cap_commander.c | 341 +++++++++++++++++- subsys/bluetooth/audio/cap_common.c | 1 + subsys/bluetooth/audio/cap_internal.h | 16 + tests/bluetooth/audio/cap_commander/prj.conf | 2 +- .../audio/cap_commander/uut/CMakeLists.txt | 4 + .../uut/bap_broadcast_assistant.c | 30 ++ 9 files changed, 403 insertions(+), 33 deletions(-) create mode 100644 tests/bluetooth/audio/cap_commander/uut/bap_broadcast_assistant.c diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index 8119c0e2e9ef83..9c785b87e98437 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -750,6 +750,20 @@ struct bt_cap_commander_cb { void (*microphone_gain_changed)(struct bt_conn *conn, int err); #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */ #endif /* CONFIG_BT_MICP_MIC_CTLR */ + +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) + /** + * @brief Callback for bt_cap_commander_broadcast_reception_start(). + * + * @param conn Pointer to the connection where the error + * occurred. NULL if @p err is 0 or if cancelled by + * bt_cap_commander_cancel() + * @param err 0 on success, BT_GATT_ERR() with a + * specific ATT (BT_ATT_ERR_*) error code or -ECANCELED if cancelled + * by bt_cap_commander_cancel(). + */ + void (*broadcast_reception_start)(struct bt_conn *conn, int err); +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ }; /** @@ -842,7 +856,7 @@ struct bt_cap_commander_broadcast_reception_start_member_param { * * At least one bit in one of the subgroups bis_sync parameters shall be set. */ - struct bt_bap_bass_subgroup *subgroups; + struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; /** Number of subgroups */ size_t num_subgroups; diff --git a/subsys/bluetooth/audio/bap_internal.h b/subsys/bluetooth/audio/bap_internal.h index 5eb53f5de586ca..27f62977a22873 100644 --- a/subsys/bluetooth/audio/bap_internal.h +++ b/subsys/bluetooth/audio/bap_internal.h @@ -123,3 +123,16 @@ static inline const char *bt_bap_big_enc_state_str(uint8_t state) return "unknown state"; } } + +static inline bool valid_bis_syncs(uint32_t bis_sync) +{ + if (bis_sync == BT_BAP_BIS_SYNC_NO_PREF) { + return true; + } + + if (bis_sync > BIT_MASK(31)) { /* Max BIS index */ + return false; + } + + return true; +} diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index 09cd2327051ebf..6a55d7da2c351e 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -88,19 +88,6 @@ static bool bits_subset_of(uint32_t a, uint32_t b) return (((a) & (~(b))) == 0); } -static bool valid_bis_syncs(uint32_t bis_sync) -{ - if (bis_sync == BT_BAP_BIS_SYNC_NO_PREF) { - return true; - } - - if (bis_sync > BIT_MASK(31)) { /* Max BIS index */ - return false; - } - - return true; -} - static bool bis_syncs_unique_or_no_pref(uint32_t requested_bis_syncs, uint32_t aggregated_bis_syncs) { diff --git a/subsys/bluetooth/audio/cap_commander.c b/subsys/bluetooth/audio/cap_commander.c index b65eb453ce9cdb..f7c05a4e55f5ea 100644 --- a/subsys/bluetooth/audio/cap_commander.c +++ b/subsys/bluetooth/audio/cap_commander.c @@ -11,6 +11,7 @@ #include #include #include +#include "bap_internal.h" #include "cap_internal.h" #include "ccid_internal.h" #include "csip_internal.h" @@ -22,17 +23,21 @@ LOG_MODULE_REGISTER(bt_cap_commander, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL); #include "common/bt_str.h" +static void cap_commander_proc_complete(void); + static const struct bt_cap_commander_cb *cap_cb; int bt_cap_commander_register_cb(const struct bt_cap_commander_cb *cb) { CHECKIF(cb == NULL) { LOG_DBG("cb is NULL"); + return -EINVAL; } CHECKIF(cap_cb != NULL) { LOG_DBG("callbacks already registered"); + return -EALREADY; } @@ -77,18 +82,311 @@ int bt_cap_commander_discover(struct bt_conn *conn) return bt_cap_common_discover(conn, cap_commander_discover_complete); } +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) +static struct bt_bap_broadcast_assistant_cb broadcast_assistant_cb; +static bool ba_cb_registered; + +static void +copy_broadcast_reception_start_param(struct bt_bap_broadcast_assistant_add_src_param *add_src_param, + struct cap_broadcast_reception_start *start_param) +{ + bt_addr_le_copy(&add_src_param->addr, &start_param->addr); + add_src_param->adv_sid = start_param->adv_sid; + add_src_param->broadcast_id = start_param->broadcast_id; + add_src_param->pa_interval = start_param->pa_interval; + add_src_param->num_subgroups = start_param->num_subgroups; + add_src_param->subgroups = start_param->subgroups; +} + +static void cap_commander_ba_add_src_cb(struct bt_conn *conn, int err) +{ + struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc(); + struct bt_bap_broadcast_assistant_add_src_param add_src_param = {0}; + + LOG_DBG("conn %p", (void *)conn); + + if (!bt_cap_common_conn_in_active_proc(conn)) { + + /* State change happened outside of a procedure; ignore */ + return; + } + + if (err != 0) { + LOG_DBG("Failed to add source: %d", err); + LOG_DBG("Aborting the proc %d %d", active_proc->proc_done_cnt, + active_proc->proc_initiated_cnt); + + bt_cap_common_abort_proc(conn, err); + } else { + active_proc->proc_done_cnt++; + + LOG_DBG("Conn %p broadcast source added (%zu/%zu streams done)", (void *)conn, + active_proc->proc_done_cnt, active_proc->proc_cnt); + } + + if (bt_cap_common_proc_is_aborted()) { + if (bt_cap_common_proc_all_handled()) { + cap_commander_proc_complete(); + } + + return; + } + + if (!bt_cap_common_proc_is_done()) { + struct bt_cap_commander_proc_param *proc_param; + + proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt]; + conn = proc_param->conn; + copy_broadcast_reception_start_param(&add_src_param, + &proc_param->broadcast_reception_start); + + active_proc->proc_initiated_cnt++; + err = bt_bap_broadcast_assistant_add_src(conn, &add_src_param); + if (err != 0) { + LOG_DBG("Failed to perform broadcast reception start for conn %p: %d", + (void *)conn, err); + bt_cap_common_abort_proc(conn, err); + cap_commander_proc_complete(); + } + } else { + cap_commander_proc_complete(); + } +} + +static int cap_commander_register_ba_cb(void) +{ + int err; + + err = bt_bap_broadcast_assistant_register_cb(&broadcast_assistant_cb); + if (err != 0) { + LOG_DBG("Failed to register broadcast assistant callbacks: %d", err); + + return -ENOEXEC; + } + + ba_cb_registered = true; + + return 0; +} + +static bool valid_broadcast_reception_start_param( + const struct bt_cap_commander_broadcast_reception_start_param *param) +{ + uint32_t total_bis_sync = 0U; + + CHECKIF(param == NULL) { + LOG_DBG("param is NULL"); + return false; + } + + CHECKIF(param->count == 0) { + LOG_DBG("Invalid param->count: %u", param->count); + return false; + } + + CHECKIF(param->count > CONFIG_BT_MAX_CONN) { + LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count, + CONFIG_BT_MAX_CONN); + return false; + } + + CHECKIF(param->param == NULL) { + LOG_DBG("param->param is NULL"); + return false; + } + + for (size_t i = 0; i < param->count; i++) { + const struct bt_cap_commander_broadcast_reception_start_member_param *start_param = + ¶m->param[i]; + const union bt_cap_set_member *member = ¶m->param[i].member; + const struct bt_cap_common_client *client = + bt_cap_common_get_client(param->type, member); + + if (member == NULL) { + LOG_DBG("param->param[%zu].member is NULL", i); + return false; + } + + if (client == NULL) { + LOG_DBG("Invalid param->param[%zu].member", i); + return false; + } + + CHECKIF(start_param->addr.type > BT_ADDR_LE_RANDOM) { + LOG_DBG("Invalid address type %u", start_param->addr.type); + return false; + } + + CHECKIF(start_param->adv_sid > BT_GAP_SID_MAX) { + LOG_DBG("param->param[%zu]->adv_sid is larger than %d", i, BT_GAP_SID_MAX); + return false; + } + + CHECKIF(!IN_RANGE(start_param->pa_interval, BT_GAP_PER_ADV_MIN_INTERVAL, + BT_GAP_PER_ADV_MAX_INTERVAL)) { + LOG_DBG("param->param[%zu]->pa_interval is out of range", i); + return false; + } + + CHECKIF(start_param->broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) { + LOG_DBG("param->param[%zu]->broadcast_id is larger than %u", i, + BT_AUDIO_BROADCAST_ID_MAX); + return false; + } + + CHECKIF(start_param->num_subgroups == 0) { + LOG_DBG("param->param[%zu]->num_subgroups is 0", i); + return false; + } + + CHECKIF(start_param->num_subgroups > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) { + LOG_DBG("Too many subgroups %u/%u", start_param->num_subgroups, + CONFIG_BT_BAP_BASS_MAX_SUBGROUPS); + + return false; + } + + CHECKIF(start_param->subgroups == NULL) { + LOG_DBG("param->param[%zu]->subgroup is NULL", i); + return false; + } + + for (size_t j = 0U; j < start_param->num_subgroups; j++) { + const struct bt_bap_bass_subgroup *param_subgroups = + &start_param->subgroups[j]; + + CHECKIF(!valid_bis_syncs(param_subgroups->bis_sync)) { + LOG_DBG("param->param[%zu].subgroup[%zu].bis_sync is invalid %u", i, + j, param_subgroups->bis_sync); + } + + CHECKIF((total_bis_sync & param_subgroups->bis_sync) != 0) { + LOG_DBG("param->param[%zu].subgroup[%zu].bis_sync 0x%08X has " + "duplicate bits (0x%08X) ", + i, j, param_subgroups->bis_sync, total_bis_sync); + } + + total_bis_sync |= param_subgroups->bis_sync; + + CHECKIF(param_subgroups->metadata_len > + CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) { + LOG_DBG("param->param[%zu].subgroup[%zu].metadata_len too long " + "%u/%u", + i, j, param_subgroups->metadata_len, + CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE); + + return false; + } +#if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) + CHECKIF(param_subgroups->metadata_len > 0 && + !bt_audio_valid_ltv(param_subgroups->metadata, + param_subgroups->metadata_len)) { + LOG_DBG("param->param[%zu].subgroup[%zu].metadata not valid LTV", i, + j); + } +#endif + } + + for (size_t j = 0U; j < i; j++) { + const union bt_cap_set_member *other = ¶m->param[j].member; + + if (other == member) { + LOG_DBG("param->members[%zu] (%p) is duplicated by " + "param->members[%zu] (%p)", + j, other, i, member); + return false; + } + } + } + + return true; +} + int bt_cap_commander_broadcast_reception_start( const struct bt_cap_commander_broadcast_reception_start_param *param) { - return -ENOSYS; + struct bt_bap_broadcast_assistant_add_src_param add_src_param = {0}; + struct bt_cap_commander_proc_param *proc_param; + struct bt_cap_common_proc *active_proc; + struct bt_conn *conn; + int err; + + if (bt_cap_common_proc_is_active()) { + LOG_DBG("A CAP procedure is already in progress"); + + return -EBUSY; + } + + if (!valid_broadcast_reception_start_param(param)) { + return -EINVAL; + } + + bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START, param->count); + + broadcast_assistant_cb.add_src = cap_commander_ba_add_src_cb; + if (!ba_cb_registered && cap_commander_register_ba_cb() != 0) { + LOG_DBG("Failed to register VCP callbacks"); + + return -ENOEXEC; + } + + active_proc = bt_cap_common_get_active_proc(); + + for (size_t i = 0U; i < param->count; i++) { + const struct bt_cap_commander_broadcast_reception_start_member_param *member_param = + ¶m->param[i]; + struct bt_cap_commander_proc_param *stored_param; + struct bt_conn *member_conn = + bt_cap_common_get_member_conn(param->type, &member_param->member); + + if (member_conn == NULL) { + LOG_DBG("Invalid param->members[%zu]", i); + + return -EINVAL; + } + + /* Store the necessary parameters as we cannot assume that the supplied parameters + * are kept valid + * TODO: consider putting this into a function + */ + stored_param = &active_proc->proc_param.commander[i]; + stored_param->conn = member_conn; + bt_addr_le_copy(&stored_param->broadcast_reception_start.addr, &member_param->addr); + stored_param->broadcast_reception_start.adv_sid = member_param->adv_sid; + stored_param->broadcast_reception_start.broadcast_id = member_param->broadcast_id; + stored_param->broadcast_reception_start.pa_interval = member_param->pa_interval; + stored_param->broadcast_reception_start.num_subgroups = member_param->num_subgroups; + memcpy(stored_param->broadcast_reception_start.subgroups, member_param->subgroups, + sizeof(struct bt_bap_bass_subgroup) * add_src_param.num_subgroups); + } + + active_proc->proc_initiated_cnt++; + + proc_param = &active_proc->proc_param.commander[0]; + + conn = proc_param->conn; + copy_broadcast_reception_start_param(&add_src_param, + &proc_param->broadcast_reception_start); + + /* TODO: what to do if we are adding a source that has already been added? */ + err = bt_bap_broadcast_assistant_add_src(conn, &add_src_param); + if (err != 0) { + LOG_DBG("Failed to start broadcast reception for conn %p: %d", (void *)conn, err); + + return -ENOEXEC; + } + + return 0; } +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ int bt_cap_commander_broadcast_reception_stop( const struct bt_cap_commander_broadcast_reception_stop_param *param) { return -ENOSYS; } -static void cap_commander_unicast_audio_proc_complete(void) + +static void cap_commander_proc_complete(void) { struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc(); enum bt_cap_common_proc_type proc_type; @@ -138,6 +436,13 @@ static void cap_commander_unicast_audio_proc_complete(void) break; #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */ #endif /* CONFIG_BT_MICP_MIC_CTLR */ +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) + case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START: + if (cap_cb->broadcast_reception_start != NULL) { + cap_cb->broadcast_reception_start(failed_conn, err); + } + break; +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ case BT_CAP_COMMON_PROC_TYPE_NONE: default: __ASSERT(false, "Invalid proc_type: %u", proc_type); @@ -153,7 +458,7 @@ int bt_cap_commander_cancel(void) } bt_cap_common_abort_proc(NULL, -ECANCELED); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); return 0; } @@ -265,7 +570,7 @@ static void cap_commander_vcp_vol_set_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int e LOG_DBG("Proc is aborted"); if (bt_cap_common_proc_all_handled()) { LOG_DBG("All handled"); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } return; @@ -282,10 +587,10 @@ static void cap_commander_vcp_vol_set_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int e if (err != 0) { LOG_DBG("Failed to set volume for conn %p: %d", (void *)conn, err); bt_cap_common_abort_proc(conn, err); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } else { - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } @@ -434,7 +739,7 @@ static void cap_commander_vcp_vol_mute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int LOG_DBG("Proc is aborted"); if (bt_cap_common_proc_all_handled()) { LOG_DBG("All handled"); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } return; @@ -455,10 +760,10 @@ static void cap_commander_vcp_vol_mute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int if (err != 0) { LOG_DBG("Failed to set volume for conn %p: %d", (void *)conn, err); bt_cap_common_abort_proc(conn, err); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } else { - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } @@ -634,7 +939,7 @@ static void cap_commander_vcp_set_offset_cb(struct bt_vocs *inst, int err) LOG_DBG("Proc is aborted"); if (bt_cap_common_proc_all_handled()) { LOG_DBG("All handled"); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } return; @@ -652,10 +957,10 @@ static void cap_commander_vcp_set_offset_cb(struct bt_vocs *inst, int err) if (err != 0) { LOG_DBG("Failed to set offset for conn %p: %d", (void *)conn, err); bt_cap_common_abort_proc(conn, err); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } else { - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } @@ -847,7 +1152,7 @@ static void cap_commander_micp_mic_mute_cb(struct bt_micp_mic_ctlr *mic_ctlr, in LOG_DBG("Proc is aborted"); if (bt_cap_common_proc_all_handled()) { LOG_DBG("All handled"); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } return; @@ -868,10 +1173,10 @@ static void cap_commander_micp_mic_mute_cb(struct bt_micp_mic_ctlr *mic_ctlr, in if (err != 0) { LOG_DBG("Failed to change mute for conn %p: %d", (void *)conn, err); bt_cap_common_abort_proc(conn, err); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } else { - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } @@ -1040,7 +1345,7 @@ static void cap_commander_micp_gain_set_cb(struct bt_aics *inst, int err) LOG_DBG("Proc is aborted"); if (bt_cap_common_proc_all_handled()) { LOG_DBG("All handled"); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } return; @@ -1056,10 +1361,10 @@ static void cap_commander_micp_gain_set_cb(struct bt_aics *inst, int err) if (err != 0) { LOG_DBG("Failed to set gain for conn %p: %d", (void *)conn, err); bt_cap_common_abort_proc(conn, err); - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } else { - cap_commander_unicast_audio_proc_complete(); + cap_commander_proc_complete(); } } diff --git a/subsys/bluetooth/audio/cap_common.c b/subsys/bluetooth/audio/cap_common.c index 23de8c19cb7ecf..ea45041159992f 100644 --- a/subsys/bluetooth/audio/cap_common.c +++ b/subsys/bluetooth/audio/cap_common.c @@ -124,6 +124,7 @@ static bool active_proc_is_commander(void) case BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE: case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_GAIN_CHANGE: case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_MUTE_CHANGE: + case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START: return true; default: return false; diff --git a/subsys/bluetooth/audio/cap_internal.h b/subsys/bluetooth/audio/cap_internal.h index 2210110703ff4d..a2605e4b0c77ca 100644 --- a/subsys/bluetooth/audio/cap_internal.h +++ b/subsys/bluetooth/audio/cap_internal.h @@ -36,6 +36,7 @@ enum bt_cap_common_proc_type { BT_CAP_COMMON_PROC_TYPE_START, BT_CAP_COMMON_PROC_TYPE_UPDATE, BT_CAP_COMMON_PROC_TYPE_STOP, + BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START, BT_CAP_COMMON_PROC_TYPE_VOLUME_CHANGE, BT_CAP_COMMON_PROC_TYPE_VOLUME_OFFSET_CHANGE, BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE, @@ -70,6 +71,18 @@ struct bt_cap_initiator_proc_param { }; }; +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) +struct cap_broadcast_reception_start { + + bt_addr_le_t addr; + uint8_t adv_sid; + uint32_t broadcast_id; + uint16_t pa_interval; + uint8_t num_subgroups; + struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; +}; +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ + struct bt_cap_commander_proc_param { struct bt_conn *conn; union { @@ -87,6 +100,9 @@ struct bt_cap_commander_proc_param { struct bt_vocs *vocs; } change_offset; #endif /* CONFIG_BT_VCP_VOL_CTLR_VOCS */ +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) + struct cap_broadcast_reception_start broadcast_reception_start; +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #if defined(CONFIG_BT_MICP_MIC_CTLR) struct { bool mute; diff --git a/tests/bluetooth/audio/cap_commander/prj.conf b/tests/bluetooth/audio/cap_commander/prj.conf index c281867619aed8..231fe10c2e1849 100644 --- a/tests/bluetooth/audio/cap_commander/prj.conf +++ b/tests/bluetooth/audio/cap_commander/prj.conf @@ -15,7 +15,7 @@ CONFIG_BT_AICS_CLIENT_MAX_INSTANCE_COUNT=1 CONFIG_BT_MICP_MIC_CTLR_MAX_AICS_INST=1 CONFIG_BT_CAP_COMMANDER=y - +CONFIG_BT_BAP_BROADCAST_ASSISTANT=y CONFIG_LOG=y CONFIG_BT_CAP_COMMANDER_LOG_LEVEL_DBG=y diff --git a/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt b/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt index d1455879e57776..007ea55fb9b9d2 100644 --- a/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt +++ b/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt @@ -7,10 +7,14 @@ # add_library(uut STATIC + ${ZEPHYR_BASE}/subsys/bluetooth/audio/audio.c + ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_iso.c + ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_stream.c ${ZEPHYR_BASE}/subsys/bluetooth/audio/cap_commander.c ${ZEPHYR_BASE}/subsys/bluetooth/audio/cap_common.c ${ZEPHYR_BASE}/subsys/logging/log_minimal.c ${ZEPHYR_BASE}/subsys/net/buf_simple.c + bap_broadcast_assistant.c aics.c csip.c micp.c diff --git a/tests/bluetooth/audio/cap_commander/uut/bap_broadcast_assistant.c b/tests/bluetooth/audio/cap_commander/uut/bap_broadcast_assistant.c new file mode 100644 index 00000000000000..e4ec106c8f658d --- /dev/null +++ b/tests/bluetooth/audio/cap_commander/uut/bap_broadcast_assistant.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "zephyr/bluetooth/audio/bap.h" + +static struct bt_bap_broadcast_assistant_cb *broadcast_assistant_cbs; + +int bt_bap_broadcast_assistant_register_cb(struct bt_bap_broadcast_assistant_cb *cb) +{ + broadcast_assistant_cbs = cb; + + return 0; +} + +int bt_bap_broadcast_assistant_add_src(struct bt_conn *conn, + const struct bt_bap_broadcast_assistant_add_src_param *param) +{ + /* Note that proper parameter checking is done in the caller */ + zassert_not_null(conn, "conn is NULL"); + zassert_not_null(param, "param is NULL"); + + if (broadcast_assistant_cbs->add_src != NULL) { + broadcast_assistant_cbs->add_src(conn, 0); + } + + return 0; +} From c5cdd1669962a969cf66319c4a2779b9b75d9fac Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0238/1389] arch: riscv: only use z_riscv_fatal_error_csf if CONFIG_EXCEPTION_DEBUG Use `z_riscv_fatal_error_csf` that expects the callee-saved-registers pointer only if `CONFIG_EXCEPTION_DEBUG` is enabled, otherwise use `z_riscv_fatal_error`, as there can be garbage in the `a2`. Signed-off-by: Yong Cong Sin --- arch/riscv/core/isr.S | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index a6cb89e7c85e22..2a8ed28deae760 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -78,7 +78,12 @@ GTEXT(__soc_save_context) GTEXT(__soc_restore_context) #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ +#ifdef CONFIG_EXCEPTION_DEBUG GTEXT(z_riscv_fatal_error_csf) +#else +GTEXT(z_riscv_fatal_error) +#endif /* CONFIG_EXCEPTION_DEBUG */ + GTEXT(z_get_next_switch_handle) GTEXT(z_riscv_switch) GTEXT(z_riscv_thread_start) @@ -411,9 +416,11 @@ do_fault: /* Save callee-saved registers to be passed as 3rd arg */ STORE_CALLEE_SAVED() ; mv a2, sp -#endif tail z_riscv_fatal_error_csf +#else + tail z_riscv_fatal_error +#endif #if defined(CONFIG_IRQ_OFFLOAD) do_irq_offload: From 8508380b6d6de1b03f8c9d896a88facdb9cffec6 Mon Sep 17 00:00:00 2001 From: Benedikt Schmidt Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0239/1389] doc: migration-guide-3.7: add MAX31790 Add migration of MAX31790 to the guide for 3.7. Signed-off-by: Benedikt Schmidt --- doc/releases/migration-guide-3.7.rst | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 7af637a557c02d..bd1de0efcce7a7 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -113,6 +113,37 @@ Device Drivers and Devicetree * ``emul_bbram_backend_api`` to :c:struct:`emul_bbram_driver_api` * ``usbc_ppc_drv`` to :c:struct:`usbc_ppc_driver_api` +* The driver for :dtcompatible:`maxim,max31790` got split up into a MFD and an + actual PWM driver. Previously, an instance of this device could have been + defined like this: + + .. code-block:: devicetree + + max31790_max31790: max31790@20 { + compatible = "maxim,max31790"; + status = "okay"; + reg = <0x20>; + pwm-controller; + #pwm-cells = <2>; + }; + + This can be converted to: + + .. code-block:: devicetree + + max31790_max31790: max31790@20 { + compatible = "maxim,max31790"; + status = "okay"; + reg = <0x20>; + + max31790_max31790_pwm: max31790_max31790_pwm { + compatible = "maxim,max31790-pwm"; + status = "okay"; + pwm-controller; + #pwm-cells = <2>; + }; + }; + Analog-to-Digital Converter (ADC) ================================= From 27f1e626f2b25a9e2f858d588a6573d6124b9b18 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0240/1389] drivers: dai: ssp: fix MN_MDIVCTRL_M_DIV_ENABLE for ACE+ platform In previous generations, each MCLK divider could be enabled separately. Starting with ACE, there is a single-bit MDE field to enable a single divider. The existing code would not enable MDE in case MCLK1 is used. Signed-off-by: Pierre-Louis Bossart --- drivers/dai/intel/ssp/ssp.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/dai/intel/ssp/ssp.h b/drivers/dai/intel/ssp/ssp.h index 4f12ceece91dbf..8c3e248a0d9b7a 100644 --- a/drivers/dai/intel/ssp/ssp.h +++ b/drivers/dai/intel/ssp/ssp.h @@ -244,14 +244,23 @@ /** \brief Offset of MCLK Divider x Ratio Register. */ #define MN_MDIVR(x) (0x180 + (x) * 0x4) + +/** \brief Enables the output of MCLK Divider. + * On ACE+ there is a single divider for all MCLKs + */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(0) + #else #define MN_MDIVCTRL 0x0 #define MN_MDIVR(x) (0x80 + (x) * 0x4) -#endif -/** \brief Enables the output of MCLK Divider. */ +/** \brief Enables the output of MCLK Divider. + * Each MCLK divider can be enabled separately. + */ #define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) +#endif + /** \brief Bits for setting MCLK source clock. */ #define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) From 20a04a9427eb1a820575eb43ed9d0aeacefb23d7 Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0241/1389] scripts: twister: RegEx speedup Replace unoptimal RegEx with a faster solution. Signed-off-by: Lukasz Mrugala --- scripts/pylib/twister/twisterlib/testplan.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index e8d1c384e3bbf4..bf76b95bc30fe1 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -16,6 +16,7 @@ import copy import shutil import random + import snippets from pathlib import Path from argparse import Namespace @@ -396,7 +397,6 @@ def info(what): sys.stdout.write(what + "\n") sys.stdout.flush() - def add_configurations(self): board_dirs = set() # Create a list of board roots as defined by the build system in general @@ -448,7 +448,7 @@ def add_configurations(self): # cmake/modules/extensions.cmake. revision_patterns = ["[A-Z]", "[0-9]+", - "(0|[1-9][0-9]*)(_[0-9]+)*(_[0-9]+)*"] + "(0|[1-9][0-9]*)(_[0-9]+){0,2}"] for pattern in revision_patterns: result = re.match(f"{platform.name}_(?P{pattern})\\.conf", item) From e99c5f878d28e17918d21bf3333dc6e10a19bef3 Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0242/1389] scripts: twister: Name prefix loading Sped up Twister via name prefix loading. If the only thing influencing the platform selection is the platform filter (-p), then we only load *.yaml files that start the same way as those selected platforms. We split the platform name to the first '/' or '@'. Signed-off-by: Lukasz Mrugala --- scripts/pylib/twister/twisterlib/testplan.py | 18 ++++++++++++++++-- .../{dummy.yaml => dummy_board.yaml} | 0 2 files changed, 16 insertions(+), 2 deletions(-) rename scripts/tests/twister_blackbox/test_data/boards/others/dummy_board/{dummy.yaml => dummy_board.yaml} (100%) diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index bf76b95bc30fe1..8b63ba26a684ca 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -417,6 +417,18 @@ def add_configurations(self): platform_config = self.test_config.get('platforms', {}) for folder in board_dirs: for file in glob.glob(os.path.join(folder, "*.yaml")): + # If the user set a platform filter, we can, if no other option would increase + # the allowed platform pool, save on time by not loading YAMLs of any boards + # that do not start with the required names. + if self.options.platform and \ + not self.options.all and \ + not self.options.integration and \ + not any([ + os.path.basename(file).startswith( + re.split('[/@]', p)[0] + ) for p in self.options.platform + ]): + continue try: platform = Platform() platform.load(file) @@ -702,15 +714,17 @@ def apply_filters(self, **kwargs): if ts.build_on_all and not platform_filter and platform_config.get('increased_platform_scope', True): platform_scope = self.platforms elif ts.integration_platforms: - self.verify_platforms_existence( - ts.integration_platforms, f"{ts_name} - integration_platforms") integration_platforms = list(filter(lambda item: item.name in ts.integration_platforms, self.platforms)) if self.options.integration: + self.verify_platforms_existence( + ts.integration_platforms, f"{ts_name} - integration_platforms") platform_scope = integration_platforms else: # if not in integration mode, still add integration platforms to the list if not platform_filter: + self.verify_platforms_existence( + ts.integration_platforms, f"{ts_name} - integration_platforms") platform_scope = platforms + integration_platforms else: platform_scope = platforms diff --git a/scripts/tests/twister_blackbox/test_data/boards/others/dummy_board/dummy.yaml b/scripts/tests/twister_blackbox/test_data/boards/others/dummy_board/dummy_board.yaml similarity index 100% rename from scripts/tests/twister_blackbox/test_data/boards/others/dummy_board/dummy.yaml rename to scripts/tests/twister_blackbox/test_data/boards/others/dummy_board/dummy_board.yaml From 75ded56decd2b90159a2508c120cd714830025cb Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0243/1389] scripts: twister: New find_v2_boards() function Current find_v2_boards() has a lot of unnecessarry fluff. We can make a new version of that function without it given its use in TestPlan.add_configurations(). Signed-off-by: Lukasz Mrugala --- scripts/list_boards.py | 11 +++++++++++ scripts/pylib/twister/twisterlib/testplan.py | 5 ++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/list_boards.py b/scripts/list_boards.py index 597ecf91809b72..b768dd69b00ced 100755 --- a/scripts/list_boards.py +++ b/scripts/list_boards.py @@ -231,6 +231,17 @@ def load_v2_boards(board_name, board_yml, systems): return boards +# Note that this does not share the args.board functionality of find_v2_boards +def find_v2_board_dirs(args): + dirs = [] + board_files = [] + for root in unique_paths(args.board_roots): + board_files.extend((root / 'boards').rglob(BOARD_YML)) + + dirs = [board_yml.parent for board_yml in board_files if board_yml.is_file()] + return dirs + + def find_v2_boards(args): root_args = argparse.Namespace(**{'soc_roots': args.soc_roots}) systems = list_hardware.find_v2_systems(root_args) diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 8b63ba26a684ca..442f2f4e131139 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -407,11 +407,10 @@ def add_configurations(self): Path(ZEPHYR_BASE) / 'subsys' / 'testsuite'], board_roots=board_roots, board=None, board_dir=None) v1_boards = list_boards.find_boards(lb_args) - v2_boards = list_boards.find_v2_boards(lb_args) + v2_dirs = list_boards.find_v2_board_dirs(lb_args) for b in v1_boards: board_dirs.add(b.dir) - for b in v2_boards: - board_dirs.add(b.dir) + board_dirs.update(v2_dirs) logger.debug("Reading platform configuration files under %s..." % self.env.board_roots) platform_config = self.test_config.get('platforms', {}) From ad80643ddd731e89480be176d9e8746220b4d347 Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0244/1389] scripts: Loader change CSafeLoader used instead of yaml.safe_load and SafeLoader. C implementation is faster. Signed-off-by: Lukasz Mrugala --- scripts/list_boards.py | 9 +++++++-- scripts/list_hardware.py | 13 +++++++++---- scripts/pylib/twister/twisterlib/quarantine.py | 9 +++++++-- scripts/pylib/twister/twisterlib/runner.py | 9 +++++++-- scripts/pylib/twister/twisterlib/testplan.py | 1 - scripts/tests/twister/test_runner.py | 2 +- scripts/zephyr_module.py | 9 +++++++-- 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/scripts/list_boards.py b/scripts/list_boards.py index b768dd69b00ced..6b810d0e286e7e 100755 --- a/scripts/list_boards.py +++ b/scripts/list_boards.py @@ -15,9 +15,14 @@ import list_hardware from list_hardware import unique_paths +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + BOARD_SCHEMA_PATH = str(Path(__file__).parent / 'schemas' / 'board-schema.yml') with open(BOARD_SCHEMA_PATH, 'r') as f: - board_schema = yaml.safe_load(f.read()) + board_schema = yaml.load(f.read(), Loader=SafeLoader) BOARD_YML = 'board.yml' @@ -178,7 +183,7 @@ def load_v2_boards(board_name, board_yml, systems): boards = [] if board_yml.is_file(): with board_yml.open('r') as f: - b = yaml.safe_load(f.read()) + b = yaml.load(f.read(), Loader=SafeLoader) try: pykwalify.core.Core(source_data=b, schema_data=board_schema).validate() diff --git a/scripts/list_hardware.py b/scripts/list_hardware.py index d1f31a4712e1df..cdb0e059cc97cb 100755 --- a/scripts/list_hardware.py +++ b/scripts/list_hardware.py @@ -12,14 +12,19 @@ import yaml import re +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + SOC_SCHEMA_PATH = str(Path(__file__).parent / 'schemas' / 'soc-schema.yml') with open(SOC_SCHEMA_PATH, 'r') as f: - soc_schema = yaml.safe_load(f.read()) + soc_schema = yaml.load(f.read(), Loader=SafeLoader) ARCH_SCHEMA_PATH = str(Path(__file__).parent / 'schemas' / 'arch-schema.yml') with open(ARCH_SCHEMA_PATH, 'r') as f: - arch_schema = yaml.safe_load(f.read()) + arch_schema = yaml.load(f.read(), Loader=SafeLoader) SOC_YML = 'soc.yml' ARCHS_YML_PATH = PurePath('arch/archs.yml') @@ -35,7 +40,7 @@ def __init__(self, folder='', soc_yaml=None): return try: - data = yaml.safe_load(soc_yaml) + data = yaml.load(soc_yaml, Loader=SafeLoader) pykwalify.core.Core(source_data=data, schema_data=soc_schema).validate() except (yaml.YAMLError, pykwalify.errors.SchemaError) as e: @@ -188,7 +193,7 @@ def find_v2_archs(args): if Path(archs_yml).is_file(): with Path(archs_yml).open('r') as f: - archs = yaml.safe_load(f.read()) + archs = yaml.load(f.read(), Loader=SafeLoader) try: pykwalify.core.Core(source_data=archs, schema_data=arch_schema).validate() diff --git a/scripts/pylib/twister/twisterlib/quarantine.py b/scripts/pylib/twister/twisterlib/quarantine.py index e4baa52781e2a9..cc6ae43002219f 100644 --- a/scripts/pylib/twister/twisterlib/quarantine.py +++ b/scripts/pylib/twister/twisterlib/quarantine.py @@ -5,11 +5,16 @@ import logging import re +import yaml from pathlib import Path -from yaml import safe_load from dataclasses import dataclass, field +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + logger = logging.getLogger(__name__) @@ -88,7 +93,7 @@ def __post_init__(self): def load_data_from_yaml(cls, filename: str | Path) -> QuarantineData: """Load quarantine from yaml file.""" with open(filename, 'r', encoding='UTF-8') as yaml_fd: - qlist_raw_data: list[dict] = safe_load(yaml_fd) + qlist_raw_data: list[dict] = yaml.load(yaml_fd, Loader=SafeLoader) try: if not qlist_raw_data: # in case of loading empty quarantine file diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index cb22d12af97aa1..3073a7c4ca6fb9 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -46,6 +46,11 @@ from twisterlib.testplan import change_skip_to_error_if_integration from twisterlib.harness import HarnessImporter, Pytest +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + logger = logging.getLogger('twister') logger.setLevel(logging.DEBUG) import expr_parser @@ -861,7 +866,7 @@ def _get_binaries_from_runners(self, domain='') -> List[str]: return [] with open(runners_file_path, 'r') as file: - runners_content: dict = yaml.safe_load(file) + runners_content: dict = yaml.load(file, Loader=SafeLoader) if 'config' not in runners_content: return [] @@ -901,7 +906,7 @@ def _sanitize_runners_file(self): with open(runners_file_path, 'rt') as file: runners_content_text = file.read() - runners_content_yaml: dict = yaml.safe_load(runners_content_text) + runners_content_yaml: dict = yaml.load(runners_content_text, Loader=SafeLoader) if 'config' not in runners_content_yaml: return diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 442f2f4e131139..85335491af6939 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -16,7 +16,6 @@ import copy import shutil import random - import snippets from pathlib import Path from argparse import Namespace diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 18960d0ed3c045..e2a51fc2a09d1a 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -1805,7 +1805,7 @@ def mock_exists(fname): with mock.patch('os.path.exists', mock_exists), \ mock.patch('builtins.open', mock.mock_open()), \ - mock.patch('yaml.safe_load', return_value=runners_content): + mock.patch('yaml.load', return_value=runners_content): if domain: bins = pb._get_binaries_from_runners(domain) else: diff --git a/scripts/zephyr_module.py b/scripts/zephyr_module.py index b5b257ed712ca2..2bb72e810f47e3 100755 --- a/scripts/zephyr_module.py +++ b/scripts/zephyr_module.py @@ -28,6 +28,11 @@ from pathlib import Path, PurePath from collections import namedtuple +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + METADATA_SCHEMA = ''' ## A pykwalify schema for basic validation of the structure of a ## metadata YAML file. @@ -156,7 +161,7 @@ BLOB_NOT_PRESENT = 'D' BLOB_OUTDATED = 'M' -schema = yaml.safe_load(METADATA_SCHEMA) +schema = yaml.load(METADATA_SCHEMA, Loader=SafeLoader) def validate_setting(setting, module_path, filename=None): @@ -180,7 +185,7 @@ def process_module(module): module_path / MODULE_YML_PATH.with_suffix('.yaml')]: if Path(module_yml).is_file(): with Path(module_yml).open('r') as f: - meta = yaml.safe_load(f.read()) + meta = yaml.load(f.read(), Loader=SafeLoader) try: pykwalify.core.Core(source_data=meta, schema_data=schema)\ From a76e4feb08b36c726abe5ff3e7733733ed050025 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0245/1389] drivers: mdio: add stm32 mdio support MDIO is part of the ETH IP, but some phy chip may need a specific phy driver to set up certain vendor registers enabling particular features. Add support for stm32 mdio access. Signed-off-by: Angelo Dureghello --- drivers/mdio/CMakeLists.txt | 1 + drivers/mdio/Kconfig | 1 + drivers/mdio/Kconfig.stm32_hal | 11 +++ drivers/mdio/mdio_stm32_hal.c | 123 +++++++++++++++++++++++++++ dts/bindings/mdio/st,stm32-mdio.yaml | 24 ++++++ 5 files changed, 160 insertions(+) create mode 100644 drivers/mdio/Kconfig.stm32_hal create mode 100644 drivers/mdio/mdio_stm32_hal.c create mode 100644 dts/bindings/mdio/st,stm32-mdio.yaml diff --git a/drivers/mdio/CMakeLists.txt b/drivers/mdio/CMakeLists.txt index ad63d34f4ad526..63e43e5936bd86 100644 --- a/drivers/mdio/CMakeLists.txt +++ b/drivers/mdio/CMakeLists.txt @@ -10,5 +10,6 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_S32_GMAC mdio_nxp_s32_gmac.c) zephyr_library_sources_ifdef(CONFIG_MDIO_ADIN2111 mdio_adin2111.c) zephyr_library_sources_ifdef(CONFIG_MDIO_GPIO mdio_gpio.c) zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET mdio_nxp_enet.c) +zephyr_library_sources_ifdef(CONFIG_MDIO_ST_STM32_HAL mdio_stm32_hal.c) zephyr_library_sources_ifdef(CONFIG_MDIO_INFINEON_XMC4XXX mdio_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET_QOS mdio_nxp_enet_qos.c) diff --git a/drivers/mdio/Kconfig b/drivers/mdio/Kconfig index 4af6827e8b7fd0..dbd1ae9a038c6a 100644 --- a/drivers/mdio/Kconfig +++ b/drivers/mdio/Kconfig @@ -31,6 +31,7 @@ source "drivers/mdio/Kconfig.nxp_s32_gmac" source "drivers/mdio/Kconfig.adin2111" source "drivers/mdio/Kconfig.gpio" source "drivers/mdio/Kconfig.nxp_enet" +source "drivers/mdio/Kconfig.stm32_hal" source "drivers/mdio/Kconfig.xmc4xxx" source "drivers/mdio/Kconfig.nxp_enet_qos" diff --git a/drivers/mdio/Kconfig.stm32_hal b/drivers/mdio/Kconfig.stm32_hal new file mode 100644 index 00000000000000..28268ab1486d4a --- /dev/null +++ b/drivers/mdio/Kconfig.stm32_hal @@ -0,0 +1,11 @@ +# Copyright (c) 2024 BayLibre, SAS +# Copyright (c) 2024 Analog Devices Inc. +# SPDX-License-Identifier: Apache-2.0 + +config MDIO_ST_STM32_HAL + bool "STM32 MDIO controller driver" + default y + depends on ETH_STM32_HAL_API_V2 + depends on DT_HAS_ST_STM32_MDIO_ENABLED + help + Enable STM32 MDIO support. diff --git a/drivers/mdio/mdio_stm32_hal.c b/drivers/mdio/mdio_stm32_hal.c new file mode 100644 index 00000000000000..3e788027fae0e0 --- /dev/null +++ b/drivers/mdio/mdio_stm32_hal.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024 BayLibre, SAS + * Copyright (c) 2024 Analog Devices Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(mdio_stm32_hal, CONFIG_MDIO_LOG_LEVEL); + +#define DT_DRV_COMPAT st_stm32_mdio + +#define ADIN1100_REG_VALUE_MASK GENMASK(15, 0) + +struct mdio_stm32_data { + struct k_sem sem; + ETH_HandleTypeDef heth; +}; + +struct mdio_stm32_config { + const struct pinctrl_dev_config *pincfg; +}; + +static int mdio_stm32_read(const struct device *dev, uint8_t prtad, + uint8_t regad, uint16_t *data) +{ + struct mdio_stm32_data *const dev_data = dev->data; + ETH_HandleTypeDef *heth = &dev_data->heth; + uint32_t read; + int ret; + + k_sem_take(&dev_data->sem, K_FOREVER); + + ret = HAL_ETH_ReadPHYRegister(heth, prtad, regad, &read); + + k_sem_give(&dev_data->sem); + + if (ret != HAL_OK) { + return -EIO; + } + + *data = read & ADIN1100_REG_VALUE_MASK; + + return ret; +} + +static int mdio_stm32_write(const struct device *dev, uint8_t prtad, + uint8_t regad, uint16_t data) +{ + struct mdio_stm32_data *const dev_data = dev->data; + ETH_HandleTypeDef *heth = &dev_data->heth; + int ret; + + k_sem_take(&dev_data->sem, K_FOREVER); + + ret = HAL_ETH_WritePHYRegister(heth, prtad, regad, data); + + k_sem_give(&dev_data->sem); + + if (ret != HAL_OK) { + return -EIO; + } + + return ret; +} + +static void mdio_stm32_bus_enable(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static void mdio_stm32_bus_disable(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static int mdio_stm32_init(const struct device *dev) +{ + struct mdio_stm32_data *const dev_data = dev->data; + const struct mdio_stm32_config *const config = dev->config; + int ret; + + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + k_sem_init(&dev_data->sem, 1, 1); + + return 0; +} + +static const struct mdio_driver_api mdio_stm32_api = { + .read = mdio_stm32_read, + .write = mdio_stm32_write, + .bus_enable = mdio_stm32_bus_enable, + .bus_disable = mdio_stm32_bus_disable, +}; + +#define MDIO_STM32_HAL_DEVICE(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + \ + static struct mdio_stm32_data mdio_stm32_data_##inst = { \ + .heth = {.Instance = (ETH_TypeDef *)DT_REG_ADDR(DT_INST_PARENT(inst))}, \ + }; \ + static struct mdio_stm32_config mdio_stm32_config_##inst = { \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &mdio_stm32_init, NULL, \ + &mdio_stm32_data_##inst, &mdio_stm32_config_##inst, \ + POST_KERNEL, CONFIG_ETH_INIT_PRIORITY, \ + &mdio_stm32_api); + +DT_INST_FOREACH_STATUS_OKAY(MDIO_STM32_HAL_DEVICE) diff --git a/dts/bindings/mdio/st,stm32-mdio.yaml b/dts/bindings/mdio/st,stm32-mdio.yaml new file mode 100644 index 00000000000000..e536ed1c23a7bd --- /dev/null +++ b/dts/bindings/mdio/st,stm32-mdio.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2024 BayLibre, SAS +# Copyright (c) 2024 Analog Devices Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: ST MDIO Features + +compatible: "st,stm32-mdio" + +include: [mdio-controller.yaml, pinctrl-device.yaml] + +properties: + "#address-cells": + required: true + const: 1 + + "#size-cells": + required: true + const: 0 + + pinctrl-0: + required: true + + pinctrl-names: + required: true From 66ea27683dbad3295d3dc6cd4b0866e8aaecfb7c Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0246/1389] dts: arm: st: add mdio node for h5 and h7 Add mdio node for h5 and h7 series. Since MDIO registers are part of the same ETH hw IP, keeping mdio node just as a child of mac/eth, cannot see as appropriate to assign an adddress to it. Signed-off-by: Angelo Dureghello --- dts/arm/st/h5/stm32h5.dtsi | 7 +++++++ dts/arm/st/h7/stm32h7.dtsi | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index e154aa8d9dea5b..cd19d329e60f4c 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -495,6 +495,13 @@ <&rcc STM32_CLOCK_BUS_AHB1 0x00100000>, <&rcc STM32_CLOCK_BUS_AHB1 0x00200000>; status = "disabled"; + + mdio: mdio { + compatible = "st,stm32-mdio"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; gpdma1: dma@40020000 { diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index d03b8fc5ab41dd..f3a24e2718fc80 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -1015,6 +1015,13 @@ <&rcc STM32_CLOCK_BUS_AHB1 0x00010000>, <&rcc STM32_CLOCK_BUS_AHB1 0x00020000>; status = "disabled"; + + mdio: mdio { + compatible = "st,stm32-mdio"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; fmc: memory-controller@52004000 { From 08dc984ae8ffb580686b85810817a9e3d44d1655 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0247/1389] boards: st: add mdio and phy nodes Add mdio and phy nodes for h5/h7 families. Signed-off-by: Angelo Dureghello --- boards/st/nucleo_h563zi/nucleo_h563zi.dts | 16 +++++++++++++--- boards/st/nucleo_h723zg/nucleo_h723zg.dts | 14 ++++++++++++-- boards/st/nucleo_h743zi/nucleo_h743zi.dts | 16 +++++++++++++--- .../nucleo_h745zi_q_stm32h745xx_m7.dts | 14 ++++++++++++-- boards/st/nucleo_h753zi/nucleo_h753zi.dts | 16 +++++++++++++--- boards/st/stm32h573i_dk/stm32h573i_dk.dts | 16 +++++++++++++--- boards/st/stm32h735g_disco/stm32h735g_disco.dts | 16 +++++++++++++--- 7 files changed, 89 insertions(+), 19 deletions(-) diff --git a/boards/st/nucleo_h563zi/nucleo_h563zi.dts b/boards/st/nucleo_h563zi/nucleo_h563zi.dts index 347a9fa954899c..915a0ddee60469 100644 --- a/boards/st/nucleo_h563zi/nucleo_h563zi.dts +++ b/boards/st/nucleo_h563zi/nucleo_h563zi.dts @@ -40,14 +40,24 @@ &mac { status = "okay"; - pinctrl-0 = <ð_mdc_pc1 - ð_rxd0_pc4 + pinctrl-0 = <ð_rxd0_pc4 ð_rxd1_pc5 ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 ð_tx_en_pg11 ð_txd0_pg13 ð_txd1_pb15>; pinctrl-names = "default"; }; + +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; diff --git a/boards/st/nucleo_h723zg/nucleo_h723zg.dts b/boards/st/nucleo_h723zg/nucleo_h723zg.dts index cb3064b6ef2c27..8fdd4be9442275 100644 --- a/boards/st/nucleo_h723zg/nucleo_h723zg.dts +++ b/boards/st/nucleo_h723zg/nucleo_h723zg.dts @@ -160,9 +160,7 @@ &mac { status = "okay"; pinctrl-0 = <ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 - ð_mdc_pc1 ð_rxd0_pc4 ð_rxd1_pc5 ð_tx_en_pg11 @@ -171,6 +169,18 @@ pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + phy: ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0>; + status = "okay"; + }; +}; + zephyr_udc0: &usbotg_hs { pinctrl-0 = <&usb_otg_hs_dm_pa11 &usb_otg_hs_dp_pa12>; pinctrl-names = "default"; diff --git a/boards/st/nucleo_h743zi/nucleo_h743zi.dts b/boards/st/nucleo_h743zi/nucleo_h743zi.dts index ad88d87f0599f3..fd1a5a8b29ff8d 100644 --- a/boards/st/nucleo_h743zi/nucleo_h743zi.dts +++ b/boards/st/nucleo_h743zi/nucleo_h743zi.dts @@ -187,11 +187,9 @@ zephyr_udc0: &usbotg_fs { */ &mac { status = "okay"; - pinctrl-0 = <ð_mdc_pc1 - ð_rxd0_pc4 + pinctrl-0 = <ð_rxd0_pc4 ð_rxd1_pc5 ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 ð_tx_en_pg11 ð_txd0_pg13 @@ -199,6 +197,18 @@ zephyr_udc0: &usbotg_fs { pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &spi1 { status = "okay"; pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pb5>; diff --git a/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.dts b/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.dts index cf22a60ad2abd7..d3ed100f74a0a8 100644 --- a/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.dts +++ b/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.dts @@ -107,9 +107,7 @@ &mac { status = "okay"; pinctrl-0 = <ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 - ð_mdc_pc1 ð_rxd0_pc4 ð_rxd1_pc5 ð_tx_en_pg11 @@ -118,6 +116,18 @@ pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &rng { status = "okay"; }; diff --git a/boards/st/nucleo_h753zi/nucleo_h753zi.dts b/boards/st/nucleo_h753zi/nucleo_h753zi.dts index 701cf4276f3041..d8cc922acada28 100644 --- a/boards/st/nucleo_h753zi/nucleo_h753zi.dts +++ b/boards/st/nucleo_h753zi/nucleo_h753zi.dts @@ -164,11 +164,9 @@ zephyr_udc0: &usbotg_fs { */ &mac { status = "okay"; - pinctrl-0 = <ð_mdc_pc1 - ð_rxd0_pc4 + pinctrl-0 = <ð_rxd0_pc4 ð_rxd1_pc5 ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 ð_tx_en_pg11 ð_txd0_pg13 @@ -176,6 +174,18 @@ zephyr_udc0: &usbotg_fs { pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &spi1 { status = "okay"; pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pb5>; diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.dts b/boards/st/stm32h573i_dk/stm32h573i_dk.dts index ba73cc49916700..e27445c2ac3bf7 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.dts +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.dts @@ -149,11 +149,9 @@ &mac { status = "okay"; - pinctrl-0 = <ð_mdc_pc1 - ð_rxd0_pc4 + pinctrl-0 = <ð_rxd0_pc4 ð_rxd1_pc5 ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 ð_tx_en_pg11 ð_txd0_pg13 @@ -161,6 +159,18 @@ pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/st/stm32h735g_disco/stm32h735g_disco.dts b/boards/st/stm32h735g_disco/stm32h735g_disco.dts index cc504a4a6c3b70..4843e98a709d2f 100644 --- a/boards/st/stm32h735g_disco/stm32h735g_disco.dts +++ b/boards/st/stm32h735g_disco/stm32h735g_disco.dts @@ -130,11 +130,9 @@ }; &mac { - pinctrl-0 = <ð_mdc_pc1 - ð_rxd0_pc4 + pinctrl-0 = <ð_rxd0_pc4 ð_rxd1_pc5 ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 ð_tx_en_pb11 ð_txd0_pb12 @@ -143,6 +141,18 @@ status = "okay"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &sdmmc1 { pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 From cdd7bb55263581debb98de3fbcd9560787b3147f Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0248/1389] soc: st: set soc-level phy priority Introducing MDIO and PHY support for stm32, phy driver gets error (-116) if it tries to read phy chip id, since MDIO IP is part of ETH IP, and eth hw module is still not initialized. Forcing a priority that allows possibly connected PHY chip to be detected properly at initial boot. Signed-off-by: Angelo Dureghello --- soc/st/stm32/Kconfig.defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soc/st/stm32/Kconfig.defconfig b/soc/st/stm32/Kconfig.defconfig index d90ce9b7da865b..64f6b817dd026a 100644 --- a/soc/st/stm32/Kconfig.defconfig +++ b/soc/st/stm32/Kconfig.defconfig @@ -57,6 +57,10 @@ config CLOCK_CONTROL_INIT_PRIORITY default 1 depends on CLOCK_CONTROL +config PHY_INIT_PRIORITY + default 81 + depends on NET_L2_ETHERNET && ETH_DRIVER + config MEMC_STM32 default y depends on MEMC From 8123c881c27561f05b6e97d1ea1bed6f3f82150d Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0249/1389] drivers: eth: eth_stm32: use phy api support for h5/h7 Use PHY apis to access the PHY, to avoid any kind of collisions with other tasks using the PHY apis. Signed-off-by: Angelo Dureghello --- drivers/ethernet/Kconfig.stm32_hal | 1 + drivers/ethernet/eth_stm32_hal.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index fb64adbb5acb88..4a11796dc88153 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -12,6 +12,7 @@ menuconfig ETH_STM32_HAL select NOCACHE_MEMORY if SOC_SERIES_STM32H7X && CPU_CORTEX_M7 select HWINFO select ETH_DSA_SUPPORT + select MDIO if SOC_SERIES_STM32H5X || SOC_SERIES_STM32H7X imply CRC help Enable STM32 HAL based Ethernet driver. It is available for diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index 10391a5458e7d6..0da1411c3112a8 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -23,6 +23,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include +#include #include #include #include @@ -57,6 +58,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) +#define DEVICE_PHY_BY_NAME(n) \ + DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(n, mdio), ethernet_phy_0)) + +static const struct device *eth_stm32_phy_dev = DEVICE_PHY_BY_NAME(0); + #define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ #define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ @@ -211,8 +217,9 @@ static HAL_StatusTypeDef read_eth_phy_register(ETH_HandleTypeDef *heth, uint32_t PHYReg, uint32_t *RegVal) { -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ - defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_MDIO) + return phy_read(eth_stm32_phy_dev, PHYReg, RegVal); +#elif defined(CONFIG_ETH_STM32_HAL_API_V2) return HAL_ETH_ReadPHYRegister(heth, PHYAddr, PHYReg, RegVal); #else ARG_UNUSED(PHYAddr); @@ -1225,7 +1232,6 @@ static int eth_initialize(const struct device *dev) setup_mac_filter(heth); - LOG_DBG("MAC %02x:%02x:%02x:%02x:%02x:%02x", dev_data->mac_addr[0], dev_data->mac_addr[1], dev_data->mac_addr[2], dev_data->mac_addr[3], From a8eb4db2315a81257a7aae58cd4d21e69844060e Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0250/1389] drivers: eth: phy: adin2111: add support for adin1100 phy Add support for similar adin1100 phy, boath are 10Base-T1L, only difference is that adin1100 connects through r/mii. Signed-off-by: Angelo Dureghello --- drivers/ethernet/phy/Kconfig | 4 +- drivers/ethernet/phy/phy_adin2111.c | 192 ++++++++++++++++++-- dts/bindings/ethernet/adi,adin1100-phy.yaml | 9 + 3 files changed, 189 insertions(+), 16 deletions(-) create mode 100644 dts/bindings/ethernet/adi,adin1100-phy.yaml diff --git a/drivers/ethernet/phy/Kconfig b/drivers/ethernet/phy/Kconfig index 264469749957d5..8ff32b8fee2a7b 100644 --- a/drivers/ethernet/phy/Kconfig +++ b/drivers/ethernet/phy/Kconfig @@ -36,9 +36,7 @@ config PHY_GENERIC_MII config PHY_ADIN2111 bool "ADIN2111 PHY driver" default y - depends on DT_HAS_ADI_ADIN2111_PHY_ENABLED - depends on ETH_ADIN2111 - depends on MDIO_ADIN2111 + depends on DT_HAS_ADI_ADIN2111_PHY_ENABLED || DT_HAS_ADI_ADIN1100_PHY_ENABLED help Enable ADIN2111 PHY driver. diff --git a/drivers/ethernet/phy/phy_adin2111.c b/drivers/ethernet/phy/phy_adin2111.c index eb90eddd01361d..380def0ebe74c2 100644 --- a/drivers/ethernet/phy/phy_adin2111.c +++ b/drivers/ethernet/phy/phy_adin2111.c @@ -6,9 +6,14 @@ */ #include -LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL); +#if DT_NODE_HAS_STATUS(DT_INST(0, adi_adin2111_phy), okay) #define DT_DRV_COMPAT adi_adin2111_phy +#else +#define DT_DRV_COMPAT adi_adin1100_phy +#endif + +LOG_MODULE_REGISTER(DT_DRV_COMPAT, CONFIG_PHY_LOG_LEVEL); #include #include @@ -23,20 +28,28 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL); /* PHYs out of reset check retry delay */ #define ADIN2111_PHY_AWAIT_DELAY_POLL_US 15U -/* Number of retries for PHYs out of reset check */ -#define ADIN2111_PHY_AWAIT_RETRY_COUNT 200U +/* + * Number of retries for PHYs out of reset check, + * rmii variants as ADIN11XX need 70ms maximum after hw reset to be up, + * so the increasing the count for that, as default 25ms (sw reset) + 45. + */ +#define ADIN2111_PHY_AWAIT_RETRY_COUNT 3000U /* PHY's software powerdown check retry delay */ #define ADIN2111_PHY_SFT_PD_DELAY_POLL_US 15U /* Number of retries for PHY's software powerdown check */ #define ADIN2111_PHY_SFT_PD_RETRY_COUNT 200U +/* Software reset, CLK_25 disabled time*/ +#define ADIN1100_PHY_SFT_RESET_MS 25U + /* PHYs autonegotiation complete timeout */ #define ADIN2111_AN_COMPLETE_AWAIT_TIMEOUT_MS 3000U /* ADIN2111 PHY identifier */ #define ADIN2111_PHY_ID 0x0283BCA1U #define ADIN1110_PHY_ID 0x0283BC91U +#define ADIN1100_PHY_ID 0x0283BC81U /* System Interrupt Mask Register */ #define ADIN2111_PHY_CRSM_IRQ_MASK 0x0020U @@ -77,17 +90,26 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL); /* LED 0 Enable */ #define ADIN2111_PHY_LED_CNTRL_LED0_EN BIT(7) +/* MMD bridge regs */ +#define ADIN1100_MMD_ACCESS_CNTRL 0x0DU +#define ADIN1100_MMD_ACCESS 0x0EU + struct phy_adin2111_config { const struct device *mdio; uint8_t phy_addr; bool led0_en; bool led1_en; bool tx_24v; + bool mii; }; struct phy_adin2111_data { + const struct device *dev; struct phy_link_state state; struct k_sem sem; + struct k_work_delayable monitor_work; + phy_callback_t cb; + void *cb_data; }; static inline int phy_adin2111_c22_read(const struct device *dev, uint16_t reg, @@ -106,22 +128,62 @@ static inline int phy_adin2111_c22_write(const struct device *dev, uint16_t reg, return mdio_write(cfg->mdio, cfg->phy_addr, reg, val); } -static inline int phy_adin2111_c45_write(const struct device *dev, uint16_t devad, - uint16_t reg, uint16_t val) +static int phy_adin2111_c45_setup_dev_reg(const struct device *dev, uint16_t devad, + uint16_t reg) { const struct phy_adin2111_config *cfg = dev->config; + int rval; - return mdio_write_c45(cfg->mdio, cfg->phy_addr, devad, reg, val); + rval = mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS_CNTRL, devad); + if (rval < 0) { + return rval; + } + rval = mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS, reg); + if (rval < 0) { + return rval; + } + + return mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS_CNTRL, devad | BIT(14)); } -static inline int phy_adin2111_c45_read(const struct device *dev, uint16_t devad, - uint16_t reg, uint16_t *val) +static int phy_adin2111_c45_read(const struct device *dev, uint16_t devad, + uint16_t reg, uint16_t *val) { const struct phy_adin2111_config *cfg = dev->config; + int rval; + + if (cfg->mii) { + /* Using C22 -> devad bridge */ + rval = phy_adin2111_c45_setup_dev_reg(dev, devad, reg); + if (rval < 0) { + return rval; + } + + return mdio_read(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS, val); + } return mdio_read_c45(cfg->mdio, cfg->phy_addr, devad, reg, val); } +static int phy_adin2111_c45_write(const struct device *dev, uint16_t devad, + uint16_t reg, uint16_t val) +{ + const struct phy_adin2111_config *cfg = dev->config; + int rval; + + if (cfg->mii) { + /* Using C22 -> devad bridge */ + rval = phy_adin2111_c45_setup_dev_reg(dev, devad, reg); + if (rval < 0) { + return rval; + } + + return mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS, val); + } + + return mdio_write_c45(cfg->mdio, cfg->phy_addr, devad, reg, val); +} + static int phy_adin2111_reg_read(const struct device *dev, uint16_t reg_addr, uint32_t *data) { @@ -304,6 +366,84 @@ static int phy_adin2111_cfg_link(const struct device *dev, return -ENOTSUP; } +static int phy_adin2111_reset(const struct device *dev) +{ + int ret; + + ret = phy_adin2111_c22_write(dev, MII_BMCR, MII_BMCR_RESET); + if (ret < 0) { + return ret; + } + + k_msleep(ADIN1100_PHY_SFT_RESET_MS); + + return 0; +} + +static void invoke_link_cb(const struct device *dev) +{ + struct phy_adin2111_data *const data = dev->data; + struct phy_link_state state; + + if (data->cb == NULL) { + return; + } + + data->cb(dev, &state, data->cb_data); +} + +static int update_link_state(const struct device *dev) +{ + struct phy_adin2111_data *const data = dev->data; + const struct phy_adin2111_config *config = dev->config; + struct phy_link_state old_state; + uint16_t bmsr; + int ret; + + ret = phy_adin2111_c22_read(dev, MII_BMSR, &bmsr); + if (ret < 0) { + return ret; + } + + old_state = data->state; + data->state.is_up = !!(bmsr & MII_BMSR_LINK_STATUS); + + if (old_state.speed != data->state.speed || old_state.is_up != data->state.is_up) { + + LOG_INF("PHY (%d) Link is %s", config->phy_addr, data->state.is_up ? "up" : "down"); + + if (data->state.is_up == false) { + return 0; + } + + invoke_link_cb(dev); + + LOG_INF("PHY (%d) Link speed %s Mb, %s duplex\n", config->phy_addr, + (PHY_LINK_IS_SPEED_100M(data->state.speed) ? "100" : "10"), + PHY_LINK_IS_FULL_DUPLEX(data->state.speed) ? "full" : "half"); + } + + return 0; +} + +static void monitor_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct phy_adin2111_data *const data = + CONTAINER_OF(dwork, struct phy_adin2111_data, monitor_work); + const struct device *dev = data->dev; + int rc; + + k_sem_take(&data->sem, K_FOREVER); + + rc = update_link_state(dev); + + k_sem_give(&data->sem); + + /* Submit delayed work */ + k_work_reschedule(&data->monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); +} + static int phy_adin2111_init(const struct device *dev) { const struct phy_adin2111_config *const cfg = dev->config; @@ -313,9 +453,21 @@ static int phy_adin2111_init(const struct device *dev) bool tx_24v_supported = false; int ret; + data->dev = dev; data->state.is_up = false; data->state.speed = LINK_FULL_10BASE_T; + /* + * For adin1100 and further mii stuff, + * reset may not be performed from the mac layer, doing a clean reset here. + */ + if (cfg->mii) { + ret = phy_adin2111_reset(dev); + if (ret < 0) { + return ret; + } + } + ret = phy_adin2111_await_phy(dev); if (ret < 0) { LOG_ERR("PHY %u didn't come out of reset, %d", @@ -330,7 +482,7 @@ static int phy_adin2111_init(const struct device *dev) return -ENODEV; } - if (phy_id != ADIN2111_PHY_ID && phy_id != ADIN1110_PHY_ID) { + if (phy_id != ADIN2111_PHY_ID && phy_id != ADIN1110_PHY_ID && phy_id != ADIN1100_PHY_ID) { LOG_ERR("PHY %u unexpected PHY ID %X", cfg->phy_addr, phy_id); return -EINVAL; } @@ -447,6 +599,11 @@ static int phy_adin2111_init(const struct device *dev) return ret; } + if (cfg->mii) { + k_work_init_delayable(&data->monitor_work, monitor_work_handler); + monitor_work_handler(&data->monitor_work.work); + } + /** * done, PHY is in software powerdown (SFT PD) * exit software powerdown, PHY 1 has to exit before PHY 2 @@ -458,10 +615,17 @@ static int phy_adin2111_init(const struct device *dev) static int phy_adin2111_link_cb_set(const struct device *dev, phy_callback_t cb, void *user_data) { - ARG_UNUSED(dev); - ARG_UNUSED(cb); - ARG_UNUSED(user_data); - return -ENOTSUP; + struct phy_adin2111_data *const data = dev->data; + + data->cb = cb; + data->cb_data = user_data; + + /* Invoke the callback to notify the caller of the current + * link status. + */ + invoke_link_cb(dev); + + return 0; } static const struct ethphy_driver_api phy_adin2111_api = { @@ -479,6 +643,8 @@ static const struct ethphy_driver_api phy_adin2111_api = { .led0_en = DT_INST_PROP(n, led0_en), \ .led1_en = DT_INST_PROP(n, led1_en), \ .tx_24v = !(DT_INST_PROP(n, disable_tx_mode_24v)), \ + IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(adi_adin1100_phy), \ + (.mii = 1)) \ }; \ static struct phy_adin2111_data phy_adin2111_data_##n = { \ .sem = Z_SEM_INITIALIZER(phy_adin2111_data_##n.sem, 1, 1), \ diff --git a/dts/bindings/ethernet/adi,adin1100-phy.yaml b/dts/bindings/ethernet/adi,adin1100-phy.yaml new file mode 100644 index 00000000000000..c8613bcb90212c --- /dev/null +++ b/dts/bindings/ethernet/adi,adin1100-phy.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# Copyright (c) 2024 BayLibre, SAS +# SPDX-License-Identifier: Apache-2.0 + +description: ADIN1100 PHY + +compatible: "adi,adin1100-phy" + +include: adi,adin2111-phy.yaml From 807af85e374f50b9702c80d5ecb79a5b87912493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0251/1389] Bluetooth: Remove legacy debug symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `BT_DEBUG_*` Kconfig symbols have been deprecated for more than 2 versions, remove them. Update code that was still using them. Remove the Bluetooth specific `Kconfig.template.log_config_bt` and use `Kconfig.template.log_config_inherit` from the logging subsystem instead, now that the legacy symbols can be removed. Signed-off-by: Théo Battrel --- .../audio/shell/bap_broadcast_assistant.rst | 3 +- .../api/audio/shell/bap_scan_delegator.rst | 3 +- .../bluetooth/api/audio/shell/ccp.rst | 8 +- .../bluetooth/api/audio/shell/csip.rst | 5 +- doc/releases/release-notes-3.7.rst | 6 + drivers/bluetooth/hci/cyw43xxx.c | 1 - drivers/bluetooth/hci/hci_psoc6_bless.c | 1 - scripts/kconfig/hardened.csv | 4 +- subsys/bluetooth/Kconfig.logging | 838 ++---------------- subsys/bluetooth/audio/Kconfig.tmap | 12 +- .../common/Kconfig.template.log_config_bt | 22 - subsys/bluetooth/mesh/rpr_cli.c | 2 +- subsys/bluetooth/mesh/rpr_srv.c | 2 +- tests/bluetooth/ctrl_isoal/Kconfig | 11 +- 14 files changed, 105 insertions(+), 813 deletions(-) delete mode 100644 subsys/bluetooth/common/Kconfig.template.log_config_bt diff --git a/doc/connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant.rst b/doc/connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant.rst index 5ebd7b34327a19..2fdd25192c1126 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/bap_broadcast_assistant.rst @@ -14,7 +14,8 @@ The Broadcast Assistant will typically be phones or laptops. The Broadcast Assistant scans for periodic advertisements and transfer information to the server. -It is necessary to have :code:`BT_DEBUG_BAP_BROADCAST_ASSISTANT` enabled for +It is necessary to have +:kconfig:option:`CONFIG_BT_BAP_BROADCAST_ASSISTANT_LOG_LEVEL_DBG` enabled for using the Broadcast Assistant interactively. When the Bluetooth stack has been initialized (:code:`bt init`), diff --git a/doc/connectivity/bluetooth/api/audio/shell/bap_scan_delegator.rst b/doc/connectivity/bluetooth/api/audio/shell/bap_scan_delegator.rst index cbdbc8ecbce986..ad9348c170515c 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/bap_scan_delegator.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/bap_scan_delegator.rst @@ -11,7 +11,8 @@ synchronization transfer (PAST) protocol. The Scan Delegator server typically resides on devices that have inputs or outputs. -It is necessary to have :code:`BT_DEBUG_BAP_SCAN_DELEGATOR` enabled for using +It is necessary to have +:kconfig:option:`CONFIG_BT_BAP_SCAN_DELEGATOR_LOG_LEVEL_DBG` enabled for using the Scan Delegator interactively. The Scan Delegator can currently only set the sync state of a receive state, but diff --git a/doc/connectivity/bluetooth/api/audio/shell/ccp.rst b/doc/connectivity/bluetooth/api/audio/shell/ccp.rst index 69e20de63e82ca..023e8515aa9c79 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/ccp.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/ccp.rst @@ -15,8 +15,8 @@ laptops. The call control client will also thus typically be the advertiser. The client can control the states of calls on a server using the call control point. -It is necessary to have :code:`BT_DEBUG_TBS_CLIENT` enabled for using the client -interactively. +It is necessary to have :kconfig:option:`CONFIG_BT_TBS_CLIENT_LOG_LEVEL_DBG` +enabled for using the client interactively. Using the telephone bearer service client ========================================= @@ -160,8 +160,8 @@ The telephone bearer service is a service that typically resides on devices that can make calls, including calls from apps such as Skype, e.g. (smart)phones and PCs. -It is necessary to have :code:`BT_DEBUG_TBS` enabled for using the TBS server -interactively. +It is necessary to have :kconfig:option:`CONFIG_BT_TBS_LOG_LEVEL_DBG` enabled +for using the TBS server interactively. Using the telephone bearer service ================================== diff --git a/doc/connectivity/bluetooth/api/audio/shell/csip.rst b/doc/connectivity/bluetooth/api/audio/shell/csip.rst index c4efa0a6f93d72..307eade3999ffb 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/csip.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/csip.rst @@ -36,8 +36,9 @@ read the set information, which is needed to identify other set members. The client can then scan for and connect to the remaining set members, and once all the members has been connected to, it can lock and release the set. -It is necessary to enable :code:`BT_DEBUG_CSIP_SET_COORDINATOR` to properly use the set -coordinator. +It is necessary to enable +:kconfig:option:`CONFIG_BT_CSIP_SET_COORDINATOR_LOG_LEVEL_DBG` to properly use +the set coordinator. .. code-block:: console diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 54d96f9d3672e0..fd74dc40f8f156 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -32,6 +32,12 @@ https://docs.zephyrproject.org/latest/security/vulnerabilities.html API Changes *********** +Removed APIs in this release +============================ + + * The Bluetooth subsystem specific debug symbols are removed. They have been replaced with the + Zephyr logging ones. + Deprecated in this release ========================== diff --git a/drivers/bluetooth/hci/cyw43xxx.c b/drivers/bluetooth/hci/cyw43xxx.c index f1ee9ad81b1c03..8da6192610dbe5 100644 --- a/drivers/bluetooth/hci/cyw43xxx.c +++ b/drivers/bluetooth/hci/cyw43xxx.c @@ -19,7 +19,6 @@ #include #include -#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL #include LOG_MODULE_REGISTER(cyw43xxx_driver); diff --git a/drivers/bluetooth/hci/hci_psoc6_bless.c b/drivers/bluetooth/hci/hci_psoc6_bless.c index 9a622411454382..af6804f2f17596 100644 --- a/drivers/bluetooth/hci/hci_psoc6_bless.c +++ b/drivers/bluetooth/hci/hci_psoc6_bless.c @@ -23,7 +23,6 @@ #include #include -#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL #include LOG_MODULE_REGISTER(psoc6_bless); diff --git a/scripts/kconfig/hardened.csv b/scripts/kconfig/hardened.csv index a8caf3a87ccd04..f55899569e4f90 100644 --- a/scripts/kconfig/hardened.csv +++ b/scripts/kconfig/hardened.csv @@ -2,8 +2,8 @@ BOOT_BANNER,n BOOT_DELAY,0 BOUNDS_CHECK_BYPASS_MITIGATION,y BT_CONN_DISABLE_SECURITY,n -BT_DEBUG_KEYS,n -BT_DEBUG_SMP,n +BT_KEYS_LOG_LEVEL_DBG,n +BT_SMP_LOG_LEVEL_DBG,n BT_FIXED_PASSKEY,n BT_LOG_SNIFFER_INFO,n BT_OOB_DATA_FIXED,n diff --git a/subsys/bluetooth/Kconfig.logging b/subsys/bluetooth/Kconfig.logging index 6c6c26f0b77109..6cd4006c91abc5 100644 --- a/subsys/bluetooth/Kconfig.logging +++ b/subsys/bluetooth/Kconfig.logging @@ -7,704 +7,89 @@ config BT_LOG # convenience symbol, _no touchy_ bool default y if LOG && BT - select BT_LOG_LEGACY if BT_LOG menu "Bluetooth logging" -config BT_LOG_LEGACY - bool - -if BT_LOG_LEGACY - -menu "Bluetooth legacy logging options" - -# COMMON - -config BT_DEBUG_HCI_DRIVER - bool "[DEPRECATED] Bluetooth HCI driver debug" - select DEPRECATED - help - This option enables debug support for the active - Bluetooth HCI driver, including the Controller-side HCI layer - when included in the build. - -config BT_DEBUG_RPA - bool "[DEPRECATED] Bluetooth Resolvable Private Address (RPA) debug" - select DEPRECATED - depends on BT_RPA - help - This option enables debug support for the Bluetooth - Resolvable Private Address (RPA) generation and resolution. - -menu "[DEPRECATED] Audio" - -# AICS - -config BT_DEBUG_AICS - bool "[DEPRECATED] Audio Input Control Service debug" - select DEPRECATED - help - Use this option to enable Audio Input Control Service debug logs for - the Bluetooth Audio functionality. - -config BT_DEBUG_AICS_CLIENT - bool "[DEPRECATED] Audio Input Control Service client debug" - select DEPRECATED - help - Use this option to enable Audio Input Control Service client debug - logs for the Bluetooth Audio functionality. - -# BAP - -config BT_BAP_DEBUG_STREAM - bool "[DEPRECATED] Basic Audio Profile Stream debug" - select DEPRECATED - depends on BT_BAP_STREAM - help - Use this option to enable Basic Audio Profile Stream debug logs. - -config BT_DEBUG_ASCS - bool "[DEPRECATED] Audio Stream Control Service debug" - select DEPRECATED - depends on BT_ASCS - help - Use this option to enable Audio Stream Control Service debug logs for - the Bluetooth Audio functionality. - -config BT_DEBUG_BAP_UNICAST_SERVER - bool "[DEPRECATED] Bluetooth Audio Unicast Server debug" - select DEPRECATED - depends on BT_BAP_UNICAST_SERVER - help - Use this option to enable Bluetooth Audio Unicast Server debug logs - for the Bluetooth Audio functionality. - -config BT_DEBUG_BAP_UNICAST_CLIENT - bool "[DEPRECATED] Basic Audio Profile client debug" - select DEPRECATED - depends on BT_BAP_UNICAST_CLIENT - help - Use this option to enable Basic Audio Profile debug logs for the - Bluetooth Audio functionality. - -config BT_DEBUG_BAP_BROADCAST_SOURCE - bool "[DEPRECATED] Bluetooth Audio Broadcast Source debug" - select DEPRECATED - depends on BT_BAP_BROADCAST_SOURCE - help - Use this option to enable Bluetooth Audio Broadcast Source debug logs - for the Bluetooth Audio functionality. - -config BT_DEBUG_BAP_BROADCAST_SINK - bool "[DEPRECATED] Bluetooth Audio Broadcast Sink debug" - select DEPRECATED - depends on BT_BAP_BROADCAST_SINK - help - Use this option to enable Bluetooth Audio Broadcast Sink debug logs - for the Bluetooth Audio functionality. - -config BT_DEBUG_BAP_SCAN_DELEGATOR - bool "[DEPRECATED] Broadcast Audio Scan Service debug" - select DEPRECATED - depends on BT_BAP_SCAN_DELEGATOR - help - Use this option to enable Broadcast Audio Scan Service debug logs for - the Bluetooth Audio functionality. - -config BT_DEBUG_BAP_BROADCAST_ASSISTANT - bool "[DEPRECATED] Broadcast Audio Scan Service client debug" - select DEPRECATED - depends on BT_BAP_BROADCAST_ASSISTANT - help - Use this option to enable Broadcast Audio Scan Service client - debug logs for the Bluetooth Audio functionality. - -# CAP - -config BT_DEBUG_CAP_ACCEPTOR - bool "[DEPRECATED] Common Audio Profile debug" - select DEPRECATED - depends on BT_CAP_ACCEPTOR - help - Use this option to enable CAP debug logs for the - Bluetooth Audio functionality. - -config BT_DEBUG_CAP_INITIATOR - bool "[DEPRECATED] Common Audio Profile Initiator debug" - select DEPRECATED - depends on BT_CAP_INITIATOR - help - Use this option to enable CAP Initiator debug logs for the - Bluetooth Audio functionality. - -# CISP - -config BT_DEBUG_CSIP_SET_MEMBER - bool "[DEPRECATED] Coordinated Set Identification Service debug" - select DEPRECATED - help - Use this option to enable Coordinated Set Identification Service debug - logs for the Bluetooth Audio functionality. - -config BT_DEBUG_CSIP_SET_COORDINATOR - bool "[DEPRECATED] Coordinated Set Identification Profile Set Coordinator debug" - select DEPRECATED - help - Use this option to enable Coordinated Set Identification Profile - Set Coordinator debug logs for the Bluetooth Audio functionality. - -config BT_DEBUG_CSIP_SET_MEMBER_CRYPTO - bool "[DEPRECATED] Coordinated Set Identification Profile crypto functions debug" - select DEPRECATED - depends on BT_CSIP_SET_COORDINATOR || BT_CSIP_SET_MEMBER - help - Use this option to enable Coordinated Set Identification Profile - crypto functions debug logs for the Bluetooth Audio functionality. - -# HAS - -config BT_DEBUG_HAS - bool "[DEPRECATED] Hearing Access Service debug" - select DEPRECATED - help - This option enables enables Hearing Access Service debug logs. - -config BT_DEBUG_HAS_CLIENT - bool "[DEPRECATED] Hearing Access Service Client debug" - select DEPRECATED - depends on BT_HAS_CLIENT - help - This option enables enables Hearing Access Service Client debug logs. - -# MCS - -config BT_DEBUG_MCS - bool "[DEPRECATED] Media Control Service debug" - select DEPRECATED - help - Use this option to enable Media Control Service debug logs for the - Bluetooth Audio functionality. - -config BT_DEBUG_MCC - bool "[DEPRECATED] Media Control Client debug" - select DEPRECATED - help - Use this option to enable Media Control Client debug logs for the - Bluetooth Audio functionality. - -# MCTL - -config MCTL_DEBUG - bool "[DEPRECATED] Media control debug" - select DEPRECATED - help - Use this option to enable Media control debug logs - -# MICP - -config BT_DEBUG_MICP_MIC_DEV - bool "[DEPRECATED] Microphone Control Profile Microphone Device debug" - select DEPRECATED - help - Use this option to enable Microphone Control Profile - Microphone Device debug logs for the Bluetooth Audio functionality. - -config BT_DEBUG_MICP_MIC_CTLR - bool "[DEPRECATED] Microphone Control Profile Microphone Controller debug" - select DEPRECATED - help - Use this option to enable Microphone Control Profile Microphone - Controller debug logs for the Bluetooth Audio functionality. - -# MPL - -config BT_DEBUG_MPL - bool "[DEPRECATED] Media player debug" - select DEPRECATED - help - Enables debug logs for the media player - -# PACS - -config BT_DEBUG_PACS - bool "[DEPRECATED] Published Audio Capabilities Service debug" - select DEPRECATED - depends on BT_PACS - help - Use this option to enable Published Audio Capabilities Service debug - logs for the Bluetooth Audio functionality. - -# TBS - -config BT_DEBUG_TBS - bool "[DEPRECATED] Telephone Bearer Service debug" - select DEPRECATED - help - Use this option to enable Telephone Bearer Service debug logs for the - Bluetooth Audio functionality. - -config BT_DEBUG_TBS_CLIENT - bool "[DEPRECATED] Telephone Bearer Service client debug" - select DEPRECATED - help - Use this option to enable Telephone Bearer Service client debug logs - for the Bluetooth Audio functionality. - -# VCP - -config BT_DEBUG_VCP_VOL_REND - bool "[DEPRECATED] Volume Control Profile Volume Renderer debug" - select DEPRECATED - help - Use this option to enable Volume Control Profile debug logs for the - Bluetooth Audio functionality. - -config BT_DEBUG_VCP_VOL_CTLR - bool "[DEPRECATED] Volume Control Profile Volume Controller debug" - select DEPRECATED - help - Use this option to enable Volume Control Profile Volume Controller - debug logs for the Bluetooth Audio functionality. - -# VOCS - -config BT_DEBUG_VOCS - bool "[DEPRECATED] Volume Offset Control Service debug" - select DEPRECATED - help - Use this option to enable Volume Offset Control Service debug logs for - the Bluetooth Audio functionality. - -config BT_DEBUG_VOCS_CLIENT - bool "[DEPRECATED] Volume Offset Control Service client debug" - select DEPRECATED - help - Use this option to enable Volume Offset Control Service client debug - logs for the Bluetooth Audio functionality. - -endmenu # [DEPRECATED] Audio - -menu "[DEPRECATED] Others" - -# CRYPTO (subsys/bluetooth/crypto/Kconfig) - -config BT_DEBUG_CRYPTO - bool "[DEPRECATED] Bluetooth Cryptographic Toolbox debug" - select DEPRECATED - depends on BT_CRYPTO - help - This option enables debug log output for the Bluetooth - Cryptographic Toolbox. - - WARNING: This option prints out private security keys such as - the Long Term Key. - Use of this feature in production is strongly discouraged. - -# GATT - -config BT_DEBUG_ATT - bool "[DEPRECATED] Bluetooth Attribute Protocol (ATT) debug" - select DEPRECATED - help - This option enables debug support for the Bluetooth - Attribute Protocol (ATT). - -config BT_DEBUG_GATT - bool "[DEPRECATED] Bluetooth Generic Attribute Profile (GATT) debug" - select DEPRECATED - help - This option enables debug support for the Bluetooth - Generic Attribute Profile (GATT). - -# L2CAP - -config BT_DEBUG_L2CAP - bool "[DEPRECATED] Bluetooth L2CAP debug" - select DEPRECATED - help - This option enables debug support for the Bluetooth - L2ACP layer. - -# HOST (subsys/bluetooth/host/Kconfig) - -config BT_DEBUG_DF - bool "[DEPRECATED] Bluetooth Direction Finding debug" - select DEPRECATED - help - This option enables debug support for Bluetooth Direction Finding - -config BT_DEBUG_SETTINGS - bool "[DEPRECATED] Bluetooth storage debug" - select DEPRECATED - depends on BT_SETTINGS - help - This option enables debug support for Bluetooth storage. - -config BT_DEBUG_HCI_CORE - bool "[DEPRECATED] Bluetooth HCI core debug" - select DEPRECATED - help - This option enables debug support for Bluetooth HCI - core. - -config BT_DEBUG_CONN - bool "[DEPRECATED] Bluetooth connection debug" - select DEPRECATED - depends on BT_CONN || BT_ISO - help - This option enables debug support for Bluetooth - connection handling. - -config BT_DEBUG_ISO - bool "[DEPRECATED] ISO channel debug" - select DEPRECATED - help - Use this option to enable ISO channels debug logs for the - Bluetooth Audio functionality. - -config BT_DEBUG_KEYS - bool "[DEPRECATED] Bluetooth security keys debug" - select DEPRECATED - depends on BT_HCI_HOST - depends on BT_SMP - help - This option enables debug support for the handling of - Bluetooth security keys. - - WARNING: This option prints out private security keys such as - the Long Term Key. - Use of this feature in production is strongly discouraged. - -config BT_DEBUG_SMP - bool "[DEPRECATED] Bluetooth Security Manager Protocol (SMP) debug" - select DEPRECATED - depends on BT_HCI_HOST - depends on BT_SMP - help - This option enables debug support for the Bluetooth - Security Manager Protocol (SMP). - - WARNING: This option prints out private security keys such as - the Long Term Key. - Use of this feature in production is strongly discouraged. - -config BT_DEBUG_SERVICE - bool "[DEPRECATED] Bluetooth Services debug" - select DEPRECATED - depends on BT_CONN - help - This option enables debug support for the Bluetooth - Services. - -# CONTROLLER (subsys/bluetooth/controller/Kconfig) - -config BT_CTLR_DEBUG_ISOAL - bool "[DEPRECATED] Bluetooth ISO-AL debug" - select DEPRECATED - depends on BT_CTLR_ISO - help - This option enables debug support for the Bluetooth ISO-AL. - - -endmenu # [DEPRECATED] Others - -menu "[DEPRECATED] BR/EDR" - -config BT_DEBUG_RFCOMM - bool "[DEPRECATED] Bluetooth RFCOMM debug" - select DEPRECATED - depends on BT_RFCOMM - help - This option enables debug support for the Bluetooth - RFCOMM layer. - -config BT_DEBUG_HFP_HF - bool "[DEPRECATED] Bluetooth Hands Free Profile (HFP) debug" - select DEPRECATED - depends on BT_HFP_HF - help - This option enables debug support for the Bluetooth - Hands Free Profile (HFP). - -config BT_DEBUG_AVDTP - bool "[DEPRECATED] Bluetooth AVDTP debug" - select DEPRECATED - depends on BT_AVDTP - help - This option enables debug support for the Bluetooth AVDTP. - -config BT_DEBUG_A2DP - bool "[DEPRECATED] Bluetooth A2DP debug" - select DEPRECATED - depends on BT_A2DP - help - This option enables debug support for the Bluetooth - A2DP profile. - -config BT_DEBUG_SDP - bool "[DEPRECATED] Bluetooth Service Discovery Protocol (SDP) debug" - select DEPRECATED - depends on BT_CLASSIC - help - This option enables debug support for the Bluetooth - Service Discovery Protocol (SDP). - -endmenu # [DEPRECATED] BR/EDR - -# MESH (subsys/bluetooth/mesh/Kconfig) - -menu "[DEPRECATED] Mesh" - -config BT_MESH_DEBUG - bool "[DEPRECATED] Debug logs" - select DEPRECATED - help - Use this option to enable debug logs for the Bluetooth - Mesh functionality. - -config BT_MESH_DEBUG_NET - bool "[DEPRECATED] Network layer debug" - select DEPRECATED - help - Use this option to enable Network layer debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_RPL - bool "[DEPRECATED] Replay protection list debug" - select DEPRECATED - help - Use this option to enable Replay protection list debug logs - for the Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_TRANS - bool "[DEPRECATED] Transport layer debug" - select DEPRECATED - help - Use this option to enable Transport layer debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_BEACON - bool "[DEPRECATED] Beacon debug" - select DEPRECATED - help - Use this option to enable Beacon-related debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_CRYPTO - bool "[DEPRECATED] Crypto debug" - select DEPRECATED - help - Use this option to enable cryptographic debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_KEYS - bool "[DEPRECATED] Key management debug" - select DEPRECATED - help - Use this option to enable key management debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_PROV - bool "[DEPRECATED] Provisioning debug" - select DEPRECATED - help - Use this option to enable Provisioning debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_PROVISIONER - bool "[DEPRECATED] Provisioner debug" - select DEPRECATED - help - Use this option to enable Provisioner debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_PROV_DEVICE - bool "[DEPRECATED] Provisioning device debug" - select DEPRECATED - help - Use this option to enable Provisioning device debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_ACCESS - bool "[DEPRECATED] Access layer debug" - select DEPRECATED - help - Use this option to enable Access layer and device composition - related debug logs for Bluetooth Mesh. - -config BT_MESH_DEBUG_MODEL - bool "[DEPRECATED] Foundation model debug" - select DEPRECATED - help - Use this option to enable debug logs for the Foundation - Models. - -config BT_MESH_DEBUG_ADV - bool "[DEPRECATED] Advertising debug" - select DEPRECATED - help - Use this option to enable advertising debug logs for - the Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_LOW_POWER - bool "[DEPRECATED] Low Power debug" - select DEPRECATED - help - Use this option to enable Low Power debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_FRIEND - bool "[DEPRECATED] Friend debug" - select DEPRECATED - help - Use this option to enable Friend debug logs for the - Bluetooth Mesh functionality. - -config BT_MESH_DEBUG_PROXY - bool "[DEPRECATED] Proxy debug" - select DEPRECATED - depends on BT_MESH_GATT - help - Use this option to enable Proxy protocol debug logs. - -config BT_MESH_DEBUG_SETTINGS - bool "[DEPRECATED] Persistent settings debug" - select DEPRECATED - depends on BT_SETTINGS - help - Use this option to enable persistent settings debug logs. - -config BT_MESH_DEBUG_CDB - bool "[DEPRECATED] Configuration database debug" - select DEPRECATED - depends on BT_MESH_CDB - help - Use this option to enable configuration database debug logs. - -config BT_MESH_DEBUG_CFG - bool "[DEPRECATED] Configuration debug" - select DEPRECATED - help - Use this option to enable node configuration debug logs for the - Bluetooth Mesh functionality. - -endmenu # [DEPRECATED] Mesh - -menu "[DEPRECATED] Services" - -# IAS - -config BT_DEBUG_IAS_CLIENT - bool "[DEPRECATED] Immediate Alert Service Client debug" - select DEPRECATED - depends on BT_IAS_CLIENT - help - This option enables enables Immediate Alert Service Client debug logs. - -# OTS - -# TODO: Unify logging for OTS server and client - the client uses -# "BT" debugging, the server does not. - -config BT_DEBUG_OTS_CLIENT - bool "[DEPRECATED] Object Transfer Service Client debug" - select DEPRECATED - help - Use this option to enable Object Transfer Client debug logs - -endmenu # [DEPRECATED] Services - -endmenu # Bluetooth legacy logging options - -endif # BT_LOG_LEGACY - # (subsys/bluetooth/Kconfig) module = BT module-str = "Bluetooth" source "subsys/logging/Kconfig.template.log_config" +# Set BT as the parent module for all the symbols that will use +# `Kconfig.template.log_config_inherit`. This is more convenient to do it here +# instead of setting it for every modules. +# +# The downside of doing that is that people need to be careful when adding a new +# parent module because all the following symbol will use it. +parent-module = BT + # COMMON (subsys/bluetooth/common/Kconfig) module = BT_HCI_DRIVER -legacy-debug-sym = BT_DEBUG_HCI_DRIVER module-str = "Bluetooth HCI driver" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_RPA -legacy-debug-sym = BT_DEBUG_RPA module-str = "Bluetooth Resolvable Private Address (RPA)" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" menu "Audio" # AICS module = BT_AICS -legacy-debug-sym = BT_DEBUG_AICS module-str = "Audio Input Control Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_AICS_CLIENT -legacy-debug-sym = BT_DEBUG_AICS_CLIENT module-str = "Audio Input Control Service client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # BAP module = BT_BAP_STREAM -legacy-debug-sym = BT_BAP_DEBUG_STREAM module-str = "Bluetooth Audio Stream" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" -parent-module = BT module = BT_BAP_BASE module-str = "Bluetooth Basic Audio Profile Broadcast Audio Source Endpoint" source "subsys/logging/Kconfig.template.log_config_inherit" -parent-module = BT module = BT_AUDIO_CODEC module-str = "Bluetooth Audio Codec" source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_ASCS -legacy-debug-sym = BT_DEBUG_ASCS module-str = "Audio Stream Control Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_BAP_UNICAST_SERVER -legacy-debug-sym = BT_DEBUG_BAP_UNICAST_SERVER module-str = "Bluetooth Audio Unicast Server" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_BAP_UNICAST_CLIENT -legacy-debug-sym = BT_DEBUG_BAP_UNICAST_CLIENT module-str = "Basic Audio Profile" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_BAP_BROADCAST_SOURCE -legacy-debug-sym = BT_DEBUG_BAP_BROADCAST_SOURCE module-str = "Bluetooth Audio Broadcast Source" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_BAP_BROADCAST_SINK -legacy-debug-sym = BT_DEBUG_BAP_BROADCAST_SINK module-str = "Bluetooth Audio Broadcast Sink" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_BAP_SCAN_DELEGATOR -legacy-debug-sym = BT_DEBUG_BAP_SCAN_DELEGATOR module-str = "Broadcast Audio Scan Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_BAP_BROADCAST_ASSISTANT -legacy-debug-sym = BT_DEBUG_BAP_BROADCAST_ASSISTANT module-str = "Broadcast Audio Scan Service client debug" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" -parent-module = BT module = BT_BAP_ISO module-str = "Bluetooth Audio ISO" source "subsys/logging/Kconfig.template.log_config_inherit" @@ -712,26 +97,21 @@ source "subsys/logging/Kconfig.template.log_config_inherit" # CAP module = BT_CAP_ACCEPTOR -legacy-debug-sym = BT_DEBUG_CAP_ACCEPTOR module-str = "Common Audio Profile Acceptor" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_CAP_INITIATOR -legacy-debug-sym = BT_DEBUG_CAP_INITIATOR module-str = "Common Audio Profile Initiator" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" -parent-module = BT module = BT_CAP_COMMANDER module-str = "Common Audio Profile Commander" source "subsys/logging/Kconfig.template.log_config_inherit" -parent-module = BT module = BT_CAP_COMMON module-str = "Common Audio Profile Common" source "subsys/logging/Kconfig.template.log_config_inherit" -parent-module = BT module = BT_CAP_STREAM module-str = "Common Audio Profile Stream" source "subsys/logging/Kconfig.template.log_config_inherit" @@ -739,112 +119,94 @@ source "subsys/logging/Kconfig.template.log_config_inherit" # CSIP module = BT_CSIP_SET_MEMBER -legacy-debug-sym = BT_DEBUG_CSIP_SET_MEMBER module-str = "Coordinated Set Identification Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_CSIP_SET_COORDINATOR -legacy-debug-sym = BT_DEBUG_CSIP_SET_COORDINATOR module-str = "Coordinated Set Identification Profile Set Coordinator" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_CSIP_SET_MEMBER_CRYPTO -legacy-debug-sym = BT_DEBUG_CSIP_SET_MEMBER_CRYPTO module-str = "Coordinated Set Identification Profile crypto functions" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # HAS module = BT_HAS -legacy-debug-sym = BT_DEBUG_HAS module-str = "Hearing Access Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_HAS_CLIENT -legacy-debug-sym = BT_DEBUG_HAS_CLIENT module-str = "Hearing Access Service Client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # MCS module = BT_MCS -legacy-debug-sym = BT_DEBUG_MCS module-str = "Media Control Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MCC -legacy-debug-sym = BT_DEBUG_MCC module-str = "Media Control Client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # MCTL module = MCTL -legacy-debug-sym = MCTL_DEBUG module-str = "Media control" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # MICP module = BT_MICP_MIC_DEV -legacy-debug-sym = BT_DEBUG_MICP_MIC_DEV module-str = "Microphone Control Profile Microphone Device" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MICP_MIC_CTLR -legacy-debug-sym = BT_DEBUG_MICP_MIC_CTLR module-str = "Microphone Control Profile Microphone Controller" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # MPL module = BT_MPL -legacy-debug-sym = BT_DEBUG_MPL module-str = "Media player" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # PACS module = BT_PACS -legacy-debug-sym = BT_DEBUG_PACS module-str = "Published Audio Capabilities Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # TBS module = BT_TBS -legacy-debug-sym = BT_DEBUG_TBS module-str = "Telephone Bearer Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_TBS_CLIENT -legacy-debug-sym = BT_DEBUG_TBS_CLIENT module-str = "Telephone Bearer Service client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # VCP module = BT_VCP_VOL_REND -legacy-debug-sym = BT_DEBUG_VCP_VOL_REND module-str = "Volume Control Profile Voluem Renderer" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_VCP_VOL_CTLR -legacy-debug-sym = BT_DEBUG_VCP_VOL_CTLR module-str = "Volume Control Profile Volume Controller" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # VOCS module = BT_VOCS -legacy-debug-sym = BT_DEBUG_VOCS module-str = "Volume Offset Control Service" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_VOCS_CLIENT -legacy-debug-sym = BT_DEBUG_VOCS_CLIENT module-str = "Volume Offset Control Service client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # PBP @@ -859,32 +221,27 @@ menu "Others" # CRYPTO (subsys/bluetooth/crypto/Kconfig) module = BT_CRYPTO -legacy-debug-sym = BT_DEBUG_CRYPTO module-str = "Bluetooth Cryptographic Toolbox" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # GATT module = BT_ATT -legacy-debug-sym = BT_DEBUG_ATT module-str = "Bluetooth Attribute Protocol (ATT)" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_GATT -legacy-debug-sym = BT_DEBUG_GATT module-str = "Bluetooth Generic Attribute Profile (GATT)" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # L2CAP module = BT_L2CAP -legacy-debug-sym = BT_DEBUG_L2CAP module-str = "Bluetooth L2CAP" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # LIB (subsys/bluetooth/lib/Kconfig) -parent-module = BT module = BT_EAD module-str = "Bluetooth Encrypted Advertising Data" source "subsys/logging/Kconfig.template.log_config_inherit" @@ -892,80 +249,66 @@ source "subsys/logging/Kconfig.template.log_config_inherit" # HOST (subsys/bluetooth/host/Kconfig) module = BT_DF -legacy-debug-sym = BT_DEBUG_DF module-str = "Bluetooth Direction Finding" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_SETTINGS -legacy-debug-sym = BT_DEBUG_SETTINGS module-str = "Bluetooth storage" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_HCI_CORE -legacy-debug-sym = BT_DEBUG_HCI_CORE module-str = "Bluetooth HCI core" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_CONN -legacy-debug-sym = BT_DEBUG_CONN module-str = "Bluetooth connection" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_ISO -legacy-debug-sym = BT_DEBUG_ISO module-str = "ISO channel" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_KEYS -legacy-debug-sym = BT_DEBUG_KEYS module-str = "Bluetooth security keys" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_SMP -legacy-debug-sym = BT_DEBUG_SMP module-str = "Bluetooth Security Manager Protocol" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_SERVICE -legacy-debug-sym = BT_DEBUG_SERVICE module-str = "Bluetooth Services" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" # CONTROLLER (subsys/bluetooth/controller/Kconfig) module = BT_CTLR_ISOAL -legacy-debug-sym = BT_CTLR_DEBUG_ISOAL module-str = "Bluetooth Controller ISO-AL" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" endmenu # Others menu "BR/EDR" module = BT_RFCOMM -legacy-debug-sym = BT_DEBUG_RFCOMM module-str = "Bluetooth RFCOMM" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_HFP_HF -legacy-debug-sym = BT_DEBUG_HFP_HF module-str = "Bluetooth Hands Free Profile (HFP)" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_AVDTP -legacy-debug-sym = BT_DEBUG_AVDTP module-str = "Bluetooth AVDTP debug" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_A2DP -legacy-debug-sym = BT_DEBUG_A2DP module-str = "Bluetooth A2DP" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_SDP -legacy-debug-sym = BT_DEBUG_SDP module-str = "Bluetooth Service Discovery Protocol (SDP)" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" endmenu # BR/EDR @@ -974,103 +317,84 @@ endmenu # BR/EDR menu "Mesh" module = BT_MESH -legacy-debug-sym = BT_MESH_DEBUG module-str = "Debug logs" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_NET -legacy-debug-sym = BT_MESH_DEBUG_NET module-str = "Network layer" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_RPL -legacy-debug-sym = BT_MESH_DEBUG_RPL module-str = "Replay protection list" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_TRANS -legacy-debug-sym = BT_MESH_DEBUG_TRANS module-str = "Transport layer" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_BEACON -legacy-debug-sym = BT_MESH_DEBUG_BEACON module-str = "Beacon" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_CRYPTO -legacy-debug-sym = BT_MESH_DEBUG_CRYPTO module-str = "Crypto" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_KEYS -legacy-debug-sym = BT_MESH_DEBUG_KEYS module-str = "Key management" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_PROV -legacy-debug-sym = BT_MESH_DEBUG_PROV module-str = "Provisioning" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_PROVISIONER -legacy-debug-sym = BT_MESH_DEBUG_PROVISIONER module-str = "Provisioner" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_PROVISIONEE -legacy-debug-sym = BT_MESH_DEBUG_PROV_DEVICE module-str = "Provisioning device" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_ACCESS -legacy-debug-sym = BT_MESH_DEBUG_ACCESS module-str = "Access layer" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_MODEL -legacy-debug-sym = BT_MESH_DEBUG_MODEL module-str = "Foundation model" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_DFU module-str = "DFU model" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_ADV -legacy-debug-sym = BT_MESH_DEBUG_ADV module-str = "Advertising" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_LOW_POWER -legacy-debug-sym = BT_MESH_DEBUG_LOW_POWER module-str = "Low Power" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_FRIEND -legacy-debug-sym = BT_MESH_DEBUG_FRIEND module-str = "Friend" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_PROXY -legacy-debug-sym = BT_MESH_DEBUG_PROXY module-str = "Proxy" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_SETTINGS -legacy-debug-sym = BT_MESH_DEBUG_SETTINGS module-str = "Persistent settings" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_CDB -legacy-debug-sym = BT_MESH_DEBUG_CDB module-str = "Configuration database" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_MESH_CFG -legacy-debug-sym = BT_MESH_DEBUG_CFG module-str = "Configuration" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" endmenu # Mesh @@ -1097,9 +421,8 @@ source "subsys/logging/Kconfig.template.log_config" # IAS module = BT_IAS_CLIENT -legacy-debug-sym = BT_DEBUG_IAS_CLIENT module-str = "Immediate Alert Service Client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_IAS module-str = IAS @@ -1108,9 +431,8 @@ source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" # OTS (subsys/bluetooth/services/ots/Kconfig) module = BT_OTS_CLIENT -legacy-debug-sym = BT_DEBUG_OTS_CLIENT module-str = "Object Transfer Service Client" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" module = BT_OTS module-str = BT_OTS diff --git a/subsys/bluetooth/audio/Kconfig.tmap b/subsys/bluetooth/audio/Kconfig.tmap index 9a9d6c61d2618a..a2bc94d6fb9420 100644 --- a/subsys/bluetooth/audio/Kconfig.tmap +++ b/subsys/bluetooth/audio/Kconfig.tmap @@ -12,15 +12,7 @@ config BT_TMAP help Enabling this will enable TMAP. -config BT_DEBUG_TMAP - bool "Telephony and Media Audio Profile debug" - select DEPRECATED - depends on BT_TMAP - help - Use this option to enable Telephony and Media Audio Profile debug - logs for the Bluetooth Audio functionality. - +parent-module = BT module = BT_TMAP -legacy-debug-sym = BT_DEBUG_TMAP module-str = "Telephony and Media Audio Profile" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" diff --git a/subsys/bluetooth/common/Kconfig.template.log_config_bt b/subsys/bluetooth/common/Kconfig.template.log_config_bt deleted file mode 100644 index 0a1a865cfafc1b..00000000000000 --- a/subsys/bluetooth/common/Kconfig.template.log_config_bt +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2022 Nordic Semicoductor ASA -# SPDX-License-Identifier: Apache-2.0 - -# Usage: -# This template provides backwards compatibility for legacy kconfig symbols. -# Do not add new uses of it. -# -# The following arguments are mandatory: -# - module: -# Name of the new log level kconfig. -# Example: "BT_HCI_CORE" -# - legacy-debug-sym: -# An existing "legacy" kconfig bool. If that bool is selected, -# the new kconfig is forced to max verbosity. -# Example: "BT_DEBUG_HCI_CORE" - -config $(module)_LOG_LEVEL - default 4 if $(legacy-debug-sym) - -module := $(module) -parent-module := BT -source "subsys/logging/Kconfig.template.log_config_inherit" diff --git a/subsys/bluetooth/mesh/rpr_cli.c b/subsys/bluetooth/mesh/rpr_cli.c index cbb92e75b40cc9..5d5aeb9ee601d7 100644 --- a/subsys/bluetooth/mesh/rpr_cli.c +++ b/subsys/bluetooth/mesh/rpr_cli.c @@ -298,7 +298,7 @@ static int handle_scan_report(const struct bt_mesh_model *mod, struct bt_mesh_ms return -EINVAL; } - if (IS_ENABLED(CONFIG_BT_MESH_DEBUG)) { + if (IS_ENABLED(CONFIG_BT_MESH_MODEL_LOG_LEVEL_DBG)) { struct bt_uuid_128 uuid_repr = { .uuid = { BT_UUID_TYPE_128 } }; memcpy(uuid_repr.val, dev.uuid, 16); diff --git a/subsys/bluetooth/mesh/rpr_srv.c b/subsys/bluetooth/mesh/rpr_srv.c index d31368f317884d..ed8d87f3c04641 100644 --- a/subsys/bluetooth/mesh/rpr_srv.c +++ b/subsys/bluetooth/mesh/rpr_srv.c @@ -1173,7 +1173,7 @@ static void adv_handle_ext_scan(const struct bt_le_scan_recv_info *info, srv.scan.addr = *info->addr; atomic_set_bit(srv.flags, SCAN_EXT_HAS_ADDR); - if (IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)) { + if (IS_ENABLED(CONFIG_BT_MESH_MODEL_LOG_LEVEL_DBG)) { struct bt_uuid_128 uuid_repr = { .uuid = { BT_UUID_TYPE_128 } }; memcpy(uuid_repr.val, dev->uuid, 16); diff --git a/tests/bluetooth/ctrl_isoal/Kconfig b/tests/bluetooth/ctrl_isoal/Kconfig index 30049d53a5eec6..e6623e8e3b21fb 100644 --- a/tests/bluetooth/ctrl_isoal/Kconfig +++ b/tests/bluetooth/ctrl_isoal/Kconfig @@ -12,17 +12,10 @@ config BT_CTLR_CONN_ISO_GROUPS range 1 240 default 1 -config BT_CTLR_DEBUG_ISOAL - bool "[DEPRECATED] Bluetooth ISO-AL debug" - select DEPRECATED - depends on BT_CTLR_ISO - help - This option enables debug support for the Bluetooth ISO-AL. - +parent-module = BT module = BT_CTLR_ISOAL -legacy-debug-sym = BT_CTLR_DEBUG_ISOAL module-str = "Bluetooth Controller ISO-AL" -source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +source "subsys/logging/Kconfig.template.log_config_inherit" config BT_CTLR_ISOAL_LOG_DBG_VERBOSE bool "ISO-AL verbose debug logging" From f8f591a51f4b77e067e1f6e3f46fb4c0ba93d1e0 Mon Sep 17 00:00:00 2001 From: Arunmani Alagarsamy Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0252/1389] boards: silabs: efr32_radio: Remove duplicate usart0 definition In the .dts file, the definition for usart0 was found to be redundant as the same information is already provided in the included .dtsi file. this commit removes the duplicate definition of usart0, resulting in a cleaner and more maintainable device tree configuration. Signed-off-by: Arunmani Alagarsamy --- .../efr32_radio_efr32mg12p432f1024gl125.dts | 8 ------- .../efr32_radio_efr32mg12p433f1024gm68.dts | 8 ------- dts/arm/silabs/efr32xg12p-pinctrl.dtsi | 23 ------------------- 3 files changed, 39 deletions(-) delete mode 100644 dts/arm/silabs/efr32xg12p-pinctrl.dtsi diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts index ee57db52aedb9e..64b9dce560dd8a 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts @@ -6,7 +6,6 @@ /dts-v1/; #include -#include #include "efr32_radio.dtsi" / { @@ -73,13 +72,6 @@ }; }; -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - &i2c0 { pinctrl-0 = <&i2c0_default>; pinctrl-names = "default"; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts index ed7e2f992a183e..effd66a8515b98 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts @@ -6,7 +6,6 @@ /dts-v1/; #include -#include #include "efr32_radio.dtsi" / { @@ -61,10 +60,3 @@ }; }; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; diff --git a/dts/arm/silabs/efr32xg12p-pinctrl.dtsi b/dts/arm/silabs/efr32xg12p-pinctrl.dtsi deleted file mode 100644 index e500e3b18bdd97..00000000000000 --- a/dts/arm/silabs/efr32xg12p-pinctrl.dtsi +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2022 Silicon Labs - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -&pinctrl { - /* configuration for uart0 device, default state */ - usart0_default: usart0_default { - group1 { - /* configure PA.1 as UART_RX */ - psels = , - ; - }; - group2 { - /* configure PA.0 as UART_TX */ - psels = , - ; - }; - }; -}; From d4107974ff3a59d71e665ed94a29184d76930807 Mon Sep 17 00:00:00 2001 From: Nikolay Agishev Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0253/1389] ARCMWDT: Fix building under hwmv2 model On very early stage build system needs to get access to DTC preprocessor. MWDT has no it's own preprocessor, so here zephyr-SDK preprocessor is used. On latest build stages zephyr-SDK objcoby also required as MWDT binutils don't support all features. This at the same time requires that ZEPHYR_SDK_INSTALL_DIR must be initialized with valid arch-dependent prefix. Zephyr-SDK requires ARCH variable to be initialized before include "generic.cmake", but in hew HWMv2 model ARCH variable will be initialized more later. This workaround uses any (first awailable, independent on ARCH) toolchain from SDK for DTC preprocessing only. For other build stages ARCMWDT will be used. Signed-off-by: Nikolay Agishev --- cmake/bintools/arcmwdt/target.cmake | 15 +++++++++++---- cmake/toolchain/arcmwdt/generic.cmake | 12 +++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cmake/bintools/arcmwdt/target.cmake b/cmake/bintools/arcmwdt/target.cmake index ea461771830159..36f31fffba1e1b 100644 --- a/cmake/bintools/arcmwdt/target.cmake +++ b/cmake/bintools/arcmwdt/target.cmake @@ -20,9 +20,16 @@ SET(CMAKE_C_ARCHIVE_FINISH " -sq ") find_program(CMAKE_GDB ${CROSS_COMPILE}mdb PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH) -# MWDT binutils don't support required features like section renaming, so we -# temporarily had to use GNU objcopy instead -find_program(CMAKE_OBJCOPY ${ZEPHYR_SDK_CROSS_COMPILE}objcopy PATHS ${ZEPHYR_SDK_INSTALL_DIR} NO_DEFAULT_PATH) -message(STATUS "Found GNU objcopy helper for MWDT: ${CMAKE_OBJCOPY} (Zephyr SDK ${SDK_VERSION})") +function(zephyr_sdk_target_cmake) + # Scoped loading of variables set by Zephyr SDK target.cmake. + include(${ZEPHYR_SDK_INSTALL_DIR}/cmake/zephyr/target.cmake) + + # MWDT binutils don't support required features like section renaming, so we + # temporarily had to use GNU objcopy instead + find_program(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy PATHS ${ZEPHYR_SDK_INSTALL_DIR} NO_DEFAULT_PATH) + message(STATUS "Found GNU objcopy helper for MWDT: ${CMAKE_OBJCOPY} (Zephyr SDK ${SDK_VERSION})") +endfunction() + +zephyr_sdk_target_cmake() include(${ZEPHYR_BASE}/cmake/bintools/arcmwdt/target_bintools.cmake) diff --git a/cmake/toolchain/arcmwdt/generic.cmake b/cmake/toolchain/arcmwdt/generic.cmake index 3f5fded2dac4d4..42a8331f00403e 100644 --- a/cmake/toolchain/arcmwdt/generic.cmake +++ b/cmake/toolchain/arcmwdt/generic.cmake @@ -23,7 +23,17 @@ find_package(Zephyr-sdk 0.15 REQUIRED) # https://github.com/zephyrproject-rtos/sdk-ng/pull/682 got merged and we switch to proper SDK # version. set(TOOLCHAIN_HOME ${ZEPHYR_SDK_INSTALL_DIR}) -include(${ZEPHYR_SDK_INSTALL_DIR}/cmake/zephyr/target.cmake) + +# On very early stage build system needs to get access to DTC preprocessor. +# MWDT has no it's own preprocessor, so here zephyr-SDK preprocessor is used. +# At the same time zephyr-SDK requires ARCH variable to be initialized before include "generic.cmake", +# but in hew HWMv2 model ARCH variable will be initialized more later. +# This workaround uses any (first awailable, independent on ARCH) toolchain from SDK for DTC preprocessing only. +# For other build stages ARCMWDT will be used. +include(${ZEPHYR_SDK_INSTALL_DIR}/cmake/zephyr/generic.cmake) +unset(TOOLCHAIN_HAS_NEWLIB CACHE) +unset(TOOLCHAIN_HAS_PICOLIBC CACHE) + set(ZEPHYR_SDK_CROSS_COMPILE ${CROSS_COMPILE}) # Handling to be improved in Zephyr SDK, to avoid overriding ZEPHYR_TOOLCHAIN_VARIANT by # find_package(Zephyr-sdk) if it's already set From 3c4f79f9d95280c0647025cc7d74cc3cd0efde45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0254/1389] include: dts: nrf: add EXMIF pinctrl definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added EXMIP pinctrl definitions, which allow selecting pin functions by name in DTS. The definitions are added, but not used in pinctrl_nrf.c. The nrf-regtool reads the pinctrl configuration and applies the settings using different mechanisms. Signed-off-by: Rafał Kuźnia --- .../zephyr/dt-bindings/pinctrl/nrf-pinctrl.h | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h index 9d7f8c2312fe13..a50233ab38c7fc 100644 --- a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h @@ -126,6 +126,28 @@ #define NRF_FUN_QSPI_IO2 33U /** QSPI IO3 */ #define NRF_FUN_QSPI_IO3 34U +/** EXMIF CK */ +#define NRF_FUN_EXMIF_CK 35U +/** EXMIF DQ0 */ +#define NRF_FUN_EXMIF_DQ0 36U +/** EXMIF DQ1 */ +#define NRF_FUN_EXMIF_DQ1 37U +/** EXMIF DQ2 */ +#define NRF_FUN_EXMIF_DQ2 38U +/** EXMIF DQ3 */ +#define NRF_FUN_EXMIF_DQ3 39U +/** EXMIF DQ4 */ +#define NRF_FUN_EXMIF_DQ4 40U +/** EXMIF DQ5 */ +#define NRF_FUN_EXMIF_DQ5 41U +/** EXMIF DQ6 */ +#define NRF_FUN_EXMIF_DQ6 42U +/** EXMIF DQ7 */ +#define NRF_FUN_EXMIF_DQ7 43U +/** EXMIF CS0 */ +#define NRF_FUN_EXMIF_CS0 44U +/** EXMIF CS1 */ +#define NRF_FUN_EXMIF_CS1 45U /** @} */ From 9982dd2bc7b3e5c2e82b89fd2131ea6a3e2dba9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0255/1389] soc: nrf54h: Enable SPI DW HSSI register layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nRF54H20 implements a variant of the SPI DW peripheral that has slightly different register layout. Enable it in the defconfig. Signed-off-by: Rafał Kuźnia --- soc/nordic/nrf54h/Kconfig.defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/nordic/nrf54h/Kconfig.defconfig b/soc/nordic/nrf54h/Kconfig.defconfig index 72ba234e883b4f..ad06920c15ce83 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig +++ b/soc/nordic/nrf54h/Kconfig.defconfig @@ -33,4 +33,7 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC endif # RISCV +config SPI_DW_HSSI + default y if SPI_DW + endif # SOC_SERIES_NRF54HX From a4ca0c35ddbc7d870b788f7c88f193cb6f74ac24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Sun, 26 May 2024 22:38:37 +0200 Subject: [PATCH 0256/1389] dts: nordic: add EXMIF peripheral description to nRF54H20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added EXMIF peripheral DTS description and bindings. The peripheral operates as an SPI device. Signed-off-by: Rafał Kuźnia --- dts/bindings/spi/nordic,nrf-exmif.yaml | 12 ++++++++++++ dts/common/nordic/nrf54h20.dtsi | 13 +++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 dts/bindings/spi/nordic,nrf-exmif.yaml diff --git a/dts/bindings/spi/nordic,nrf-exmif.yaml b/dts/bindings/spi/nordic,nrf-exmif.yaml new file mode 100644 index 00000000000000..d2b8815046b5b5 --- /dev/null +++ b/dts/bindings/spi/nordic,nrf-exmif.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic External Memory Interface (EXMIF) + +compatible: "nordic,nrf-exmif" + +include: snps,designware-spi.yaml + +properties: + reg: + required: true diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 0131763ef1e95b..75d112b85e2c80 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -308,6 +308,19 @@ status = "disabled"; }; + exmif: spi@95000 { + compatible = "nordic,nrf-exmif", "snps,designware-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x95000 0x500 0x95500 0xb00>; + reg-names = "wrapper", "core"; + interrupts = <149 NRF_DEFAULT_IRQ_PRIORITY>; + clock-frequency = ; + fifo-depth = <32>; + max-xfer-size = <16>; + status = "disabled"; + }; + cpusec_bellboard: mailbox@99000 { reg = <0x99000 0x1000>; status = "disabled"; From 83d4728b062440473912f76f4d4f1a67c1edc75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0257/1389] boards: nordic: add mx25uw6345g flash node to nRF54H20dk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nRF54H20dk has mx25uw6345g flash device on board. Added DTS description and pinctrl configuration. The flash device node is disabled by default. The flash device needs to be powered-on using the nRF Connect for Desktop Board Configurator application. Signed-off-by: Rafał Kuźnia --- .../nrf54h20dk_nrf54h20-pinctrl.dtsi | 9 ++++++ .../nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi index 6c6da3fa747e68..0cfe8a24c43ccd 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi @@ -50,4 +50,13 @@ ; }; }; + + /omit-if-no-ref/ exmif_default: exmif_default { + group1 { + psels = , + , + ; + nordic,drive-mode = ; + }; + }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index a62c7c88fe6bf6..fd838f3757df9e 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -195,3 +195,32 @@ ipc0: &cpuapp_cpurad_ipc { pinctrl-names = "default", "sleep"; hw-flow-control; }; + +&gpio6 { + status = "okay"; +}; + +&exmif { + cs-gpios = <&gpio6 3 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&exmif_default>; + pinctrl-names = "default"; + status = "okay"; + mx25uw63: mx25uw6345g@0 { + compatible = "jedec,spi-nor"; + status = "disabled"; + reg = <0>; + spi-max-frequency = ; + jedec-id = [c2 84 37]; + sfdp-bfp = [ + e5 20 8a ff ff ff ff 03 00 ff 00 ff 00 ff 00 ff + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 10 d8 + 00 ff 00 ff 87 79 01 00 84 12 00 c4 cc 04 67 46 + 30 b0 30 b0 f4 bd d5 5c 00 00 00 ff 10 10 00 20 + 00 00 00 00 00 00 7c 23 48 00 00 00 00 00 88 88 + ]; + size = <67108864>; + has-dpd; + t-enter-dpd = <10000>; + t-exit-dpd = <30000>; + }; +}; From 4cca6716b52f8dfe090c2477afbce0aff4707319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0258/1389] samples: drivers: jesd216: add nRF54H20 overlay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure the sample for nRF54H20 CPUAPP. Signed-off-by: Rafał Kuźnia --- .../jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..b8f138ad2b2e21 --- /dev/null +++ b/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25uw63 { + status = "okay"; +}; From f1827fa8fd53ab67abc205415cfae6b89469f4d2 Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0259/1389] linker: lld: cortex_m: Place .ARM.exidx sections when using lld Currently, .ARM.exidx input sections are only handled when building with ld. When building with lld (and depending on the orphan section handling policy configured), a few issues can arise: 1. lld may produce warnings about the orphan section 2. lld may place the input .ARM.exidx sections in unexpected ways--it seems lld does place the .ARM.exidx input sections in the expected .ARM.exidx output section, but it places them at the end of the section (after '__exidx_end'). To resolve the possible warning and unexpected placement, explicitly handle .ARM.exidx sections when lld is used. Signed-off-by: Jonathon Penix --- include/zephyr/arch/arm/cortex_m/scripts/linker.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index da802647db1254..6d5ba15ee6e825 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -178,7 +178,7 @@ SECTIONS * section overlap. */ __exidx_start = .; -#if defined (__GCC_LINKER_CMD__) +#if defined (__GCC_LINKER_CMD__) || defined (__LLD_LINKER_CMD__) *(.ARM.exidx* gnu.linkonce.armexidx.*) #endif __exidx_end = .; From 04a60dd08d1fe5b1c2177403198c2a89dc114683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0260/1389] soc: nordic: nrf54h20: Disable USBHS core cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure USBHS core registers as non-cachable to prevent D-Cache from inhibiting volatile accesses to the USBHS core registers. Signed-off-by: Tomasz Moń --- soc/nordic/nrf54h/CMakeLists.txt | 2 ++ soc/nordic/nrf54h/Kconfig | 2 ++ soc/nordic/nrf54h/mpu_regions.c | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 soc/nordic/nrf54h/mpu_regions.c diff --git a/soc/nordic/nrf54h/CMakeLists.txt b/soc/nordic/nrf54h/CMakeLists.txt index 1aa4723814f5df..88e45de0046746 100644 --- a/soc/nordic/nrf54h/CMakeLists.txt +++ b/soc/nordic/nrf54h/CMakeLists.txt @@ -5,6 +5,8 @@ if(CONFIG_ARM) zephyr_library_sources(soc.c) endif() +zephyr_library_sources_ifdef(CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS mpu_regions.c) + zephyr_include_directories(.) # Ensure that image size aligns with 16 bytes so that MRAMC finalizes all writes diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index 8925669ae0db49..1be3e6bc40ea8c 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -16,6 +16,7 @@ config SOC_NRF54H20_CPUAPP select CPU_HAS_DCACHE select CPU_HAS_ICACHE select CPU_HAS_FPU + select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE config SOC_NRF54H20_CPURAD @@ -27,6 +28,7 @@ config SOC_NRF54H20_CPURAD select CPU_HAS_DCACHE select CPU_HAS_ICACHE select CPU_HAS_FPU + select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE config SOC_NRF54H20_CPUPPR diff --git a/soc/nordic/nrf54h/mpu_regions.c b/soc/nordic/nrf54h/mpu_regions.c new file mode 100644 index 00000000000000..d4ffa23706447a --- /dev/null +++ b/soc/nordic/nrf54h/mpu_regions.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define USBHS_BASE DT_REG_ADDR_BY_NAME(DT_NODELABEL(usbhs), core) +#define USBHS_SIZE DT_REG_SIZE_BY_NAME(DT_NODELABEL(usbhs), core) + +static struct arm_mpu_region mpu_regions[] = { +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usbhs), okay) + MPU_REGION_ENTRY("USBHS_CORE", USBHS_BASE, + REGION_RAM_NOCACHE_ATTR(USBHS_BASE, USBHS_SIZE)), +#endif +}; + +const struct arm_mpu_config mpu_config = { + .num_regions = ARRAY_SIZE(mpu_regions), + .mpu_regions = mpu_regions, +}; From d1cc7e4d015fc83db48216611727a55bca7be65f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0261/1389] lib: smf: constant number of arguments for SMF_CREATE_STATE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This sets the number of arguments for SMF_CREATE_STATE() to always be the same, independent of the selected Kconfig options. Signed-off-by: Fin Maaß --- doc/services/smf/index.rst | 36 ++++++------- include/zephyr/smf.h | 53 ++++--------------- subsys/usb/usb_c/usbc_pe_common.c | 49 +++++++++++++---- subsys/usb/usb_c/usbc_prl.c | 14 +++++ subsys/usb/usb_c/usbc_tc_common.c | 24 ++++++--- tests/lib/smf/src/test_lib_flat_smf.c | 8 +-- .../test_lib_hierarchical_5_ancestor_smf.c | 18 +++---- tests/lib/smf/src/test_lib_hierarchical_smf.c | 12 ++--- 8 files changed, 115 insertions(+), 99 deletions(-) diff --git a/doc/services/smf/index.rst b/doc/services/smf/index.rst index ad15393120f32f..169ee507ec4b4f 100644 --- a/doc/services/smf/index.rst +++ b/doc/services/smf/index.rst @@ -47,12 +47,6 @@ The following macro can be used for easy state creation: * :c:macro:`SMF_CREATE_STATE` Create a state -.. note:: The :c:macro:`SMF_CREATE_STATE` macro takes an additional parameter - for the parent state when :kconfig:option:`CONFIG_SMF_ANCESTOR_SUPPORT` is - enabled . The :c:macro:`SMF_CREATE_STATE` macro takes two additional - parameters for the parent state and initial transition when the - :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION` option is enabled. - State Machine Creation ====================== @@ -62,9 +56,9 @@ enum. For example, the following creates three flat states:: enum demo_state { S0, S1, S2 }; const struct smf_state demo_states[] = { - [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit), - [S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit), - [S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit) + [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit, NULL, NULL), + [S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit, NULL, NULL), + [S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit, NULL, NULL) }; And this example creates three hierarchical states:: @@ -72,9 +66,9 @@ And this example creates three hierarchical states:: enum demo_state { S0, S1, S2 }; const struct smf_state demo_states[] = { - [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit, parent_s0), - [S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit, parent_s12), - [S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit, parent_s12) + [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit, parent_s0, NULL), + [S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit, parent_s12, NULL), + [S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit, parent_s12, NULL) }; @@ -211,11 +205,11 @@ Code:: /* Populate state table */ static const struct smf_state demo_states[] = { - [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit), + [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit, NULL, NULL), /* State S1 does not have an entry action */ - [S1] = SMF_CREATE_STATE(NULL, s1_run, s1_exit), + [S1] = SMF_CREATE_STATE(NULL, s1_run, s1_exit, NULL, NULL), /* State S2 does not have an exit action */ - [S2] = SMF_CREATE_STATE(s2_entry, s2_run, NULL), + [S2] = SMF_CREATE_STATE(s2_entry, s2_run, NULL, NULL, NULL), }; int main(void) @@ -314,12 +308,12 @@ Code:: /* Populate state table */ static const struct smf_state demo_states[] = { /* Parent state does not have a run action */ - [PARENT] = SMF_CREATE_STATE(parent_entry, NULL, parent_exit, NULL), + [PARENT] = SMF_CREATE_STATE(parent_entry, NULL, parent_exit, NULL, NULL), /* Child states do not have entry or exit actions */ - [S0] = SMF_CREATE_STATE(NULL, s0_run, NULL, &demo_states[PARENT]), - [S1] = SMF_CREATE_STATE(NULL, s1_run, NULL, &demo_states[PARENT]), + [S0] = SMF_CREATE_STATE(NULL, s0_run, NULL, &demo_states[PARENT], NULL), + [S1] = SMF_CREATE_STATE(NULL, s1_run, NULL, &demo_states[PARENT], NULL), /* State S2 do ot have entry or exit actions and no parent */ - [S2] = SMF_CREATE_STATE(NULL, s2_run, NULL, NULL), + [S2] = SMF_CREATE_STATE(NULL, s2_run, NULL, NULL, NULL), }; int main(void) @@ -445,8 +439,8 @@ Code:: /* Populate state table */ static const struct smf_state demo_states[] = { - [S0] = SMF_CREATE_STATE(s0_entry, s0_run, NULL), - [S1] = SMF_CREATE_STATE(s1_entry, s1_run, NULL), + [S0] = SMF_CREATE_STATE(s0_entry, s0_run, NULL, NULL, NULL), + [S1] = SMF_CREATE_STATE(s1_entry, s1_run, NULL, NULL, NULL), }; void button_pressed(const struct device *dev, diff --git a/include/zephyr/smf.h b/include/zephyr/smf.h index c7a2c4fbff4add..ba0191272648b9 100644 --- a/include/zephyr/smf.h +++ b/include/zephyr/smf.h @@ -13,6 +13,8 @@ #ifndef ZEPHYR_INCLUDE_SMF_H_ #define ZEPHYR_INCLUDE_SMF_H_ +#include + /** * @brief State Machine Framework API * @defgroup smf State Machine Framework API @@ -20,24 +22,6 @@ * @{ */ -#ifdef CONFIG_SMF_ANCESTOR_SUPPORT -/** - * @brief Macro to create a hierarchical state. - * - * @param _entry State entry function - * @param _run State run function - * @param _exit State exit function - * @param _parent State parent object or NULL - */ -#ifndef CONFIG_SMF_INITIAL_TRANSITION -#define SMF_CREATE_STATE(_entry, _run, _exit, _parent) \ -{ \ - .entry = _entry, \ - .run = _run, \ - .exit = _exit, \ - .parent = _parent \ -} -#else /** * @brief Macro to create a hierarchical state. * @@ -47,33 +31,14 @@ * @param _parent State parent object or NULL * @param _initial State initial transition object or NULL */ -#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ -{ \ - .entry = _entry, \ - .run = _run, \ - .exit = _exit, \ - .parent = _parent, \ - .initial = _initial \ +#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ +{ \ + .entry = _entry, \ + .run = _run, \ + .exit = _exit, \ + IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \ + IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \ } -#endif /* CONFIG_SMF_INITIAL_TRANSITION */ - -#else - -/** - * @brief Macro to create a flat state. - * - * @param _entry State entry function - * @param _run State run function - * @param _exit State exit function - */ -#define SMF_CREATE_STATE(_entry, _run, _exit) \ -{ \ - .entry = _entry, \ - .run = _run, \ - .exit = _exit \ -} - -#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ /** * @brief Macro to cast user defined object to state machine diff --git a/subsys/usb/usb_c/usbc_pe_common.c b/subsys/usb/usb_c/usbc_pe_common.c index cc59cecbadc8f8..de29264d5d5090 100644 --- a/subsys/usb/usb_c/usbc_pe_common.c +++ b/subsys/usb/usb_c/usbc_pe_common.c @@ -1251,12 +1251,14 @@ static const struct smf_state pe_states[PE_STATE_COUNT] = { NULL, pe_sender_response_run, pe_sender_response_exit, + NULL, NULL), #ifdef CONFIG_USBC_CSM_SOURCE_ONLY [PE_SRC_HARD_RESET_PARENT] = SMF_CREATE_STATE( pe_src_hard_reset_parent_entry, pe_src_hard_reset_parent_run, pe_src_hard_reset_parent_exit, + NULL, NULL), #endif #ifdef CONFIG_USBC_CSM_SINK_ONLY @@ -1264,148 +1266,177 @@ static const struct smf_state pe_states[PE_STATE_COUNT] = { pe_snk_startup_entry, pe_snk_startup_run, NULL, + NULL, NULL), [PE_SNK_DISCOVERY] = SMF_CREATE_STATE( pe_snk_discovery_entry, pe_snk_discovery_run, NULL, + NULL, NULL), [PE_SNK_WAIT_FOR_CAPABILITIES] = SMF_CREATE_STATE( pe_snk_wait_for_capabilities_entry, pe_snk_wait_for_capabilities_run, pe_snk_wait_for_capabilities_exit, + NULL, NULL), [PE_SNK_EVALUATE_CAPABILITY] = SMF_CREATE_STATE( pe_snk_evaluate_capability_entry, NULL, NULL, + NULL, NULL), [PE_SNK_SELECT_CAPABILITY] = SMF_CREATE_STATE( pe_snk_select_capability_entry, pe_snk_select_capability_run, NULL, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_SNK_READY] = SMF_CREATE_STATE( pe_snk_ready_entry, pe_snk_ready_run, pe_snk_ready_exit, + NULL, NULL), [PE_SNK_HARD_RESET] = SMF_CREATE_STATE( pe_snk_hard_reset_entry, pe_snk_hard_reset_run, NULL, + NULL, NULL), [PE_SNK_TRANSITION_TO_DEFAULT] = SMF_CREATE_STATE( pe_snk_transition_to_default_entry, pe_snk_transition_to_default_run, NULL, + NULL, NULL), [PE_SNK_GIVE_SINK_CAP] = SMF_CREATE_STATE( pe_snk_give_sink_cap_entry, pe_snk_give_sink_cap_run, NULL, + NULL, NULL), [PE_SNK_GET_SOURCE_CAP] = SMF_CREATE_STATE( pe_snk_get_source_cap_entry, pe_snk_get_source_cap_run, NULL, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_SNK_TRANSITION_SINK] = SMF_CREATE_STATE( pe_snk_transition_sink_entry, pe_snk_transition_sink_run, pe_snk_transition_sink_exit, + NULL, NULL), #else [PE_SRC_STARTUP] = SMF_CREATE_STATE( pe_src_startup_entry, pe_src_startup_run, NULL, + NULL, NULL), [PE_SRC_DISCOVERY] = SMF_CREATE_STATE( pe_src_discovery_entry, pe_src_discovery_run, pe_src_discovery_exit, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_SRC_SEND_CAPABILITIES] = SMF_CREATE_STATE( pe_src_send_capabilities_entry, pe_src_send_capabilities_run, NULL, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_SRC_NEGOTIATE_CAPABILITY] = SMF_CREATE_STATE( pe_src_negotiate_capability_entry, NULL, NULL, + NULL, NULL), [PE_SRC_CAPABILITY_RESPONSE] = SMF_CREATE_STATE( pe_src_capability_response_entry, pe_src_capability_response_run, NULL, + NULL, NULL), [PE_SRC_TRANSITION_SUPPLY] = SMF_CREATE_STATE( pe_src_transition_supply_entry, pe_src_transition_supply_run, pe_src_transition_supply_exit, + NULL, NULL), [PE_SRC_READY] = SMF_CREATE_STATE( pe_src_ready_entry, pe_src_ready_run, pe_src_ready_exit, + NULL, NULL), [PE_SRC_TRANSITION_TO_DEFAULT] = SMF_CREATE_STATE( pe_src_transition_to_default_entry, pe_src_transition_to_default_run, pe_src_transition_to_default_exit, + NULL, NULL), [PE_SRC_HARD_RESET_RECEIVED] = SMF_CREATE_STATE( NULL, NULL, NULL, - &pe_states[PE_SRC_HARD_RESET_PARENT]), + &pe_states[PE_SRC_HARD_RESET_PARENT], + NULL), [PE_SRC_HARD_RESET] = SMF_CREATE_STATE( pe_src_hard_reset_entry, NULL, NULL, - &pe_states[PE_SRC_HARD_RESET_PARENT]), + &pe_states[PE_SRC_HARD_RESET_PARENT], + NULL), #endif [PE_GET_SINK_CAP] = SMF_CREATE_STATE( pe_get_sink_cap_entry, pe_get_sink_cap_run, NULL, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_SEND_SOFT_RESET] = SMF_CREATE_STATE( pe_send_soft_reset_entry, pe_send_soft_reset_run, NULL, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_SOFT_RESET] = SMF_CREATE_STATE( pe_soft_reset_entry, pe_soft_reset_run, NULL, + NULL, NULL), [PE_SEND_NOT_SUPPORTED] = SMF_CREATE_STATE( pe_send_not_supported_entry, pe_send_not_supported_run, NULL, + NULL, NULL), [PE_DRS_EVALUATE_SWAP] = SMF_CREATE_STATE( pe_drs_evaluate_swap_entry, pe_drs_evaluate_swap_run, NULL, + NULL, NULL), [PE_DRS_SEND_SWAP] = SMF_CREATE_STATE( pe_drs_send_swap_entry, pe_drs_send_swap_run, NULL, - &pe_states[PE_SENDER_RESPONSE_PARENT]), + &pe_states[PE_SENDER_RESPONSE_PARENT], + NULL), [PE_CHUNK_RECEIVED] = SMF_CREATE_STATE( pe_chunk_received_entry, pe_chunk_received_run, NULL, + NULL, NULL), [PE_SUSPEND] = SMF_CREATE_STATE( pe_suspend_entry, pe_suspend_run, NULL, + NULL, NULL), }; BUILD_ASSERT(ARRAY_SIZE(pe_states) == PE_STATE_COUNT); diff --git a/subsys/usb/usb_c/usbc_prl.c b/subsys/usb/usb_c/usbc_prl.c index ca0465bac6d2da..975709c7a24963 100644 --- a/subsys/usb/usb_c/usbc_prl.c +++ b/subsys/usb/usb_c/usbc_prl.c @@ -1265,37 +1265,44 @@ static const struct smf_state prl_tx_states[PRL_TX_STATE_COUNT] = { prl_tx_phy_layer_reset_entry, NULL, NULL, + NULL, NULL), [PRL_TX_WAIT_FOR_MESSAGE_REQUEST] = SMF_CREATE_STATE( prl_tx_wait_for_message_request_entry, prl_tx_wait_for_message_request_run, NULL, + NULL, NULL), [PRL_TX_LAYER_RESET_FOR_TRANSMIT] = SMF_CREATE_STATE( prl_tx_layer_reset_for_transmit_entry, NULL, NULL, + NULL, NULL), [PRL_TX_WAIT_FOR_PHY_RESPONSE] = SMF_CREATE_STATE( prl_tx_wait_for_phy_response_entry, prl_tx_wait_for_phy_response_run, prl_tx_wait_for_phy_response_exit, + NULL, NULL), [PRL_TX_SUSPEND] = SMF_CREATE_STATE( prl_tx_suspend_entry, prl_tx_suspend_run, NULL, + NULL, NULL), #ifdef CONFIG_USBC_CSM_SINK_ONLY [PRL_TX_SNK_START_AMS] = SMF_CREATE_STATE( prl_tx_snk_start_ams_entry, prl_tx_snk_start_ams_run, NULL, + NULL, NULL), [PRL_TX_SNK_PENDING] = SMF_CREATE_STATE( prl_tx_snk_pending_entry, prl_tx_snk_pending_run, NULL, + NULL, NULL), #endif #ifdef CONFIG_USBC_CSM_SOURCE_ONLY @@ -1303,11 +1310,13 @@ static const struct smf_state prl_tx_states[PRL_TX_STATE_COUNT] = { prl_tx_src_source_tx_entry, prl_tx_src_source_tx_run, NULL, + NULL, NULL), [PRL_TX_SRC_PENDING] = SMF_CREATE_STATE( prl_tx_src_pending_entry, prl_tx_src_pending_run, prl_tx_src_pending_exit, + NULL, NULL), #endif }; @@ -1321,26 +1330,31 @@ static const struct smf_state prl_hr_states[PRL_HR_STATE_COUNT] = { prl_hr_wait_for_request_entry, prl_hr_wait_for_request_run, NULL, + NULL, NULL), [PRL_HR_RESET_LAYER] = SMF_CREATE_STATE( prl_hr_reset_layer_entry, NULL, NULL, + NULL, NULL), [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE] = SMF_CREATE_STATE( prl_hr_wait_for_phy_hard_reset_complete_entry, prl_hr_wait_for_phy_hard_reset_complete_run, prl_hr_wait_for_phy_hard_reset_complete_exit, + NULL, NULL), [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] = SMF_CREATE_STATE( prl_hr_wait_for_pe_hard_reset_complete_entry, prl_hr_wait_for_pe_hard_reset_complete_run, NULL, + NULL, NULL), [PRL_HR_SUSPEND] = SMF_CREATE_STATE( prl_hr_suspend_entry, prl_hr_suspend_run, NULL, + NULL, NULL), }; BUILD_ASSERT(ARRAY_SIZE(prl_hr_states) == PRL_HR_STATE_COUNT); diff --git a/subsys/usb/usb_c/usbc_tc_common.c b/subsys/usb/usb_c/usbc_tc_common.c index e4a58a24899bd1..43d6c9899d3654 100644 --- a/subsys/usb/usb_c/usbc_tc_common.c +++ b/subsys/usb/usb_c/usbc_tc_common.c @@ -326,18 +326,21 @@ static const struct smf_state tc_states[TC_STATE_COUNT] = { tc_cc_open_entry, NULL, NULL, + NULL, NULL), #ifdef CONFIG_USBC_CSM_SINK_ONLY [TC_CC_RD_SUPER_STATE] = SMF_CREATE_STATE( tc_cc_rd_entry, NULL, NULL, + NULL, NULL), #else [TC_CC_RP_SUPER_STATE] = SMF_CREATE_STATE( tc_cc_rp_entry, NULL, NULL, + NULL, NULL), #endif /* Normal States */ @@ -346,48 +349,57 @@ static const struct smf_state tc_states[TC_STATE_COUNT] = { tc_unattached_snk_entry, tc_unattached_snk_run, NULL, - &tc_states[TC_CC_RD_SUPER_STATE]), + &tc_states[TC_CC_RD_SUPER_STATE], + NULL), [TC_ATTACH_WAIT_SNK_STATE] = SMF_CREATE_STATE( tc_attach_wait_snk_entry, tc_attach_wait_snk_run, tc_attach_wait_snk_exit, - &tc_states[TC_CC_RD_SUPER_STATE]), + &tc_states[TC_CC_RD_SUPER_STATE], + NULL), [TC_ATTACHED_SNK_STATE] = SMF_CREATE_STATE( tc_attached_snk_entry, tc_attached_snk_run, tc_attached_snk_exit, + NULL, NULL), #else [TC_UNATTACHED_SRC_STATE] = SMF_CREATE_STATE( tc_unattached_src_entry, tc_unattached_src_run, NULL, - &tc_states[TC_CC_RP_SUPER_STATE]), + &tc_states[TC_CC_RP_SUPER_STATE], + NULL), [TC_UNATTACHED_WAIT_SRC_STATE] = SMF_CREATE_STATE( tc_unattached_wait_src_entry, tc_unattached_wait_src_run, tc_unattached_wait_src_exit, + NULL, NULL), [TC_ATTACH_WAIT_SRC_STATE] = SMF_CREATE_STATE( tc_attach_wait_src_entry, tc_attach_wait_src_run, tc_attach_wait_src_exit, - &tc_states[TC_CC_RP_SUPER_STATE]), + &tc_states[TC_CC_RP_SUPER_STATE], + NULL), [TC_ATTACHED_SRC_STATE] = SMF_CREATE_STATE( tc_attached_src_entry, tc_attached_src_run, tc_attached_src_exit, + NULL, NULL), #endif [TC_DISABLED_STATE] = SMF_CREATE_STATE( tc_disabled_entry, tc_disabled_run, NULL, - &tc_states[TC_CC_OPEN_SUPER_STATE]), + &tc_states[TC_CC_OPEN_SUPER_STATE], + NULL), [TC_ERROR_RECOVERY_STATE] = SMF_CREATE_STATE( tc_error_recovery_entry, tc_error_recovery_run, NULL, - &tc_states[TC_CC_OPEN_SUPER_STATE]), + &tc_states[TC_CC_OPEN_SUPER_STATE], + NULL), }; BUILD_ASSERT(ARRAY_SIZE(tc_states) == TC_STATE_COUNT); diff --git a/tests/lib/smf/src/test_lib_flat_smf.c b/tests/lib/smf/src/test_lib_flat_smf.c index 2a66fb85943bf8..3824565986e6d4 100644 --- a/tests/lib/smf/src/test_lib_flat_smf.c +++ b/tests/lib/smf/src/test_lib_flat_smf.c @@ -213,10 +213,10 @@ static void state_d_exit(void *obj) } static const struct smf_state test_states[] = { - [STATE_A] = SMF_CREATE_STATE(state_a_entry, state_a_run, state_a_exit), - [STATE_B] = SMF_CREATE_STATE(state_b_entry, state_b_run, state_b_exit), - [STATE_C] = SMF_CREATE_STATE(state_c_entry, state_c_run, state_c_exit), - [STATE_D] = SMF_CREATE_STATE(state_d_entry, state_d_run, state_d_exit), + [STATE_A] = SMF_CREATE_STATE(state_a_entry, state_a_run, state_a_exit, NULL, NULL), + [STATE_B] = SMF_CREATE_STATE(state_b_entry, state_b_run, state_b_exit, NULL, NULL), + [STATE_C] = SMF_CREATE_STATE(state_c_entry, state_c_run, state_c_exit, NULL, NULL), + [STATE_D] = SMF_CREATE_STATE(state_d_entry, state_d_run, state_d_exit, NULL, NULL), }; ZTEST(smf_tests, test_smf_flat) diff --git a/tests/lib/smf/src/test_lib_hierarchical_5_ancestor_smf.c b/tests/lib/smf/src/test_lib_hierarchical_5_ancestor_smf.c index b50221e67d3fc4..bd62e9bb110bbd 100644 --- a/tests/lib/smf/src/test_lib_hierarchical_5_ancestor_smf.c +++ b/tests/lib/smf/src/test_lib_hierarchical_5_ancestor_smf.c @@ -412,15 +412,15 @@ static void d_entry(void *obj) } static const struct smf_state test_states[] = { - [P05] SMF_CREATE_STATE(p05_entry, p05_run, p05_exit, NULL), - [P04] SMF_CREATE_STATE(p04_entry, p04_run, p04_exit, &test_states[P05]), - [P03] SMF_CREATE_STATE(p03_entry, p03_run, p03_exit, &test_states[P04]), - [P02] SMF_CREATE_STATE(p02_entry, p02_run, p02_exit, &test_states[P03]), - [P01] SMF_CREATE_STATE(p01_entry, p01_run, p01_exit, &test_states[P02]), - [A] = SMF_CREATE_STATE(a_entry, a_run, a_exit, &test_states[P01]), - [B] = SMF_CREATE_STATE(b_entry, b_run, b_exit, &test_states[P01]), - [C] = SMF_CREATE_STATE(c_entry, c_run, c_exit, NULL), - [D] = SMF_CREATE_STATE(d_entry, NULL, NULL, NULL), + [P05] SMF_CREATE_STATE(p05_entry, p05_run, p05_exit, NULL, NULL), + [P04] SMF_CREATE_STATE(p04_entry, p04_run, p04_exit, &test_states[P05], NULL), + [P03] SMF_CREATE_STATE(p03_entry, p03_run, p03_exit, &test_states[P04], NULL), + [P02] SMF_CREATE_STATE(p02_entry, p02_run, p02_exit, &test_states[P03], NULL), + [P01] SMF_CREATE_STATE(p01_entry, p01_run, p01_exit, &test_states[P02], NULL), + [A] = SMF_CREATE_STATE(a_entry, a_run, a_exit, &test_states[P01], NULL), + [B] = SMF_CREATE_STATE(b_entry, b_run, b_exit, &test_states[P01], NULL), + [C] = SMF_CREATE_STATE(c_entry, c_run, c_exit, NULL, NULL), + [D] = SMF_CREATE_STATE(d_entry, NULL, NULL, NULL, NULL), }; ZTEST(smf_tests, test_smf_hierarchical_5_ancestors) diff --git a/tests/lib/smf/src/test_lib_hierarchical_smf.c b/tests/lib/smf/src/test_lib_hierarchical_smf.c index cf3b4845d31a29..2070ffb1a1661c 100644 --- a/tests/lib/smf/src/test_lib_hierarchical_smf.c +++ b/tests/lib/smf/src/test_lib_hierarchical_smf.c @@ -338,17 +338,17 @@ static void state_d_exit(void *obj) static const struct smf_state test_states[] = { [PARENT_AB] = SMF_CREATE_STATE(parent_ab_entry, parent_ab_run, - parent_ab_exit, NULL), + parent_ab_exit, NULL, NULL), [PARENT_C] = SMF_CREATE_STATE(parent_c_entry, parent_c_run, - parent_c_exit, NULL), + parent_c_exit, NULL, NULL), [STATE_A] = SMF_CREATE_STATE(state_a_entry, state_a_run, state_a_exit, - &test_states[PARENT_AB]), + &test_states[PARENT_AB], NULL), [STATE_B] = SMF_CREATE_STATE(state_b_entry, state_b_run, state_b_exit, - &test_states[PARENT_AB]), + &test_states[PARENT_AB], NULL), [STATE_C] = SMF_CREATE_STATE(state_c_entry, state_c_run, state_c_exit, - &test_states[PARENT_C]), + &test_states[PARENT_C], NULL), [STATE_D] = SMF_CREATE_STATE(state_d_entry, state_d_run, state_d_exit, - NULL), + NULL, NULL), }; ZTEST(smf_tests, test_smf_hierarchical) From a8d0229ffd401f72fdc8f1766e477e2725017aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0262/1389] doc: releases: migration guide: 3.7: change of SMF_CREATE_STATE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mention change of SMF_CREATE_STATE(). Signed-off-by: Fin Maaß --- doc/releases/migration-guide-3.7.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index bd1de0efcce7a7..07d2585fa1687b 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -379,6 +379,14 @@ Modem Shell ===== +State Machine Framework +======================= + +* The :c:macro:`SMF_CREATE_STATE` macro now always takes 5 arguments. The amount of arguments is + now independent of the values of :kconfig:option:`CONFIG_SMF_ANCESTOR_SUPPORT` and + :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION`. If the additional arguments are not used, they + have to be set to ``NULL``. (:github:`71250`) + ZBus ==== From 20bd5d834e4bc837a74cbfc1d2775f22c0b67ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0263/1389] doc: releases: release notes: 3.7: change of SMF_CREATE_STATE() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mention change of SMF_CREATE_STATE(). Signed-off-by: Fin Maaß --- doc/releases/release-notes-3.7.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index fd74dc40f8f156..bc60d8f3d2c400 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -329,6 +329,10 @@ Libraries / Subsystems * SD +* State Machine Framework + + * The :c:macro:`SMF_CREATE_STATE` macro now always takes 5 arguments. + * Storage * FAT FS: It is now possible to expose file system formatting functionality for FAT without also From f24e70d76950567df666c3887c08eedbca8b504d Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0264/1389] soc: arm: ambiq: apollo3: Add support for Apollo3 Blue Plus SoC Add all required parts (new SoC family/series, device tree) for the Ambiq Apollo3 Blue Plus SoC. Signed-off-by: Hao Luo --- MAINTAINERS.yml | 1 + dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 186 ++++++++++++++++++ modules/hal_ambiq/Kconfig | 2 +- soc/ambiq/apollo3x/CMakeLists.txt | 9 + soc/ambiq/apollo3x/Kconfig | 12 ++ soc/ambiq/apollo3x/Kconfig.defconfig | 9 + .../apollo3x/Kconfig.defconfig.apollo3p_blue | 10 + soc/ambiq/apollo3x/Kconfig.soc | 28 +++ soc/ambiq/apollo3x/soc.c | 23 +++ soc/ambiq/apollo3x/soc.h | 16 ++ soc/ambiq/soc.yml | 4 + west.yml | 2 +- 12 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 dts/arm/ambiq/ambiq_apollo3p_blue.dtsi create mode 100644 soc/ambiq/apollo3x/CMakeLists.txt create mode 100644 soc/ambiq/apollo3x/Kconfig create mode 100644 soc/ambiq/apollo3x/Kconfig.defconfig create mode 100644 soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue create mode 100644 soc/ambiq/apollo3x/Kconfig.soc create mode 100644 soc/ambiq/apollo3x/soc.c create mode 100644 soc/ambiq/apollo3x/soc.h diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 3f5c638347c443..dcd454fdf068d7 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -244,6 +244,7 @@ Ambiq Platforms: status: odd fixes collaborators: - aaronyegx + - HaoLuo - RichardSWheatley files: - soc/ambiq/ diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi new file mode 100644 index 00000000000000..f0ed2be9a6e486 --- /dev/null +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include + +/ { + clocks { + uartclk: apb-pclk { + compatible = "fixed-clock"; + clock-frequency = ; + #clock-cells = <0>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + /* Flash region */ + flash0: flash@C000 { + compatible = "soc-nv-flash"; + reg = <0x0000C000 0x1F4000>; + }; + + /* TCM */ + tcm: tcm@10000000 { + compatible = "zephyr,memory-region"; + reg = <0x10000000 0x10000>; + zephyr,memory-region = "ITCM"; + }; + + /* SRAM */ + sram0: memory@10010000 { + compatible = "mmio-sram"; + reg = <0x10010000 0xB0000>; + }; + + soc { + compatible = "ambiq,apollo3p-blue", "ambiq,apollo3x", "simple-bus"; + + pwrcfg: pwrcfg@40021000 { + compatible = "ambiq,pwrctrl"; + reg = <0x40021000 0x400>; + #pwrcfg-cells = <2>; + }; + + stimer0: stimer@40008140 { + compatible = "ambiq,stimer"; + reg = <0x40008140 0x80>; + interrupts = <23 0>; + status = "okay"; + }; + + counter0: counter@40008000 { + compatible = "ambiq,counter"; + reg = <0x40008000 0x80>; + interrupts = <14 0>; + status = "disabled"; + }; + + uart0: uart@4001c000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001c000 0x1000>; + interrupts = <15 0>; + interrupt-names = "UART0"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x8 0x80>; + }; + + uart1: uart@4001d000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001d000 0x1000>; + interrupts = <16 0>; + interrupt-names = "UART1"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x8 0x100>; + }; + + iom0: iom@50004000 { + reg = <0x50004000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <6 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; + }; + + iom1: iom@50005000 { + reg = <0x50005000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <7 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; + }; + + iom2: iom@50006000 { + reg = <0x50006000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; + }; + + iom3: iom@50007000 { + reg = <0x50007000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <9 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; + }; + + iom4: iom@50008000 { + reg = <0x50008000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <10 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; + }; + + iom5: iom@50009000 { + reg = <0x50009000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <11 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x40>; + }; + + mspi0: spi@50014000 { + compatible = "ambiq,mspi"; + reg = <0x50014000 0x400>; + interrupts = <20 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x800>; + }; + + mspi1: spi@50015000 { + compatible = "ambiq,mspi"; + reg = <0x50015000 0x400>; + interrupts = <32 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x1000>; + }; + + mspi2: spi@50016000 { + compatible = "ambiq,mspi"; + reg = <0x50016000 0x400>; + interrupts = <33 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x2000>; + }; + + wdt0: watchdog@40024000 { + compatible = "ambiq,watchdog"; + reg = <0x40024000 0x400>; + interrupts = <1 0>; + clock-frequency = <16>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index 28c19e9a587327..24aaf1189cd758 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -4,7 +4,7 @@ config AMBIQ_HAL bool "Ambiq HAL drivers support" - depends on SOC_SERIES_APOLLO4X + depends on SOC_SERIES_APOLLO4X || SOC_SERIES_APOLLO3X help Use the Ambiq HAL diff --git a/soc/ambiq/apollo3x/CMakeLists.txt b/soc/ambiq/apollo3x/CMakeLists.txt new file mode 100644 index 00000000000000..2003b1a8df5a6b --- /dev/null +++ b/soc/ambiq/apollo3x/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_sources(soc.c) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/ambiq/apollo3x/Kconfig b/soc/ambiq/apollo3x/Kconfig new file mode 100644 index 00000000000000..de93bd91e90b7b --- /dev/null +++ b/soc/ambiq/apollo3x/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +config SOC_SERIES_APOLLO3X + select ARM + select CPU_CORTEX_M4 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_FPU + select CPU_HAS_ARM_MPU + select HAS_SWO + select AMBIQ_HAL diff --git a/soc/ambiq/apollo3x/Kconfig.defconfig b/soc/ambiq/apollo3x/Kconfig.defconfig new file mode 100644 index 00000000000000..abac3c9c75d37a --- /dev/null +++ b/soc/ambiq/apollo3x/Kconfig.defconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +if SOC_SERIES_APOLLO3X + +rsource "Kconfig.defconfig.apollo3*" + +endif # SOC_SERIES_APOLLO3X diff --git a/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue new file mode 100644 index 00000000000000..8484dfad347529 --- /dev/null +++ b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +if SOC_APOLLO3P_BLUE + +config NUM_IRQS + default 33 + +endif # SOC_APOLLO3P_BLUE diff --git a/soc/ambiq/apollo3x/Kconfig.soc b/soc/ambiq/apollo3x/Kconfig.soc new file mode 100644 index 00000000000000..6a6814179934af --- /dev/null +++ b/soc/ambiq/apollo3x/Kconfig.soc @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +config SOC_SERIES_APOLLO3X + bool + select SOC_FAMILY_AMBIQ + help + Apollo3 Series MCU + +config SOC_APOLLO3P_BLUE + bool + select SOC_SERIES_APOLLO3X + help + Apollo3P Blue + +config SOC_APOLLO3_BLUE + bool + select SOC_SERIES_APOLLO3X + help + Apollo3 Blue + +config SOC_SERIES + default "apollo3x" if SOC_SERIES_APOLLO3X + +config SOC + default "apollo3_blue" if SOC_APOLLO3_BLUE + default "apollo3p_blue" if SOC_APOLLO3P_BLUE diff --git a/soc/ambiq/apollo3x/soc.c b/soc/ambiq/apollo3x/soc.c new file mode 100644 index 00000000000000..d10b4a5dcfb77c --- /dev/null +++ b/soc/ambiq/apollo3x/soc.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +static int arm_apollo3_init(void) +{ + + /* Initialize for low power in the power control block */ + am_hal_pwrctrl_low_power_init(); + + /* Disable the RTC. */ + am_hal_rtc_osc_disable(); + + return 0; +} + +SYS_INIT(arm_apollo3_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/ambiq/apollo3x/soc.h b/soc/ambiq/apollo3x/soc.h new file mode 100644 index 00000000000000..ae9b7e597dfceb --- /dev/null +++ b/soc/ambiq/apollo3x/soc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SOC_H__ +#define __SOC_H__ + +#if defined(CONFIG_SOC_APOLLO3P_BLUE) +#include +#elif defined(CONFIG_SOC_APOLLO3_BLUE) +#include +#endif + +#endif /* __SOC_H__ */ diff --git a/soc/ambiq/soc.yml b/soc/ambiq/soc.yml index 2fd2f06529fe81..b0a471d1fd5587 100644 --- a/soc/ambiq/soc.yml +++ b/soc/ambiq/soc.yml @@ -5,3 +5,7 @@ family: socs: - name: apollo4p - name: apollo4p_blue + - name: apollo3x + socs: + - name: apollo3_blue + - name: apollo3p_blue diff --git a/west.yml b/west.yml index f3ac97be4f930d..ff8a6d79e60131 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: ff4ca358d730536addf336c40c3faa4ebf1df00a + revision: 326d061d85c4384ff7811ab04f3ed3c66d436fb1 path: modules/hal/ambiq groups: - hal From 3f03998b73fdb71b3549b169f044c1c089ae6c54 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0265/1389] soc: arm: ambiq: apollo3: Add support for Apollo3 Blue SoC Add all required parts (new SoC family/series, device tree) for the Ambiq Apollo3 Blue SoC. Signed-off-by: Hao Luo --- dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 166 ++++++++++++++++++ .../apollo3x/Kconfig.defconfig.apollo3_blue | 10 ++ 2 files changed, 176 insertions(+) create mode 100644 dts/arm/ambiq/ambiq_apollo3_blue.dtsi create mode 100644 soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi new file mode 100644 index 00000000000000..143dd46dbd1bef --- /dev/null +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include + +/ { + clocks { + uartclk: apb-pclk { + compatible = "fixed-clock"; + clock-frequency = ; + #clock-cells = <0>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + /* Flash region */ + flash0: flash@C000 { + compatible = "soc-nv-flash"; + reg = <0x0000C000 0xF4000>; + }; + + /* TCM */ + tcm: tcm@10000000 { + compatible = "zephyr,memory-region"; + reg = <0x10000000 0x10000>; + zephyr,memory-region = "ITCM"; + }; + + /* SRAM */ + sram0: memory@10010000 { + compatible = "mmio-sram"; + reg = <0x10010000 0x50000>; + }; + + soc { + compatible = "ambiq,apollo3-blue", "ambiq,apollo3x", "simple-bus"; + + pwrcfg: pwrcfg@40021000 { + compatible = "ambiq,pwrctrl"; + reg = <0x40021000 0x400>; + #pwrcfg-cells = <2>; + }; + + stimer0: stimer@40008140 { + compatible = "ambiq,stimer"; + reg = <0x40008140 0x80>; + interrupts = <23 0>; + status = "okay"; + }; + + counter0: counter@40008000 { + compatible = "ambiq,counter"; + reg = <0x40008000 0x80>; + interrupts = <14 0>; + status = "disabled"; + }; + + uart0: uart@4001c000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001c000 0x1000>; + interrupts = <15 0>; + interrupt-names = "UART0"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x8 0x80>; + }; + + uart1: uart@4001d000 { + compatible = "ambiq,uart", "arm,pl011"; + reg = <0x4001d000 0x1000>; + interrupts = <16 0>; + interrupt-names = "UART1"; + status = "disabled"; + clocks = <&uartclk>; + ambiq,pwrcfg = <&pwrcfg 0x8 0x100>; + }; + + iom0: iom@50004000 { + reg = <0x50004000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <6 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; + }; + + iom1: iom@50005000 { + reg = <0x50005000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <7 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; + }; + + iom2: iom@50006000 { + reg = <0x50006000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; + }; + + iom3: iom@50007000 { + reg = <0x50007000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <9 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; + }; + + iom4: iom@50008000 { + reg = <0x50008000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <10 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; + }; + + iom5: iom@50009000 { + reg = <0x50009000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <11 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x40>; + }; + + mspi0: spi@40020000 { + compatible = "ambiq,mspi"; + reg = <0x40020000 0x400>; + interrupts = <20 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x800>; + }; + + wdt0: watchdog@40024000 { + compatible = "ambiq,watchdog"; + reg = <0x40024000 0x400>; + interrupts = <1 0>; + clock-frequency = <16>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue new file mode 100644 index 00000000000000..c6c07932856c40 --- /dev/null +++ b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +if SOC_APOLLO3_BLUE + +config NUM_IRQS + default 31 + +endif # SOC_APOLLO3_BLUE From 6c0b373cbb5d46b197b8fb341abbe898d5fd7e22 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0266/1389] boards: Add support for the Ambiq Apollo3P EVB board This commit adds support for the Ambiq Apollo3P EVB board (AMA3B2EVB). Signed-off-by: Hao Luo --- .../ambiq/apollo3p_evb/Kconfig.apollo3p_evb | 6 + .../apollo3p_evb/apollo3p_evb-pinctrl.dtsi | 196 ++++++++++++++++++ boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 29 +++ boards/ambiq/apollo3p_evb/apollo3p_evb.yaml | 15 ++ .../ambiq/apollo3p_evb/apollo3p_evb_defconfig | 8 + boards/ambiq/apollo3p_evb/board.cmake | 6 + boards/ambiq/apollo3p_evb/board.yml | 5 + .../doc/apollo3-blue-plus-soc-eval-board.jpg | Bin 0 -> 52492 bytes boards/ambiq/apollo3p_evb/doc/index.rst | 102 +++++++++ 9 files changed, 367 insertions(+) create mode 100644 boards/ambiq/apollo3p_evb/Kconfig.apollo3p_evb create mode 100644 boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi create mode 100644 boards/ambiq/apollo3p_evb/apollo3p_evb.dts create mode 100644 boards/ambiq/apollo3p_evb/apollo3p_evb.yaml create mode 100644 boards/ambiq/apollo3p_evb/apollo3p_evb_defconfig create mode 100644 boards/ambiq/apollo3p_evb/board.cmake create mode 100644 boards/ambiq/apollo3p_evb/board.yml create mode 100644 boards/ambiq/apollo3p_evb/doc/apollo3-blue-plus-soc-eval-board.jpg create mode 100644 boards/ambiq/apollo3p_evb/doc/index.rst diff --git a/boards/ambiq/apollo3p_evb/Kconfig.apollo3p_evb b/boards/ambiq/apollo3p_evb/Kconfig.apollo3p_evb new file mode 100644 index 00000000000000..cda93708d30aaa --- /dev/null +++ b/boards/ambiq/apollo3p_evb/Kconfig.apollo3p_evb @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +config BOARD_APOLLO3P_EVB + select SOC_APOLLO3P_BLUE diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi b/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi new file mode 100644 index 00000000000000..5619b134ee9ea9 --- /dev/null +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c1_default: i2c1_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c2_default: i2c2_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c3_default: i2c3_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c4_default: i2c4_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c5_default: i2c5_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-mspi = <1>; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <0>; + }; + }; + spi1_default: spi1_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-mspi = <1>; + ambiq,iom-nce-module = <1>; + ambiq,iom-num = <1>; + }; + }; + spi2_default: spi2_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-mspi = <1>; + ambiq,iom-nce-module = <3>; + ambiq,iom-num = <2>; + }; + }; + spi3_default: spi3_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-mspi = <1>; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <3>; + }; + }; + spi4_default: spi4_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-mspi = <1>; + ambiq,iom-nce-module = <1>; + ambiq,iom-num = <4>; + }; + }; + spi5_default: spi5_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-mspi = <1>; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <5>; + }; + }; + + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-mspi = <0>; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <0>; + }; + }; + mspi1_default: mspi1_default{ + group1 { + pinmux = , + , + , + , + , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-mspi = <0>; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <1>; + }; + }; + mspi2_default: mspi2_default{ + group1 { + pinmux = , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-mspi = <0>; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <2>; + }; + }; +}; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts new file mode 100644 index 00000000000000..46894814dbe420 --- /dev/null +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -0,0 +1,29 @@ +/dts-v1/; +#include + +#include "apollo3p_evb-pinctrl.dtsi" + +/ { + model = "Ambiq Apollo3 Blue Plus evaluation board"; + compatible = "ambiq,apollo3p_evb"; + + chosen { + zephyr,itcm = &tcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-pipe = &uart0; + }; + + aliases { + watchdog0 = &wdt0; + }; +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml new file mode 100644 index 00000000000000..db00dbedcd647b --- /dev/null +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml @@ -0,0 +1,15 @@ +identifier: apollo3p_evb +name: Apollo3 Blue Plus EVB +type: mcu +arch: arm +ram: 768 +flash: 2000 +toolchain: + - zephyr + - gnuarmemb +supported: + - uart +testing: + ignore_tags: + - net +vendor: ambiq diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb_defconfig b/boards/ambiq/apollo3p_evb/apollo3p_evb_defconfig new file mode 100644 index 00000000000000..5f556803e527ab --- /dev/null +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/ambiq/apollo3p_evb/board.cmake b/boards/ambiq/apollo3p_evb/board.cmake new file mode 100644 index 00000000000000..d81e4cdc13d4d2 --- /dev/null +++ b/boards/ambiq/apollo3p_evb/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=AMA3B2KK-KBR" "--iface=swd" "--speed=1000") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/ambiq/apollo3p_evb/board.yml b/boards/ambiq/apollo3p_evb/board.yml new file mode 100644 index 00000000000000..507a85548b0907 --- /dev/null +++ b/boards/ambiq/apollo3p_evb/board.yml @@ -0,0 +1,5 @@ +board: + name: apollo3p_evb + vendor: ambiq + socs: + - name: apollo3p_blue diff --git a/boards/ambiq/apollo3p_evb/doc/apollo3-blue-plus-soc-eval-board.jpg b/boards/ambiq/apollo3p_evb/doc/apollo3-blue-plus-soc-eval-board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6aa0d0a7d5326d3ba78df8f38644f573be570c32 GIT binary patch literal 52492 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 }?DkWZUyo>l07$zwrj& zmsiH^G|}T(eXE+UAOdWg(Sqp%WWg4nr!VxB7=3<(%=vJDBhMWX(M%^0Z$vE?x4F`=h{w zDXErR$IOm>6^S&x7`J58DcLmd(>q?AKDF&Yp=aAMOYQKQ>hkx|`=m;qZLHvTY?|O~ zcq7NGMb@hE@}~y311p|PvVG+>Pq?%*KQZ@KLVHoe=}n<4SfBUC2k!&kiSl;VjVC1= zKEK|3N2c_d$daY1hi>t)&tY&2pW4tQ+*j-r%xIps_A=XDmX5XSHMKlE99UjHPMNE9 zsqh@*v)$F~5C3G>1l&F5^t3nXOs$LY>MQ+sZ_nNKXyL99ABE?7ak9m^3zx8%wJhY6 z@Cq_u_!Yh<%sp`yk=-j;Hw!{bte^BxGt!Rl-PM~D+n(|2B@_VL@5+BdAH1CLtoOj9 zM6W8IZ)pZ=^)_tSB43d8D@m&7=_%7~+UKQT=jusGxdD$DSb5~HQ``Klxq9a;N-E~u zDcLvu{ijJ!+HN~1@u>1^1sP1(ZqE6OXZ}(z=d~}3c(1IxEVxyr!!STd*3Cmp-Ll}h z%sfuzuJx&3x~{4Iv00gWF!8z)@cNyQa-*W=O{K{@R1$u5?Q~rhd&&Jj!>Tjm$XxtaDh_D)b)nu$B=jvvT~p zZr8~ld2@YF?>|`-e1JjfT8I!k!|Ka7Ld-q(B%cMIT=U2zOvz|k@}{=g{+vz)ta(RM zN|#J)O=}^x$BGuDtMXQFTK4zyrNo4aR;ycf-O~L(eqUL%DQv|Li(H2lI+;O!lQ{01 zX68*SuHydoW4q9456AL@L0ejTdLwKa*k|-SX1MNr%jW4apDZ8g$g3jTHIF_F44R|s zvtqf|p-l!g2Sh$^Pn`9&xV2&`XVCL$H}WjKeT_oc8bYQt&O0g9_PclQs(G_27Z>H_ zsCsoKY!?^T-OwJ;UsJvYNoe_^5N9@70(>Fw8C>9 zq;Rz_`rwy0-90^jo72|gf)9>6^Y)#T`RiXbz3bGuEh__O1x!TC>x2e#Ve-r(3+zmP zv?iO)TNE?x_L0o}D<=0g{bwlnSN{9DwcuI3X))7QthJlZdz`5>q5Au=!Z~GM*LCdg ze110M#SU`|vraYJX;x}Gf|mR^?YBsLeb2uyQ+_3Hym9sD><|CmR|UoI*|TG!)08Df zouYUXTJM@Mq@6C#%t{Guj1m~VmlNdTr0ytO9NL~SeZWL*J H`TsWo`O1Gt literal 0 HcmV?d00001 diff --git a/boards/ambiq/apollo3p_evb/doc/index.rst b/boards/ambiq/apollo3p_evb/doc/index.rst new file mode 100644 index 00000000000000..9d56556d69c55f --- /dev/null +++ b/boards/ambiq/apollo3p_evb/doc/index.rst @@ -0,0 +1,102 @@ +.. _apollo3p_evb: + +Ambiq Apollo3 Blue Plus EVB +########################### + +Apollo3 Blue Plus EVB is a board by Ambiq featuring their ultra-low power Apollo3 Blue Plus SoC. + +.. image:: ./apollo3-blue-plus-soc-eval-board.jpg + :align: center + :alt: Apollo3 Blue Plus EVB + +Hardware +******** + +- Apollo3 Blue Plus SoC with up to 96 MHz operating frequency +- ARM® Cortex® M4F core +- 16 kB 2-way Associative/Direct-Mapped Cache per core +- Up to 2 MB of flash memory for code/data +- Up to 768 KB of low leakage / low power RAM for code/data +- Integrated Bluetooth 5 Low-energy controller + +For more information about the Apollo3 Blue Plus SoC and Apollo3 Blue Plus EVB board: + +- `Apollo3 Blue Plus Website`_ +- `Apollo3 Blue Plus Datasheet`_ +- `Apollo3 Blue Plus EVB Website`_ + +Supported Features +================== + +The Apollo3 Blue Plus EVB board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| STIMER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +``boards/arm/apollo3p_evb/apollo3p_evb_defconfig``. + +Programming and Debugging +========================= + +Flashing an application +----------------------- + +Connect your device to your host computer using the JLINK USB port. +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application, then flash it to the device: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: apollo3p_evb + :goals: flash + +.. note:: + `west flash` requires `SEGGER J-Link software`_ and `pylink`_ Python module + to be installed on you host computer. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! apollo3p_evb + +.. _Apollo3 Blue Plus Website: + https://ambiq.com/apollo3-blue-plus/ + +.. _Apollo3 Blue Plus Datasheet: + https://contentportal.ambiq.com/documents/20123/388390/Apollo3-Blue-Plus-SoC-Datasheet.pdf + +.. _Apollo3 Blue Plus EVB Website: + https://www.ambiq.top/en/apollo3-blue-plus-soc-eval-board + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink + +.. _pylink: + https://github.com/Square/pylink From b9d33afb5a29212115a2a50b24a19b602054a496 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0267/1389] boards: Add support for the Ambiq Apollo3 EVB board This commit adds support for the Ambiq Apollo3 EVB board (AMA3B1EVB). Signed-off-by: Hao Luo --- boards/ambiq/apollo3_evb/Kconfig.apollo3_evb | 6 + .../apollo3_evb/apollo3_evb-pinctrl.dtsi | 151 ++++++++++++++++++ boards/ambiq/apollo3_evb/apollo3_evb.dts | 29 ++++ boards/ambiq/apollo3_evb/apollo3_evb.yaml | 15 ++ .../ambiq/apollo3_evb/apollo3_evb_defconfig | 8 + boards/ambiq/apollo3_evb/board.cmake | 6 + boards/ambiq/apollo3_evb/board.yml | 5 + .../doc/apollo3-blue-soc-eval-board.jpg | Bin 0 -> 52700 bytes boards/ambiq/apollo3_evb/doc/index.rst | 102 ++++++++++++ 9 files changed, 322 insertions(+) create mode 100644 boards/ambiq/apollo3_evb/Kconfig.apollo3_evb create mode 100644 boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi create mode 100644 boards/ambiq/apollo3_evb/apollo3_evb.dts create mode 100644 boards/ambiq/apollo3_evb/apollo3_evb.yaml create mode 100644 boards/ambiq/apollo3_evb/apollo3_evb_defconfig create mode 100644 boards/ambiq/apollo3_evb/board.cmake create mode 100644 boards/ambiq/apollo3_evb/board.yml create mode 100644 boards/ambiq/apollo3_evb/doc/apollo3-blue-soc-eval-board.jpg create mode 100644 boards/ambiq/apollo3_evb/doc/index.rst diff --git a/boards/ambiq/apollo3_evb/Kconfig.apollo3_evb b/boards/ambiq/apollo3_evb/Kconfig.apollo3_evb new file mode 100644 index 00000000000000..f5ca25f15f480c --- /dev/null +++ b/boards/ambiq/apollo3_evb/Kconfig.apollo3_evb @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +config BOARD_APOLLO3_EVB + select SOC_APOLLO3_BLUE diff --git a/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi b/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi new file mode 100644 index 00000000000000..cfba01ba4dea63 --- /dev/null +++ b/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c1_default: i2c1_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c2_default: i2c2_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c3_default: i2c3_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c4_default: i2c4_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c5_default: i2c5_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <0>; + }; + }; + spi1_default: spi1_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <1>; + ambiq,iom-num = <1>; + }; + }; + spi2_default: spi2_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <3>; + ambiq,iom-num = <2>; + }; + }; + spi3_default: spi3_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <3>; + }; + }; + spi4_default: spi4_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <1>; + ambiq,iom-num = <4>; + }; + }; + spi5_default: spi5_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <5>; + }; + }; + + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <6>; + }; + }; +}; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts new file mode 100644 index 00000000000000..181495a303825c --- /dev/null +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -0,0 +1,29 @@ +/dts-v1/; +#include + +#include "apollo3_evb-pinctrl.dtsi" + +/ { + model = "Ambiq Apollo3 Blue evaluation board"; + compatible = "ambiq,apollo3_evb"; + + chosen { + zephyr,itcm = &tcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-pipe = &uart0; + }; + + aliases { + watchdog0 = &wdt0; + }; +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.yaml b/boards/ambiq/apollo3_evb/apollo3_evb.yaml new file mode 100644 index 00000000000000..c76500facc4553 --- /dev/null +++ b/boards/ambiq/apollo3_evb/apollo3_evb.yaml @@ -0,0 +1,15 @@ +identifier: apollo3_evb +name: Apollo3 Blue EVB +type: mcu +arch: arm +ram: 384 +flash: 976 +toolchain: + - zephyr + - gnuarmemb +supported: + - uart +testing: + ignore_tags: + - net +vendor: ambiq diff --git a/boards/ambiq/apollo3_evb/apollo3_evb_defconfig b/boards/ambiq/apollo3_evb/apollo3_evb_defconfig new file mode 100644 index 00000000000000..5f556803e527ab --- /dev/null +++ b/boards/ambiq/apollo3_evb/apollo3_evb_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Ambiq Micro Inc. + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/ambiq/apollo3_evb/board.cmake b/boards/ambiq/apollo3_evb/board.cmake new file mode 100644 index 00000000000000..1a5a2709639e0e --- /dev/null +++ b/boards/ambiq/apollo3_evb/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=AMA3B1KK-KBR" "--iface=swd" "--speed=1000") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/ambiq/apollo3_evb/board.yml b/boards/ambiq/apollo3_evb/board.yml new file mode 100644 index 00000000000000..8c3925245c3cef --- /dev/null +++ b/boards/ambiq/apollo3_evb/board.yml @@ -0,0 +1,5 @@ +board: + name: apollo3_evb + vendor: ambiq + socs: + - name: apollo3_blue diff --git a/boards/ambiq/apollo3_evb/doc/apollo3-blue-soc-eval-board.jpg b/boards/ambiq/apollo3_evb/doc/apollo3-blue-soc-eval-board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5e30793f3961bcfb383408deeac22f81429458ac GIT binary patch literal 52700 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 KHJ{WVSZL=xP=ReptU1<7;#X9F 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 literal 0 HcmV?d00001 diff --git a/boards/ambiq/apollo3_evb/doc/index.rst b/boards/ambiq/apollo3_evb/doc/index.rst new file mode 100644 index 00000000000000..12990d0c9fec1c --- /dev/null +++ b/boards/ambiq/apollo3_evb/doc/index.rst @@ -0,0 +1,102 @@ +.. _apollo3_evb: + +Ambiq Apollo3 Blue EVB +###################### + +Apollo3 Blue EVB is a board by Ambiq featuring their ultra-low power Apollo3 Blue SoC. + +.. image:: ./apollo3-blue-soc-eval-board.jpg + :align: center + :alt: Apollo3 Blue EVB + +Hardware +******** + +- Apollo3 Blue SoC with up to 96 MHz operating frequency +- ARM® Cortex® M4F core +- 16 kB 2-way Associative/Direct-Mapped Cache per core +- Up to 1 MB of flash memory for code/data +- Up to 384 KB of low leakage / low power RAM for code/data +- Integrated Bluetooth 5 Low-energy controller + +For more information about the Apollo3 Blue SoC and Apollo3 Blue EVB board: + +- `Apollo3 Blue Website`_ +- `Apollo3 Blue Datasheet`_ +- `Apollo3 Blue EVB Website`_ + +Supported Features +================== + +The Apollo3 Blue EVB board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| STIMER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +``boards/arm/apollo3_evb/apollo3_evb_defconfig``. + +Programming and Debugging +========================= + +Flashing an application +----------------------- + +Connect your device to your host computer using the JLINK USB port. +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application, then flash it to the device: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: apollo3_evb + :goals: flash + +.. note:: + `west flash` requires `SEGGER J-Link software`_ and `pylink`_ Python module + to be installed on you host computer. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! apollo3_evb + +.. _Apollo3 Blue Website: + https://ambiq.com/apollo3-blue/ + +.. _Apollo3 Blue Datasheet: + https://contentportal.ambiq.com/documents/20123/388390/Apollo3-Blue-SoC-Datasheet.pdf + +.. _Apollo3 Blue EVB Website: + https://www.ambiq.top/en/apollo3-blue-soc-eval-board + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink + +.. _pylink: + https://github.com/Square/pylink From 1ac6445c2c6763b08e37eeaed8197ccb7fa7ef17 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0268/1389] drivers: pinctrl: Add pinctrl driver for Apollo3 SoCs This commit adds pinctrl support for Apollo3 SoCs. Signed-off-by: Hao Luo --- drivers/pinctrl/CMakeLists.txt | 2 +- drivers/pinctrl/Kconfig.ambiq | 8 +- ...inctrl_ambiq_apollo4.c => pinctrl_ambiq.c} | 27 +- dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 5 + dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 5 + .../pinctrl/ambiq,apollo3-pinctrl.yaml | 127 +++++ .../pinctrl/ambiq-apollo3-pinctrl.h | 494 ++++++++++++++++++ soc/ambiq/apollo3x/pinctrl_soc.h | 86 +++ 8 files changed, 746 insertions(+), 8 deletions(-) rename drivers/pinctrl/{pinctrl_ambiq_apollo4.c => pinctrl_ambiq.c} (56%) create mode 100644 dts/bindings/pinctrl/ambiq,apollo3-pinctrl.yaml create mode 100644 include/zephyr/dt-bindings/pinctrl/ambiq-apollo3-pinctrl.h create mode 100644 soc/ambiq/apollo3x/pinctrl_soc.h diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index c285e7d6f7f691..91bbb8b3d51618 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -4,7 +4,7 @@ zephyr_library() zephyr_library_sources(common.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TELINK_B91 pinctrl_b91.c) -zephyr_library_sources_ifdef(CONFIG_PINCTRL_AMBIQ_APOLLO4 pinctrl_ambiq_apollo4.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_AMBIQ pinctrl_ambiq.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_ITE_IT8XXX2 pinctrl_ite_it8xxx2.c) diff --git a/drivers/pinctrl/Kconfig.ambiq b/drivers/pinctrl/Kconfig.ambiq index 14d5f76ca897f1..336dce05decab1 100644 --- a/drivers/pinctrl/Kconfig.ambiq +++ b/drivers/pinctrl/Kconfig.ambiq @@ -2,11 +2,11 @@ # # Copyright (c) 2023 Antmicro -config PINCTRL_AMBIQ_APOLLO4 - bool "Ambiq Apollo4 pin controller driver" +config PINCTRL_AMBIQ + bool "Ambiq Apollo pin controller driver" default y - depends on DT_HAS_AMBIQ_APOLLO4_PINCTRL_ENABLED + depends on DT_HAS_AMBIQ_APOLLO4_PINCTRL_ENABLED || DT_HAS_AMBIQ_APOLLO3_PINCTRL_ENABLED select AMBIQ_HAL select AMBIQ_HAL_USE_GPIO help - Ambiq Apollo4 pinctrl driver + Ambiq Apollo pinctrl driver diff --git a/drivers/pinctrl/pinctrl_ambiq_apollo4.c b/drivers/pinctrl/pinctrl_ambiq.c similarity index 56% rename from drivers/pinctrl/pinctrl_ambiq_apollo4.c rename to drivers/pinctrl/pinctrl_ambiq.c index 6247838738ebc5..395f0101f4ca2a 100644 --- a/drivers/pinctrl/pinctrl_ambiq_apollo4.c +++ b/drivers/pinctrl/pinctrl_ambiq.c @@ -13,9 +13,30 @@ static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin) { am_hal_gpio_pincfg_t pin_config = {0}; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + pin_config.uFuncSel = pin->alt_func; + pin_config.eGPInput = + pin->input_enable ? AM_HAL_GPIO_PIN_INPUT_ENABLE : AM_HAL_GPIO_PIN_INPUT_NONE; + pin_config.eGPOutcfg = pin->push_pull ? AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL + : pin->open_drain ? AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN + : pin->tristate ? AM_HAL_GPIO_PIN_OUTCFG_TRISTATE + : AM_HAL_GPIO_PIN_OUTCFG_DISABLE; + pin_config.eDriveStrength = pin->drive_strength; + pin_config.uNCE = pin->iom_nce; +#if defined(CONFIG_SOC_APOLLO3P_BLUE) + pin_config.bIomMSPIn = pin->iom_mspi; +#endif + pin_config.uIOMnum = pin->iom_num; + + if (pin->bias_pull_up) { + pin_config.ePullup = pin->ambiq_pull_up_ohms + AM_HAL_GPIO_PIN_PULLUP_1_5K; + } else if (pin->bias_pull_down) { + pin_config.ePullup = AM_HAL_GPIO_PIN_PULLDOWN; + } +#else pin_config.GP.cfg_b.uFuncSel = pin->alt_func; - pin_config.GP.cfg_b.eGPInput = pin->input_enable ? AM_HAL_GPIO_PIN_INPUT_ENABLE - : AM_HAL_GPIO_PIN_INPUT_NONE; + pin_config.GP.cfg_b.eGPInput = + pin->input_enable ? AM_HAL_GPIO_PIN_INPUT_ENABLE : AM_HAL_GPIO_PIN_INPUT_NONE; pin_config.GP.cfg_b.eGPOutCfg = pin->push_pull ? AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL : pin->open_drain ? AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN : pin->tristate ? AM_HAL_GPIO_PIN_OUTCFG_TRISTATE @@ -29,7 +50,7 @@ static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin) } else if (pin->bias_pull_down) { pin_config.GP.cfg_b.ePullup = AM_HAL_GPIO_PIN_PULLDOWN_50K; } - +#endif am_hal_gpio_pinconfig(pin->pin_num, pin_config); } diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index 143dd46dbd1bef..1f151efc9a1abc 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -151,6 +151,11 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x800>; }; + pinctrl: pin-controller@40010000 { + compatible = "ambiq,apollo3-pinctrl"; + reg = <0x40010000 0x800>; + }; + wdt0: watchdog@40024000 { compatible = "ambiq,watchdog"; reg = <0x40024000 0x400>; diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index f0ed2be9a6e486..a95b7e6945b35d 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -171,6 +171,11 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2000>; }; + pinctrl: pin-controller@40010000 { + compatible = "ambiq,apollo3-pinctrl"; + reg = <0x40010000 0x800>; + }; + wdt0: watchdog@40024000 { compatible = "ambiq,watchdog"; reg = <0x40024000 0x400>; diff --git a/dts/bindings/pinctrl/ambiq,apollo3-pinctrl.yaml b/dts/bindings/pinctrl/ambiq,apollo3-pinctrl.yaml new file mode 100644 index 00000000000000..6035955af50a01 --- /dev/null +++ b/dts/bindings/pinctrl/ambiq,apollo3-pinctrl.yaml @@ -0,0 +1,127 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + The Ambiq Apollo3 pin controller is a node responsible for controlling + pin function selection and pin properties, such as routing a UART0 TX + to pin 60 and enabling the pullup resistor on that pin. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + /* You can put this in places like a board-pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + + /* include pre-defined combinations for the SoC variant used by the board */ + #include + + &pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'pinmux' + property. + + A group can also specify shared pin properties common to all the specified + pins, such as the 'input-enable' property in group 2. + +compatible: "ambiq,apollo3-pinctrl" + +include: base.yaml + +child-binding: + description: | + Definitions for a pinctrl state. + child-binding: + + include: + - name: pincfg-node.yaml + property-allowlist: + - input-enable + - drive-push-pull + - drive-open-drain + - bias-high-impedance + - bias-pull-up + - bias-pull-down + + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. Each + element of the array is an integer constructed from the + pin number and the alternative function of the pin. + drive-strength: + type: string + enum: + - "0.1" + - "0.5" + - "0.75" + - "1.0" + default: "0.1" + description: | + The drive strength of a pin, relative to full-driver strength. + The default value is 0.1, which is the reset value of resigers + PADREGx.PADnSTRNG and ALTPADCFGx.PADn_DS1. + ambiq,pull-up-ohms: + type: int + enum: + - 1500 + - 6000 + - 12000 + - 24000 + default: 1500 + description: | + The 1.5K-24K pullup values are valid for select I2C enabled pads. + For Apollo3 these pins are 0-1,5-6,8-9,25,27,39-40,42-43,48-49. + The default value is 1500 ohms, which is the reset value of + register PADREGx.PADxRSEL. + ambiq,iom-nce-module: + type: int + default: 0 + description: | + IOM nCE module select, selects the SPI channel (CE) number (0-3). + The default value is 0, which is the reset value of + register CFGx.GPIOnOUTCFG. If the pin is not a CE, this + descriptor will be ignored. + ambiq,iom-mspi: + type: int + default: 0 + description: | + Indicates the module which uses specific CE pin, 1 if CE is IOM, 0 if MSPI. + User should check g_ui8NCEtable in am_hal_gpio.c for the mapping + information and config the pins accordingly, we give a default value + 0 here to make it be consistent with AM_HAL_GPIO_PINCFG_DEFAULT in + ambiq hal. If the pin is not a CE, this descriptor will be ignored. + ambiq,iom-num: + type: int + default: 0 + description: | + Indicates the instance which uses specific CE pin. + IOM number (0-5) or MSPI (0-2). + User should check g_ui8NCEtable in am_hal_gpio.c for the mapping + information and config the pins accordingly, we give a default value + 0 here to make it be consistent with AM_HAL_GPIO_PINCFG_DEFAULT in + ambiq hal. If the pin is not a CE, this descriptor will be ignored. diff --git a/include/zephyr/dt-bindings/pinctrl/ambiq-apollo3-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/ambiq-apollo3-pinctrl.h new file mode 100644 index 00000000000000..fbbbd42ae4c609 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/ambiq-apollo3-pinctrl.h @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __APOLLO3_PINCTRL_H__ +#define __APOLLO3_PINCTRL_H__ + +#define APOLLO3_ALT_FUNC_POS 0 +#define APOLLO3_ALT_FUNC_MASK 0xf + +#define APOLLO3_PIN_NUM_POS 4 +#define APOLLO3_PIN_NUM_MASK 0x7f + +#define APOLLO3_PINMUX(pin_num, alt_func) \ + (pin_num << APOLLO3_PIN_NUM_POS | alt_func << APOLLO3_ALT_FUNC_POS) + +#define SLSCL_P0 APOLLO3_PINMUX(0, 0) +#define SLSCK_P0 APOLLO3_PINMUX(0, 1) +#define CLKOUT_P0 APOLLO3_PINMUX(0, 2) +#define GPIO_P0 APOLLO3_PINMUX(0, 3) +#define MSPI0_4_P0 APOLLO3_PINMUX(0, 5) +#define NCE0_P0 APOLLO3_PINMUX(0, 7) +#define SLSDAWIR3_P1 APOLLO3_PINMUX(1, 0) +#define SLMOSI_P1 APOLLO3_PINMUX(1, 1) +#define UART0TX_P1 APOLLO3_PINMUX(1, 2) +#define GPIO_P1 APOLLO3_PINMUX(1, 3) +#define MSPI0_5_P1 APOLLO3_PINMUX(1, 5) +#define NCE1_P1 APOLLO3_PINMUX(1, 7) +#define UART1RX_P2 APOLLO3_PINMUX(2, 0) +#define SLMISO_P2 APOLLO3_PINMUX(2, 1) +#define UART0RX_P2 APOLLO3_PINMUX(2, 2) +#define GPIO_P2 APOLLO3_PINMUX(2, 3) +#define MSPI0_6_P2 APOLLO3_PINMUX(2, 5) +#define NCE2_P2 APOLLO3_PINMUX(2, 7) +#define UA0RTS_P3 APOLLO3_PINMUX(3, 0) +#define SLNCE_P3 APOLLO3_PINMUX(3, 1) +#define NCE3_P3 APOLLO3_PINMUX(3, 2) +#define GPIO_P3 APOLLO3_PINMUX(3, 3) +#define MSPI0_7_P3 APOLLO3_PINMUX(3, 5) +#define TRIG1_P3 APOLLO3_PINMUX(3, 6) +#define I2SWCLK_P3 APOLLO3_PINMUX(3, 7) +#define UA0CTS_P4 APOLLO3_PINMUX(4, 0) +#define SLINT_P4 APOLLO3_PINMUX(4, 1) +#define NCE4_P4 APOLLO3_PINMUX(4, 2) +#define GPIO_P4 APOLLO3_PINMUX(4, 3) +#define UART1RX_P4 APOLLO3_PINMUX(4, 5) +#define CTIM17_P4 APOLLO3_PINMUX(4, 6) +#define MSPI0_2_P4 APOLLO3_PINMUX(4, 7) +#define M0SCL_P5 APOLLO3_PINMUX(5, 0) +#define M0SCK_P5 APOLLO3_PINMUX(5, 1) +#define UA0RTS_P5 APOLLO3_PINMUX(5, 2) +#define GPIO_P5 APOLLO3_PINMUX(5, 3) +#define CT8_P5 APOLLO3_PINMUX(5, 7) +#define M0SDAWIR3_P6 APOLLO3_PINMUX(6, 0) +#define M0MISO_P6 APOLLO3_PINMUX(6, 1) +#define UA0CTS_P6 APOLLO3_PINMUX(6, 2) +#define GPIO_P6 APOLLO3_PINMUX(6, 3) +#define CTIM10_P6 APOLLO3_PINMUX(6, 5) +#define I2SDAT_P6 APOLLO3_PINMUX(6, 7) +#define NCE7_P7 APOLLO3_PINMUX(7, 0) +#define M0MOSI_P7 APOLLO3_PINMUX(7, 1) +#define CLKOUT_P7 APOLLO3_PINMUX(7, 2) +#define GPIO_P7 APOLLO3_PINMUX(7, 3) +#define TRIG0_P7 APOLLO3_PINMUX(7, 4) +#define UART0TX_P7 APOLLO3_PINMUX(7, 5) +#define CTIM19_P7 APOLLO3_PINMUX(7, 7) +#define M1SCL_P8 APOLLO3_PINMUX(8, 0) +#define M1SCK_P8 APOLLO3_PINMUX(8, 1) +#define NCE8_P8 APOLLO3_PINMUX(8, 2) +#define GPIO_P8 APOLLO3_PINMUX(8, 3) +#define SCCCLK_P8 APOLLO3_PINMUX(8, 4) +#define UART1TX_P8 APOLLO3_PINMUX(8, 6) +#define M1SDAWIR3_P9 APOLLO3_PINMUX(9, 0) +#define M1MISO_P9 APOLLO3_PINMUX(9, 1) +#define NCE9_P9 APOLLO3_PINMUX(9, 2) +#define GPIO_P9 APOLLO3_PINMUX(9, 3) +#define SCCIO_P9 APOLLO3_PINMUX(9, 4) +#define UART1RX_P9 APOLLO3_PINMUX(9, 6) +#define UART1TX_P10 APOLLO3_PINMUX(10, 0) +#define M1MOSI_P10 APOLLO3_PINMUX(10, 1) +#define NCE10_P10 APOLLO3_PINMUX(10, 2) +#define GPIO_P10 APOLLO3_PINMUX(10, 3) +#define PDMCLK_P10 APOLLO3_PINMUX(10, 4) +#define UA1RTS_P10 APOLLO3_PINMUX(10, 6) +#define ADCSE2_P11 APOLLO3_PINMUX(11, 0) +#define NCE11_P11 APOLLO3_PINMUX(11, 1) +#define CTIM31_P11 APOLLO3_PINMUX(11, 2) +#define GPIO_P11 APOLLO3_PINMUX(11, 3) +#define SLINT_P11 APOLLO3_PINMUX(11, 4) +#define UA1CTS_P11 APOLLO3_PINMUX(11, 5) +#define UART0RX_P11 APOLLO3_PINMUX(11, 6) +#define PDMDATA_P11 APOLLO3_PINMUX(11, 7) +#define ADCD0NSE9_P12 APOLLO3_PINMUX(12, 0) +#define NCE12_P12 APOLLO3_PINMUX(12, 1) +#define CT0_P12 APOLLO3_PINMUX(12, 2) +#define GPIO_P12 APOLLO3_PINMUX(12, 3) +#define PDMCLK_P12 APOLLO3_PINMUX(12, 5) +#define UA0CTS_P12 APOLLO3_PINMUX(12, 6) +#define UART1TX_P12 APOLLO3_PINMUX(12, 7) +#define ADCD0PSE8_P13 APOLLO3_PINMUX(13, 0) +#define NCE13_P13 APOLLO3_PINMUX(13, 1) +#define CTIM2_P13 APOLLO3_PINMUX(13, 2) +#define GPIO_P13 APOLLO3_PINMUX(13, 3) +#define I2SBCLK_P13 APOLLO3_PINMUX(13, 4) +#define UA0RTS_P13 APOLLO3_PINMUX(13, 6) +#define UART1RX_P13 APOLLO3_PINMUX(13, 7) +#define ADCD1P_P14 APOLLO3_PINMUX(14, 0) +#define NCE14_P14 APOLLO3_PINMUX(14, 1) +#define UART1TX_P14 APOLLO3_PINMUX(14, 2) +#define GPIO_P14 APOLLO3_PINMUX(14, 3) +#define PDMCLK_P14 APOLLO3_PINMUX(14, 4) +#define SWDCK_P14 APOLLO3_PINMUX(14, 6) +#define XT32KHz_P14 APOLLO3_PINMUX(14, 7) +#define ADCD1N_P15 APOLLO3_PINMUX(15, 0) +#define NCE15_P15 APOLLO3_PINMUX(15, 1) +#define UART1RX_P15 APOLLO3_PINMUX(15, 2) +#define GPIO_P15 APOLLO3_PINMUX(15, 3) +#define PDMDATA_P15 APOLLO3_PINMUX(15, 4) +#define SWDIO_P15 APOLLO3_PINMUX(15, 6) +#define SWO_P15 APOLLO3_PINMUX(15, 7) +#define ADCSE0_P16 APOLLO3_PINMUX(16, 0) +#define NCE16_P16 APOLLO3_PINMUX(16, 1) +#define TRIG0_P16 APOLLO3_PINMUX(16, 2) +#define GPIO_P16 APOLLO3_PINMUX(16, 3) +#define SCCRST_P16 APOLLO3_PINMUX(16, 4) +#define CMPIN0_P16 APOLLO3_PINMUX(16, 5) +#define UART0TX_P16 APOLLO3_PINMUX(16, 6) +#define UA1RTS_P16 APOLLO3_PINMUX(16, 7) +#define CMPRF1_P17 APOLLO3_PINMUX(17, 0) +#define NCE17_P17 APOLLO3_PINMUX(17, 1) +#define TRIG1_P17 APOLLO3_PINMUX(17, 2) +#define GPIO_P17 APOLLO3_PINMUX(17, 3) +#define SCCCLK_P17 APOLLO3_PINMUX(17, 4) +#define UART0RX_P17 APOLLO3_PINMUX(17, 6) +#define UA1CTS_P17 APOLLO3_PINMUX(17, 7) +#define CMPIN1_P18 APOLLO3_PINMUX(18, 0) +#define NCE18_P18 APOLLO3_PINMUX(18, 1) +#define CTIM4_P18 APOLLO3_PINMUX(18, 2) +#define GPIO_P18 APOLLO3_PINMUX(18, 3) +#define UA0RTS_P18 APOLLO3_PINMUX(18, 4) +#define UART1TX_P18 APOLLO3_PINMUX(18, 6) +#define SCCIO_P18 APOLLO3_PINMUX(18, 7) +#define CMPRF0_P19 APOLLO3_PINMUX(19, 0) +#define NCE19_P19 APOLLO3_PINMUX(19, 1) +#define CTIM6_P19 APOLLO3_PINMUX(19, 2) +#define GPIO_P19 APOLLO3_PINMUX(19, 3) +#define SCCCLK_P19 APOLLO3_PINMUX(19, 4) +#define UART1RX_P19 APOLLO3_PINMUX(19, 6) +#define I2SBCLK_P19 APOLLO3_PINMUX(19, 7) +#define SWDCK_P20 APOLLO3_PINMUX(20, 0) +#define NCE20_P20 APOLLO3_PINMUX(20, 1) +#define GPIO_P20 APOLLO3_PINMUX(20, 3) +#define UART0TX_P20 APOLLO3_PINMUX(20, 4) +#define UART1TX_P20 APOLLO3_PINMUX(20, 5) +#define I2SBCLK_P20 APOLLO3_PINMUX(20, 6) +#define UA1RTS_P20 APOLLO3_PINMUX(20, 7) +#define SWDIO_P21 APOLLO3_PINMUX(21, 0) +#define NCE21_P21 APOLLO3_PINMUX(21, 1) +#define GPIO_P21 APOLLO3_PINMUX(21, 3) +#define UART0RX_P21 APOLLO3_PINMUX(21, 4) +#define UART1RX_P21 APOLLO3_PINMUX(21, 5) +#define SCCRST_P21 APOLLO3_PINMUX(21, 6) +#define UA1CTS_P21 APOLLO3_PINMUX(21, 7) +#define UART0TX_P22 APOLLO3_PINMUX(22, 0) +#define NCE22_P22 APOLLO3_PINMUX(22, 1) +#define CTIM12_P22 APOLLO3_PINMUX(22, 2) +#define GPIO_P22 APOLLO3_PINMUX(22, 3) +#define PDMCLK_P22 APOLLO3_PINMUX(22, 4) +#define MSPI0_0_P22 APOLLO3_PINMUX(22, 6) +#define SWO_P22 APOLLO3_PINMUX(22, 7) +#define UART0RX_P23 APOLLO3_PINMUX(23, 0) +#define NCE23_P23 APOLLO3_PINMUX(23, 1) +#define CTIM14_P23 APOLLO3_PINMUX(23, 2) +#define GPIO_P23 APOLLO3_PINMUX(23, 3) +#define I2SWCLK_P23 APOLLO3_PINMUX(23, 4) +#define CMPOUT_P23 APOLLO3_PINMUX(23, 5) +#define MSPI0_3_P23 APOLLO3_PINMUX(23, 6) +#define UART1TX_P24 APOLLO3_PINMUX(24, 0) +#define NCE24_P24 APOLLO3_PINMUX(24, 1) +#define MSPI0_8_P24 APOLLO3_PINMUX(24, 2) +#define GPIO_P24 APOLLO3_PINMUX(24, 3) +#define UA0CTS_P24 APOLLO3_PINMUX(24, 4) +#define CTIM21_P24 APOLLO3_PINMUX(24, 5) +#define XT32KHz_P24 APOLLO3_PINMUX(24, 6) +#define SWO_P24 APOLLO3_PINMUX(24, 7) +#define UART1RX_P25 APOLLO3_PINMUX(25, 0) +#define NCE25_P25 APOLLO3_PINMUX(25, 1) +#define CTIM1_P25 APOLLO3_PINMUX(25, 2) +#define GPIO_P25 APOLLO3_PINMUX(25, 3) +#define M2SDAWIR3_P25 APOLLO3_PINMUX(25, 4) +#define M2MISO_P25 APOLLO3_PINMUX(25, 5) +#define NCE26_P26 APOLLO3_PINMUX(26, 1) +#define CTIM3_P26 APOLLO3_PINMUX(26, 2) +#define GPIO_P26 APOLLO3_PINMUX(26, 3) +#define SCCRST_P26 APOLLO3_PINMUX(26, 4) +#define MSPI0_1_P26 APOLLO3_PINMUX(26, 5) +#define UART0TX_P26 APOLLO3_PINMUX(26, 6) +#define UA1CTS_P26 APOLLO3_PINMUX(26, 7) +#define UART0RX_P27 APOLLO3_PINMUX(27, 0) +#define NCE27_P27 APOLLO3_PINMUX(27, 1) +#define CTIM5_P27 APOLLO3_PINMUX(27, 2) +#define GPIO_P27 APOLLO3_PINMUX(27, 3) +#define M2SCL_P27 APOLLO3_PINMUX(27, 4) +#define M2SCK_P27 APOLLO3_PINMUX(27, 5) +#define I2SWCLK_P28 APOLLO3_PINMUX(28, 0) +#define NCE28_P28 APOLLO3_PINMUX(28, 1) +#define CTIM7_P28 APOLLO3_PINMUX(28, 2) +#define GPIO_P28 APOLLO3_PINMUX(28, 3) +#define M2MOSI_P28 APOLLO3_PINMUX(28, 5) +#define UART0TX_P28 APOLLO3_PINMUX(28, 6) +#define ADCSE1_P29 APOLLO3_PINMUX(29, 0) +#define NCE29_P29 APOLLO3_PINMUX(29, 1) +#define CTIM9_P29 APOLLO3_PINMUX(29, 2) +#define GPIO_P29 APOLLO3_PINMUX(29, 3) +#define UA0CTS_P29 APOLLO3_PINMUX(29, 4) +#define UA1CTS_P29 APOLLO3_PINMUX(29, 5) +#define UART0RX_P29 APOLLO3_PINMUX(29, 6) +#define PDMDATA_P29 APOLLO3_PINMUX(29, 7) +#define NCE30_P30 APOLLO3_PINMUX(30, 1) +#define CTIM11_P30 APOLLO3_PINMUX(30, 2) +#define GPIO_P30 APOLLO3_PINMUX(30, 3) +#define UART0TX_P30 APOLLO3_PINMUX(30, 4) +#define UA1RTS_P30 APOLLO3_PINMUX(30, 5) +#define BLEIF_SCK_P30 APOLLO3_PINMUX(30, 6) +#define I2SDAT_P30 APOLLO3_PINMUX(30, 7) +#define ADCSE3_P31 APOLLO3_PINMUX(31, 0) +#define NCE31_P31 APOLLO3_PINMUX(31, 1) +#define CTIM13_P31 APOLLO3_PINMUX(31, 2) +#define GPIO_P31 APOLLO3_PINMUX(31, 3) +#define UART0RX_P31 APOLLO3_PINMUX(31, 4) +#define SCCCLK_P31 APOLLO3_PINMUX(31, 5) +#define BLEIF_MISO_P31 APOLLO3_PINMUX(31, 6) +#define UA1RTS_P31 APOLLO3_PINMUX(31, 7) +#define ADCSE4_P32 APOLLO3_PINMUX(32, 0) +#define NCE32_P32 APOLLO3_PINMUX(32, 1) +#define CTIM15_P32 APOLLO3_PINMUX(32, 2) +#define GPIO_P32 APOLLO3_PINMUX(32, 3) +#define SCCIO_P32 APOLLO3_PINMUX(32, 4) +#define BLEIF_MOSI_P32 APOLLO3_PINMUX(32, 6) +#define UA1CTS_P32 APOLLO3_PINMUX(32, 7) +#define ADCSE5_P33 APOLLO3_PINMUX(33, 0) +#define NCE33_P33 APOLLO3_PINMUX(33, 1) +#define XT32KHz_P33 APOLLO3_PINMUX(33, 2) +#define GPIO_P33 APOLLO3_PINMUX(33, 3) +#define BLEIF_CSN_P33 APOLLO3_PINMUX(33, 4) +#define UA0CTS_P33 APOLLO3_PINMUX(33, 5) +#define CTIM23_P33 APOLLO3_PINMUX(33, 6) +#define SWO_P33 APOLLO3_PINMUX(33, 7) +#define ADCSE6_P34 APOLLO3_PINMUX(34, 0) +#define NCE34_P34 APOLLO3_PINMUX(34, 1) +#define UA1RTS_P34 APOLLO3_PINMUX(34, 2) +#define GPIO_P34 APOLLO3_PINMUX(34, 3) +#define CMPRF2_P34 APOLLO3_PINMUX(34, 4) +#define UA0RTS_P34 APOLLO3_PINMUX(34, 5) +#define UART0RX_P34 APOLLO3_PINMUX(34, 6) +#define PDMDATA_P34 APOLLO3_PINMUX(34, 7) +#define ADCSE7_P35 APOLLO3_PINMUX(35, 0) +#define NCE35_P35 APOLLO3_PINMUX(35, 1) +#define UART1TX_P35 APOLLO3_PINMUX(35, 2) +#define GPIO_P35 APOLLO3_PINMUX(35, 3) +#define I2SDAT_P35 APOLLO3_PINMUX(35, 4) +#define CTIM27_P35 APOLLO3_PINMUX(35, 5) +#define UA0RTS_P35 APOLLO3_PINMUX(35, 6) +#define BLEIF_STATUS_P35 APOLLO3_PINMUX(35, 7) +#define TRIG1_P36 APOLLO3_PINMUX(36, 0) +#define NCE36_P36 APOLLO3_PINMUX(36, 1) +#define UART1RX_P36 APOLLO3_PINMUX(36, 2) +#define GPIO_P36 APOLLO3_PINMUX(36, 3) +#define XT32KHz_P36 APOLLO3_PINMUX(36, 4) +#define UA1CTS_P36 APOLLO3_PINMUX(36, 5) +#define UA0CTS_P36 APOLLO3_PINMUX(36, 6) +#define PDMDATA_P36 APOLLO3_PINMUX(36, 7) +#define TRIG2_P37 APOLLO3_PINMUX(37, 0) +#define NCE37_P37 APOLLO3_PINMUX(37, 1) +#define UA0RTS_P37 APOLLO3_PINMUX(37, 2) +#define GPIO_P37 APOLLO3_PINMUX(37, 3) +#define SCCIO_P37 APOLLO3_PINMUX(37, 4) +#define UART1TX_P37 APOLLO3_PINMUX(37, 5) +#define PDMCLK_P37 APOLLO3_PINMUX(37, 6) +#define CTIM29_P37 APOLLO3_PINMUX(37, 7) +#define TRIG3_P38 APOLLO3_PINMUX(38, 0) +#define NCE38_P38 APOLLO3_PINMUX(38, 1) +#define UA0CTS_P38 APOLLO3_PINMUX(38, 2) +#define GPIO_P38 APOLLO3_PINMUX(38, 3) +#define M3MOSI_P38 APOLLO3_PINMUX(38, 5) +#define UART1RX_P38 APOLLO3_PINMUX(38, 6) +#define UART0TX_P39 APOLLO3_PINMUX(39, 0) +#define UART1TX_P39 APOLLO3_PINMUX(39, 1) +#define CTIM25_P39 APOLLO3_PINMUX(39, 2) +#define GPIO_P39 APOLLO3_PINMUX(39, 3) +#define M4SCL_P39 APOLLO3_PINMUX(39, 4) +#define M4SCK_P39 APOLLO3_PINMUX(39, 5) +#define UART0RX_P40 APOLLO3_PINMUX(40, 0) +#define UART1RX_P40 APOLLO3_PINMUX(40, 1) +#define TRIG0_P40 APOLLO3_PINMUX(40, 2) +#define GPIO_P40 APOLLO3_PINMUX(40, 3) +#define M4SDAWIR3_P40 APOLLO3_PINMUX(40, 4) +#define M4MISO_P40 APOLLO3_PINMUX(40, 5) +#define NCE41_P41 APOLLO3_PINMUX(41, 0) +#define BLEIF_IRQ_P41 APOLLO3_PINMUX(41, 1) +#define SWO_P41 APOLLO3_PINMUX(41, 2) +#define GPIO_P41 APOLLO3_PINMUX(41, 3) +#define I2SWCLK_P41 APOLLO3_PINMUX(41, 4) +#define UA1RTS_P41 APOLLO3_PINMUX(41, 5) +#define UART0TX_P41 APOLLO3_PINMUX(41, 6) +#define UA0RTS_P41 APOLLO3_PINMUX(41, 7) +#define UART1TX_P42 APOLLO3_PINMUX(42, 0) +#define NCE42_P42 APOLLO3_PINMUX(42, 1) +#define CTIM16_P42 APOLLO3_PINMUX(42, 2) +#define GPIO_P42 APOLLO3_PINMUX(42, 3) +#define M3SCL_P42 APOLLO3_PINMUX(42, 4) +#define M3SCK_P42 APOLLO3_PINMUX(42, 5) +#define UART1RX_P43 APOLLO3_PINMUX(43, 0) +#define NCE43_P43 APOLLO3_PINMUX(43, 1) +#define CTIM18_P43 APOLLO3_PINMUX(43, 2) +#define GPIO_P43 APOLLO3_PINMUX(43, 3) +#define M3SDAWIR3_P43 APOLLO3_PINMUX(43, 4) +#define M3MISO_P43 APOLLO3_PINMUX(43, 5) +#define UA1RTS_P44 APOLLO3_PINMUX(44, 0) +#define NCE44_P44 APOLLO3_PINMUX(44, 1) +#define CTIM20_P44 APOLLO3_PINMUX(44, 2) +#define GPIO_P44 APOLLO3_PINMUX(44, 3) +#define M4MOSI_P44 APOLLO3_PINMUX(44, 5) +#define UART0TX_P44 APOLLO3_PINMUX(44, 6) +#define UA1CTS_P45 APOLLO3_PINMUX(45, 0) +#define NCE45_P45 APOLLO3_PINMUX(45, 1) +#define CTIM22_P45 APOLLO3_PINMUX(45, 2) +#define GPIO_P45 APOLLO3_PINMUX(45, 3) +#define I2SDAT_P45 APOLLO3_PINMUX(45, 4) +#define PDMDATA_P45 APOLLO3_PINMUX(45, 5) +#define UART0RX_P45 APOLLO3_PINMUX(45, 6) +#define SWO_P45 APOLLO3_PINMUX(45, 7) +#define I2SBCLK_P46 APOLLO3_PINMUX(46, 0) +#define NCE46_P46 APOLLO3_PINMUX(46, 1) +#define CTIM24_P46 APOLLO3_PINMUX(46, 2) +#define GPIO_P46 APOLLO3_PINMUX(46, 3) +#define SCCRST_P46 APOLLO3_PINMUX(46, 4) +#define PDMCLK_P46 APOLLO3_PINMUX(46, 5) +#define UART1TX_P46 APOLLO3_PINMUX(46, 6) +#define SWO_P46 APOLLO3_PINMUX(46, 7) +#define XT32KHz_P47 APOLLO3_PINMUX(47, 0) +#define NCE47_P47 APOLLO3_PINMUX(47, 1) +#define CTIM26_P47 APOLLO3_PINMUX(47, 2) +#define GPIO_P47 APOLLO3_PINMUX(47, 3) +#define M5MOSI_P47 APOLLO3_PINMUX(47, 5) +#define UART1RX_P47 APOLLO3_PINMUX(47, 6) +#define UART0TX_P48 APOLLO3_PINMUX(48, 0) +#define NCE48_P48 APOLLO3_PINMUX(48, 1) +#define CTIM28_P48 APOLLO3_PINMUX(48, 2) +#define GPIO_P48 APOLLO3_PINMUX(48, 3) +#define M5SCL_P48 APOLLO3_PINMUX(48, 4) +#define M5SCK_P48 APOLLO3_PINMUX(48, 5) +#define UART0RX_P49 APOLLO3_PINMUX(49, 0) +#define NCE49_P49 APOLLO3_PINMUX(49, 1) +#define CTIM30_P49 APOLLO3_PINMUX(49, 2) +#define GPIO_P49 APOLLO3_PINMUX(49, 3) +#define M5SDAWIR3_P49 APOLLO3_PINMUX(49, 4) +#define M5MISO_P49 APOLLO3_PINMUX(49, 5) +#define SWO_P50 APOLLO3_PINMUX(50, 0) +#define NCE50_P50 APOLLO3_PINMUX(50, 1) +#define CT0_P50 APOLLO3_PINMUX(50, 2) +#define GPIO_P50 APOLLO3_PINMUX(50, 3) +#define UART0TX_P50 APOLLO3_PINMUX(50, 4) +#define UART0RX_P50 APOLLO3_PINMUX(50, 5) +#define UART1TX_P50 APOLLO3_PINMUX(50, 6) +#define UART1RX_P50 APOLLO3_PINMUX(50, 7) +#define MSPI1_0_P51 APOLLO3_PINMUX(51, 0) +#define NCE51_P51 APOLLO3_PINMUX(51, 1) +#define CTIM1_P51 APOLLO3_PINMUX(51, 2) +#define GPIO_P51 APOLLO3_PINMUX(51, 3) +#define MSPI1_1_P52 APOLLO3_PINMUX(52, 0) +#define NCE52_P52 APOLLO3_PINMUX(52, 1) +#define CTIM2_P52 APOLLO3_PINMUX(52, 2) +#define GPIO_P52 APOLLO3_PINMUX(52, 3) +#define MSPI1_2_P53 APOLLO3_PINMUX(53, 0) +#define NCE53_P53 APOLLO3_PINMUX(53, 1) +#define CTIM3_P53 APOLLO3_PINMUX(53, 2) +#define GPIO_P53 APOLLO3_PINMUX(53, 3) +#define MSPI1_3_P54 APOLLO3_PINMUX(54, 0) +#define NCE54_P54 APOLLO3_PINMUX(54, 1) +#define CTIM4_P54 APOLLO3_PINMUX(54, 2) +#define GPIO_P54 APOLLO3_PINMUX(54, 3) +#define MSPI1_4_P55 APOLLO3_PINMUX(55, 0) +#define NCE55_P55 APOLLO3_PINMUX(55, 1) +#define CTIM5_P55 APOLLO3_PINMUX(55, 2) +#define GPIO_P55 APOLLO3_PINMUX(55, 3) +#define MSPI1_5_P56 APOLLO3_PINMUX(56, 0) +#define NCE56_P56 APOLLO3_PINMUX(56, 1) +#define CTIM6_P56 APOLLO3_PINMUX(56, 2) +#define GPIO_P56 APOLLO3_PINMUX(56, 3) +#define MSPI1_6_P57 APOLLO3_PINMUX(57, 0) +#define NCE57_P57 APOLLO3_PINMUX(57, 1) +#define CTIM7_P57 APOLLO3_PINMUX(57, 2) +#define GPIO_P57 APOLLO3_PINMUX(57, 3) +#define MSPI1_7_P58 APOLLO3_PINMUX(58, 0) +#define NCE58_P58 APOLLO3_PINMUX(58, 1) +#define CTIM8_P58 APOLLO3_PINMUX(58, 2) +#define GPIO_P58 APOLLO3_PINMUX(58, 3) +#define MSPI1_8_P59 APOLLO3_PINMUX(59, 0) +#define NCE59_P59 APOLLO3_PINMUX(59, 1) +#define CTIM9_P59 APOLLO3_PINMUX(59, 2) +#define GPIO_P59 APOLLO3_PINMUX(59, 3) +#define MSPI1_9_P60 APOLLO3_PINMUX(60, 0) +#define NCE60_P60 APOLLO3_PINMUX(60, 1) +#define CTIM10_P60 APOLLO3_PINMUX(60, 2) +#define GPIO_P60 APOLLO3_PINMUX(60, 3) +#define SWO_P61 APOLLO3_PINMUX(61, 0) +#define NCE61_P61 APOLLO3_PINMUX(61, 1) +#define CTIM11_P61 APOLLO3_PINMUX(61, 2) +#define GPIO_P61 APOLLO3_PINMUX(61, 3) +#define UART0TX_P61 APOLLO3_PINMUX(61, 4) +#define UART0RX_P61 APOLLO3_PINMUX(61, 5) +#define UART1TX_P61 APOLLO3_PINMUX(61, 6) +#define UART1RX_P61 APOLLO3_PINMUX(61, 7) +#define SWO_P62 APOLLO3_PINMUX(62, 0) +#define NCE62_P62 APOLLO3_PINMUX(62, 1) +#define CTIM12_P62 APOLLO3_PINMUX(62, 2) +#define GPIO_P62 APOLLO3_PINMUX(62, 3) +#define UA0CTS_P62 APOLLO3_PINMUX(62, 4) +#define UA0RTS_P62 APOLLO3_PINMUX(62, 5) +#define UA1CTS_P62 APOLLO3_PINMUX(62, 6) +#define UA1RTS_P62 APOLLO3_PINMUX(62, 7) +#define SWO_P63 APOLLO3_PINMUX(63, 0) +#define NCE63_P63 APOLLO3_PINMUX(63, 1) +#define CTIM13_P63 APOLLO3_PINMUX(63, 2) +#define GPIO_P63 APOLLO3_PINMUX(63, 3) +#define UA0CTS_P63 APOLLO3_PINMUX(63, 4) +#define UA0RTS_P63 APOLLO3_PINMUX(63, 5) +#define UA1CTS_P63 APOLLO3_PINMUX(63, 6) +#define UA1RTS_P63 APOLLO3_PINMUX(63, 7) +#define MSPI2_0_P64 APOLLO3_PINMUX(64, 0) +#define NCE64_P64 APOLLO3_PINMUX(64, 1) +#define CTIM14_P64 APOLLO3_PINMUX(64, 2) +#define GPIO_P64 APOLLO3_PINMUX(64, 3) +#define MSPI2_1_P65 APOLLO3_PINMUX(65, 0) +#define NCE65_P65 APOLLO3_PINMUX(65, 1) +#define CTIM15_P65 APOLLO3_PINMUX(65, 2) +#define GPIO_P65 APOLLO3_PINMUX(65, 3) +#define MSPI2_2_P66 APOLLO3_PINMUX(66, 0) +#define NCE66_P66 APOLLO3_PINMUX(66, 1) +#define CTIM16_P66 APOLLO3_PINMUX(66, 2) +#define GPIO_P66 APOLLO3_PINMUX(66, 3) +#define MSPI2_3_P67 APOLLO3_PINMUX(67, 0) +#define NCE67_P67 APOLLO3_PINMUX(67, 1) +#define CTIM17_P67 APOLLO3_PINMUX(67, 2) +#define GPIO_P67 APOLLO3_PINMUX(67, 3) +#define MSPI2_4_P68 APOLLO3_PINMUX(68, 0) +#define NCE68_P68 APOLLO3_PINMUX(68, 1) +#define CTIM18_P68 APOLLO3_PINMUX(68, 2) +#define GPIO_P68 APOLLO3_PINMUX(68, 3) +#define SWO_P69 APOLLO3_PINMUX(69, 0) +#define NCE69_P69 APOLLO3_PINMUX(69, 1) +#define CTIM19_P69 APOLLO3_PINMUX(69, 2) +#define GPIO_P69 APOLLO3_PINMUX(69, 3) +#define UART0TX_P69 APOLLO3_PINMUX(69, 4) +#define UART0RX_P69 APOLLO3_PINMUX(69, 5) +#define UART1TX_P69 APOLLO3_PINMUX(69, 6) +#define UART1RX_P69 APOLLO3_PINMUX(69, 7) +#define SWO_P70 APOLLO3_PINMUX(70, 0) +#define NCE70_P70 APOLLO3_PINMUX(70, 1) +#define CTIM20_P70 APOLLO3_PINMUX(70, 2) +#define GPIO_P70 APOLLO3_PINMUX(70, 3) +#define UART0TX_P70 APOLLO3_PINMUX(70, 4) +#define UART0RX_P70 APOLLO3_PINMUX(70, 5) +#define UART1TX_P70 APOLLO3_PINMUX(70, 6) +#define UART1RX_P70 APOLLO3_PINMUX(70, 7) +#define SWO_P71 APOLLO3_PINMUX(71, 0) +#define NCE71_P71 APOLLO3_PINMUX(71, 1) +#define CTIM21_P71 APOLLO3_PINMUX(71, 2) +#define GPIO_P71 APOLLO3_PINMUX(71, 3) +#define UART0TX_P71 APOLLO3_PINMUX(71, 4) +#define UART0RX_P71 APOLLO3_PINMUX(71, 5) +#define UART1TX_P71 APOLLO3_PINMUX(71, 6) +#define UART1RX_P71 APOLLO3_PINMUX(71, 7) +#define SWO_P72 APOLLO3_PINMUX(72, 0) +#define NCE72_P72 APOLLO3_PINMUX(72, 1) +#define CTIM22_P72 APOLLO3_PINMUX(72, 2) +#define GPIO_P72 APOLLO3_PINMUX(72, 3) +#define UART0TX_P72 APOLLO3_PINMUX(72, 4) +#define UART0RX_P72 APOLLO3_PINMUX(72, 5) +#define UART1TX_P72 APOLLO3_PINMUX(72, 6) +#define UART1RX_P72 APOLLO3_PINMUX(72, 7) +#define SWO_P73 APOLLO3_PINMUX(73, 0) +#define NCE73_P73 APOLLO3_PINMUX(73, 1) +#define CTIM23_P73 APOLLO3_PINMUX(73, 2) +#define GPIO_P73 APOLLO3_PINMUX(73, 3) +#define UA0CTS_P73 APOLLO3_PINMUX(73, 4) +#define UA0RTS_P73 APOLLO3_PINMUX(73, 5) +#define UA1CTS_P73 APOLLO3_PINMUX(73, 6) +#define UA1RTS_P73 APOLLO3_PINMUX(73, 7) + +#endif /* __APOLLO3_PINCTRL_H__ */ diff --git a/soc/ambiq/apollo3x/pinctrl_soc.h b/soc/ambiq/apollo3x/pinctrl_soc.h new file mode 100644 index 00000000000000..1aa6a32d81fd3e --- /dev/null +++ b/soc/ambiq/apollo3x/pinctrl_soc.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_AMBIQ_APOLLO3_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_AMBIQ_APOLLO3_PINCTRL_SOC_H_ + +#include + +/** + * @brief Type to hold a pin's pinctrl configuration. + */ +struct apollo3_pinctrl_soc_pin { + /** Pin number 0..74 */ + uint32_t pin_num: 7; + /** Alternative function (UART, SPI, etc.) */ + uint32_t alt_func: 3; + /** Enable the pin as an input */ + uint32_t input_enable: 1; + /** Drive strength, relative to full-driver strength */ + uint32_t drive_strength: 2; + /** Drive actively high or low */ + uint32_t push_pull: 1; + /** Drive with open drain */ + uint32_t open_drain: 1; + /** High impedance mode */ + uint32_t tristate: 1; + /** Enable the internal pull up resistor */ + uint32_t bias_pull_up: 1; + /** Enable the internal pull down resistor */ + uint32_t bias_pull_down: 1; + /** pullup resistor value */ + uint32_t ambiq_pull_up_ohms: 3; + /** IOM nCE module select */ + uint32_t iom_nce: 2; + /** IOM or MSPI */ + uint32_t iom_mspi: 1; + /** IOM/MSPI instance number */ + uint32_t iom_num: 3; +}; + +typedef struct apollo3_pinctrl_soc_pin pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { \ + APOLLO3_GET_PIN_NUM(DT_PROP_BY_IDX(node_id, prop, idx)), \ + APOLLO3_GET_PIN_ALT_FUNC(DT_PROP_BY_IDX(node_id, prop, idx)), \ + DT_PROP(node_id, input_enable), \ + DT_ENUM_IDX(node_id, drive_strength), \ + DT_PROP(node_id, drive_push_pull), \ + DT_PROP(node_id, drive_open_drain), \ + DT_PROP(node_id, bias_high_impedance), \ + DT_PROP(node_id, bias_pull_up), \ + DT_PROP(node_id, bias_pull_down), \ + DT_ENUM_IDX(node_id, ambiq_pull_up_ohms), \ + DT_PROP(node_id, ambiq_iom_nce_module), \ + DT_PROP(node_id, ambiq_iom_mspi), \ + DT_PROP(node_id, ambiq_iom_num), \ + }, + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { \ + DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT) \ + } + +#define APOLLO3_GET_PIN_NUM(pinctrl) (((pinctrl) >> APOLLO3_PIN_NUM_POS) & APOLLO3_PIN_NUM_MASK) +#define APOLLO3_GET_PIN_ALT_FUNC(pinctrl) \ + (((pinctrl) >> APOLLO3_ALT_FUNC_POS) & APOLLO3_ALT_FUNC_MASK) + +#endif /* ZEPHYR_SOC_ARM_AMBIQ_APOLLO3_PINCTRL_SOC_H_ */ From 47acb6d398256b072de874295862bd28562bafb9 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0269/1389] drivers: serial: pl011: Add support for Ambiq Apollo3 SoCs UART Apollo3 SoCs have different UART register design compared with that of Apollo4 SoCs, we need to change the offset and mask for the power status check Signed-off-by: Hao Luo --- drivers/serial/uart_pl011_ambiq.h | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/serial/uart_pl011_ambiq.h b/drivers/serial/uart_pl011_ambiq.h index 24a356571a21cf..62d6d9291238eb 100644 --- a/drivers/serial/uart_pl011_ambiq.h +++ b/drivers/serial/uart_pl011_ambiq.h @@ -54,17 +54,35 @@ static inline int clk_enable_ambiq_uart(const struct device *dev, uint32_t clk) * Solution: Check device's power status to ensure that register has taken effective. * Note: busy wait is not allowed to use here due to UART is initiated before timer starts. */ - +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +#define DEVPWRSTATUS_OFFSET 0x10 +#define HCPA_MASK 0x4 +#define AMBIQ_UART_DEFINE(n) \ + static int pwr_on_ambiq_uart_##n(void) \ + { \ + uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ + DT_INST_PHA(n, ambiq_pwrcfg, offset); \ + uint32_t pwr_status_addr = addr + DEVPWRSTATUS_OFFSET; \ + sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ + while (!(sys_read32(pwr_status_addr) & HCPA_MASK)) { \ + }; \ + return 0; \ + } \ + static inline int clk_enable_ambiq_uart_##n(const struct device *dev, uint32_t clk) \ + { \ + return clk_enable_ambiq_uart(dev, clk); \ + } +#else +#define DEVPWRSTATUS_OFFSET 0x4 #define AMBIQ_UART_DEFINE(n) \ static int pwr_on_ambiq_uart_##n(void) \ { \ uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ DT_INST_PHA(n, ambiq_pwrcfg, offset); \ - uint32_t pwr_status_addr = addr + 4; \ + uint32_t pwr_status_addr = addr + DEVPWRSTATUS_OFFSET; \ sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ while ((sys_read32(pwr_status_addr) & DT_INST_PHA(n, ambiq_pwrcfg, mask)) != \ DT_INST_PHA(n, ambiq_pwrcfg, mask)) { \ - arch_nop(); \ }; \ return 0; \ } \ @@ -72,5 +90,6 @@ static inline int clk_enable_ambiq_uart(const struct device *dev, uint32_t clk) { \ return clk_enable_ambiq_uart(dev, clk); \ } +#endif #endif /* ZEPHYR_DRIVERS_SERIAL_UART_PL011_AMBIQ_H_ */ From 6a991bcdd1180f79dae9a1ebaf0b95527512bf9c Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:38 +0200 Subject: [PATCH 0270/1389] drivers: timer: Add support for Apollo3 SoCs system timer (STIMER) This commit adds support for the system timer peripheral which can be found in Apollo3 SoCs Signed-off-by: Hao Luo --- drivers/timer/Kconfig.ambiq | 2 +- drivers/timer/ambiq_stimer.c | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/timer/Kconfig.ambiq b/drivers/timer/Kconfig.ambiq index 4d804a76998a97..1c661421e8f8dc 100644 --- a/drivers/timer/Kconfig.ambiq +++ b/drivers/timer/Kconfig.ambiq @@ -10,4 +10,4 @@ config AMBIQ_STIMER_TIMER select TICKLESS_CAPABLE select AMBIQ_HAL_USE_STIMER help - Ambiq Apollo4 stimer driver + Ambiq Apollo stimer driver diff --git a/drivers/timer/ambiq_stimer.c b/drivers/timer/ambiq_stimer.c index 8a469f35907bff..e2c9d9976f4717 100644 --- a/drivers/timer/ambiq_stimer.c +++ b/drivers/timer/ambiq_stimer.c @@ -24,11 +24,10 @@ #define COUNTER_MAX UINT32_MAX -#define CYC_PER_TICK (sys_clock_hw_cycles_per_sec() \ - / CONFIG_SYS_CLOCK_TICKS_PER_SEC) -#define MAX_TICKS ((k_ticks_t)(COUNTER_MAX / CYC_PER_TICK) - 1) -#define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) -#define MIN_DELAY 1 +#define CYC_PER_TICK (sys_clock_hw_cycles_per_sec() / CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#define MAX_TICKS ((k_ticks_t)(COUNTER_MAX / CYC_PER_TICK) - 1) +#define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) +#define MIN_DELAY 1 #define TIMER_IRQ (DT_INST_IRQN(0)) @@ -102,8 +101,7 @@ uint32_t sys_clock_elapsed(void) } k_spinlock_key_t key = k_spin_lock(&g_lock); - uint32_t ret = (am_hal_stimer_counter_get() - - g_last_count) / CYC_PER_TICK; + uint32_t ret = (am_hal_stimer_counter_get() - g_last_count) / CYC_PER_TICK; k_spin_unlock(&g_lock, key); return ret; @@ -121,10 +119,13 @@ static int stimer_init(void) oldCfg = am_hal_stimer_config(AM_HAL_STIMER_CFG_FREEZE); - am_hal_stimer_config((oldCfg & ~(AM_HAL_STIMER_CFG_FREEZE | STIMER_STCFG_CLKSEL_Msk)) - | AM_HAL_STIMER_XTAL_32KHZ - | AM_HAL_STIMER_CFG_COMPARE_A_ENABLE); - +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_stimer_config((oldCfg & ~(AM_HAL_STIMER_CFG_FREEZE | CTIMER_STCFG_CLKSEL_Msk)) | + AM_HAL_STIMER_XTAL_32KHZ | AM_HAL_STIMER_CFG_COMPARE_A_ENABLE); +#else + am_hal_stimer_config((oldCfg & ~(AM_HAL_STIMER_CFG_FREEZE | STIMER_STCFG_CLKSEL_Msk)) | + AM_HAL_STIMER_XTAL_32KHZ | AM_HAL_STIMER_CFG_COMPARE_A_ENABLE); +#endif g_last_count = am_hal_stimer_counter_get(); k_spin_unlock(&g_lock, key); @@ -141,5 +142,4 @@ static int stimer_init(void) return 0; } -SYS_INIT(stimer_init, PRE_KERNEL_2, - CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); +SYS_INIT(stimer_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); From 8561994ad14461625663b24489b4387a81b96429 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0271/1389] drivers: memc: memc_mcux_flexspi: support diff RX clock source on port B Some instances of the FlexSPI IP support a different clock source being used for port B of the FlexSPI instance. Add a devicetree property and driver support to enable configuring this property of the hardware. Signed-off-by: Daniel DeGrasse --- drivers/memc/memc_mcux_flexspi.c | 30 +++++++++++++++++++++++++++ dts/bindings/spi/nxp,imx-flexspi.yaml | 13 ++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index e0c8f6faf963a9..951d3f99a1e940 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -56,6 +56,10 @@ struct memc_flexspi_data { bool combination_mode; bool sck_differential_clock; flexspi_read_sample_clock_t rx_sample_clock; +#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && \ +FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB + flexspi_read_sample_clock_t rx_sample_clock_b; +#endif const struct pinctrl_dev_config *pincfg; size_t size[kFLEXSPI_PortCount]; struct port_lut port_luts[kFLEXSPI_PortCount]; @@ -241,6 +245,14 @@ void *memc_flexspi_get_ahb_address(const struct device *dev, offset += data->size[i]; } +#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) && \ + (FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) + if (data->base->FLSHCR0[port] & FLEXSPI_FLSHCR0_ADDRSHIFT_MASK) { + /* Address shift is set, add 0x1000_0000 to AHB address */ + offset += 0x10000000; + } +#endif + return data->ahb_base + offset; } @@ -282,6 +294,16 @@ static int memc_flexspi_init(const struct device *dev) flexspi_config.enableSckBDiffOpt = data->sck_differential_clock; #endif flexspi_config.rxSampleClock = data->rx_sample_clock; +#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && \ +FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB + flexspi_config.rxSampleClockPortB = data->rx_sample_clock_b; +#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF) && \ + FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF + if (flexspi_config.rxSampleClock != flexspi_config.rxSampleClockPortB) { + flexspi_config.rxSampleClockDiff = true; + } +#endif +#endif /* Configure AHB RX buffers, if any configuration settings are present */ __ASSERT(data->buf_cfg_cnt < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT, @@ -329,6 +351,13 @@ static int memc_flexspi_pm_action(const struct device *dev, enum pm_device_actio } #endif +#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && \ + FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB +#define MEMC_FLEXSPI_RXCLK_B(inst) .rx_sample_clock_b = DT_INST_PROP(inst, rx_clock_source_b), +#else +#define MEMC_FLEXSPI_RXCLK_B(inst) +#endif + #if defined(CONFIG_XIP) && defined(CONFIG_FLASH_MCUX_FLEXSPI_XIP) /* Checks if image flash base address is in the FlexSPI AHB base region */ #define MEMC_FLEXSPI_CFG_XIP(node_id) \ @@ -357,6 +386,7 @@ static int memc_flexspi_pm_action(const struct device *dev, enum pm_device_actio .combination_mode = DT_INST_PROP(n, combination_mode), \ .sck_differential_clock = DT_INST_PROP(n, sck_differential_clock), \ .rx_sample_clock = DT_INST_PROP(n, rx_clock_source), \ + MEMC_FLEXSPI_RXCLK_B(n) \ .buf_cfg = (struct memc_flexspi_buf_cfg *)buf_cfg_##n, \ .buf_cfg_cnt = sizeof(buf_cfg_##n) / \ sizeof(struct memc_flexspi_buf_cfg), \ diff --git a/dts/bindings/spi/nxp,imx-flexspi.yaml b/dts/bindings/spi/nxp,imx-flexspi.yaml index ebb8a08ba12cb0..8a266a8a91dd32 100644 --- a/dts/bindings/spi/nxp,imx-flexspi.yaml +++ b/dts/bindings/spi/nxp,imx-flexspi.yaml @@ -61,6 +61,19 @@ properties: Source clock for flash read. See the RXCLKSRC field in register MCR0. The default corresponds to the reset value of the register field. + rx-clock-source-b: + type: int + default: 0 + enum: + - 0 # Loopback internally + - 1 # Loopback from DQS pad + - 2 # Loopback from SCK pad + - 3 # External input from DQS pad + description: | + Source clock for flash read on port B. Only supported by some instances + of this IP. See the RXCLKSRC_B field in register MCR2. + The default corresponds to the reset value of the register field. + rx-buffer-config: type: array description: | From 9f99c86514701447160d9ead6745ddf70763370a Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0272/1389] drivers: memc: add driver for is66wvq8m4 PSRAM using MCUX FlexSPI Add driver for IS66WVQ8M4 PSRAM, using the MCUX FlexSPI interface to write data to the PSRAM device. Signed-off-by: Daniel DeGrasse --- drivers/memc/CMakeLists.txt | 1 + drivers/memc/Kconfig.mcux | 6 + drivers/memc/memc_mcux_flexspi_is66wvq8m4.c | 249 ++++++++++++++++++ .../mtd/nxp,imx-flexspi-is66wvq8m4.yaml | 8 + 4 files changed, 264 insertions(+) create mode 100644 drivers/memc/memc_mcux_flexspi_is66wvq8m4.c create mode 100644 dts/bindings/mtd/nxp,imx-flexspi-is66wvq8m4.yaml diff --git a/drivers/memc/CMakeLists.txt b/drivers/memc/CMakeLists.txt index 8aaedc2207352f..2e020548610bd3 100644 --- a/drivers/memc/CMakeLists.txt +++ b/drivers/memc/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI memc_mcux_flexspi.c) zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_W956A8MBYA memc_mcux_flexspi_w956a8mbya.c) zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_S27KS0641 memc_mcux_flexspi_s27ks0641.c) zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_APS6408L memc_mcux_flexspi_aps6408l.c) +zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_IS66WVQ8M4 memc_mcux_flexspi_is66wvq8m4.c) zephyr_library_sources_ifdef(CONFIG_MEMC_NXP_FLEXRAM memc_nxp_flexram.c) zephyr_library_sources_ifdef(CONFIG_MEMC_SAM_SMC memc_sam_smc.c) diff --git a/drivers/memc/Kconfig.mcux b/drivers/memc/Kconfig.mcux index e801e7577aeaeb..6d2f30933e96cc 100644 --- a/drivers/memc/Kconfig.mcux +++ b/drivers/memc/Kconfig.mcux @@ -24,6 +24,12 @@ config MEMC_MCUX_FLEXSPI_APS6408L depends on DT_HAS_NXP_IMX_FLEXSPI_APS6408L_ENABLED select MEMC_MCUX_FLEXSPI +config MEMC_MCUX_FLEXSPI_IS66WVQ8M4 + bool "MCUX FlexSPI ISSI IS66WVQ8M4 pSRAM driver" + default y + depends on DT_HAS_NXP_IMX_FLEXSPI_IS66WVQ8M4_ENABLED + select MEMC_MCUX_FLEXSPI + config MEMC_MCUX_FLEXSPI bool select PINCTRL diff --git a/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c b/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c new file mode 100644 index 00000000000000..e3ba54f2a5d68d --- /dev/null +++ b/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c @@ -0,0 +1,249 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #define DT_DRV_COMPAT nxp_imx_flexspi_is66wvq8m4 + + #include + #include + #include + + #include "memc_mcux_flexspi.h" + +LOG_MODULE_REGISTER(memc_flexspi_is66wvq8m4, CONFIG_MEMC_LOG_LEVEL); + +/* Vendor ID for ISSI device */ +#define ISSI_VENDOR_ID 0x3 + +enum { + READ_DATA = 0, + WRITE_DATA, + READ_REG, + WRITE_REG, + READ_ID, +}; + +struct memc_flexspi_is66wvq8m4_config { + flexspi_port_t port; + flexspi_device_config_t config; +}; + +/* Device variables used in critical sections should be in this structure */ +struct memc_flexspi_is66wvq8m4_data { + const struct device *controller; +}; + +/* IS66WVQ8M4 configuration register constants */ +#define IS66WVQ8M4_LATENCY_MASK BIT(3) +#define IS66WVQ8M4_LATENCY_FIXED BIT(3) + +static const uint32_t memc_flexspi_is66wvq8m4_lut[][4] = { + /* Read Data (continuous burst) */ + [READ_DATA] = { + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0xAA, + kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, + kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_4PAD, 28, + kFLEXSPI_Command_READ_DDR, kFLEXSPI_4PAD, 0x01), + }, + /* Write Data (continuous burst) */ + [WRITE_DATA] = { + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x22, + kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, + kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_4PAD, 28, + kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_4PAD, 0x01), + }, + /* Read Register */ + [READ_REG] = { + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0xCC, + kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, + kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_4PAD, 12, + kFLEXSPI_Command_READ_DDR, kFLEXSPI_4PAD, 0x01), + }, + /* Write Register */ + [WRITE_REG] = { + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x66, + kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, + kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_4PAD, 0x01, + kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), + }, + /* Read Identification register */ + [READ_ID] = { + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xE0, + kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16, + kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_4PAD, 0x08), + FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_4PAD, 0x01, + kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), + } +}; + + +/* Read vendor ID from identification register */ +static int memc_flexspi_is66wvq8m4_get_vendor_id(const struct device *dev, + uint8_t *vendor_id) +{ + const struct memc_flexspi_is66wvq8m4_config *config = dev->config; + struct memc_flexspi_is66wvq8m4_data *data = dev->data; + uint32_t buffer = 0; + int ret; + + flexspi_transfer_t transfer = { + .deviceAddress = 0x00, /* Not used by this command */ + .port = config->port, + .cmdType = kFLEXSPI_Read, + .SeqNumber = 1, + .seqIndex = READ_ID, + .data = &buffer, + .dataSize = 2, + }; + + ret = memc_flexspi_transfer(data->controller, &transfer); + *vendor_id = buffer & 0x7; + + return ret; +} + +/* Update configuration register */ +static int memc_flexspi_is66wvq8m4_update_cfg(const struct device *dev, + uint16_t mask, uint16_t set_val) +{ + const struct memc_flexspi_is66wvq8m4_config *config = dev->config; + struct memc_flexspi_is66wvq8m4_data *data = dev->data; + uint32_t buffer = 0; + int ret; + + flexspi_transfer_t transfer = { + /* Results in 0x4 being written on clock 4 */ + .deviceAddress = (0x4 << 9), + .port = config->port, + .cmdType = kFLEXSPI_Read, + .SeqNumber = 1, + .seqIndex = READ_REG, + .data = &buffer, + .dataSize = 2, + }; + + ret = memc_flexspi_transfer(data->controller, &transfer); + if (ret < 0) { + return ret; + } + + buffer &= (~mask & GENMASK(15, 0)); + buffer |= set_val; + + LOG_DBG("Setting cfg reg to 0x%0x", buffer); + + transfer.cmdType = kFLEXSPI_Write, + transfer.seqIndex = WRITE_REG; + + ret = memc_flexspi_transfer(data->controller, &transfer); + return ret; +} + +static int memc_flexspi_is66wvq8m4_init(const struct device *dev) +{ + const struct memc_flexspi_is66wvq8m4_config *config = dev->config; + struct memc_flexspi_is66wvq8m4_data *data = dev->data; + uint8_t vendor_id; + + if (!device_is_ready(data->controller)) { + LOG_ERR("Controller device not ready"); + return -ENODEV; + } + + if (memc_flexspi_set_device_config(data->controller, &config->config, + (const uint32_t *) memc_flexspi_is66wvq8m4_lut, + sizeof(memc_flexspi_is66wvq8m4_lut) / MEMC_FLEXSPI_CMD_SIZE, + config->port)) { + LOG_ERR("Could not set device configuration"); + return -EINVAL; + } + + memc_flexspi_reset(data->controller); + + if (memc_flexspi_is66wvq8m4_get_vendor_id(dev, &vendor_id)) { + LOG_ERR("Could not read vendor id"); + return -EIO; + } + LOG_DBG("Vendor id: 0x%0x", vendor_id); + if (vendor_id != ISSI_VENDOR_ID) { + LOG_WRN("Vendor ID does not match expected value of 0x%0x", + ISSI_VENDOR_ID); + } + + if (memc_flexspi_is66wvq8m4_update_cfg(dev, IS66WVQ8M4_LATENCY_MASK, + IS66WVQ8M4_LATENCY_FIXED)) { + LOG_ERR("Could not set fixed latency mode"); + return -EIO; + } + + return 0; +} + +#define CONCAT3(x, y, z) x ## y ## z + +#define CS_INTERVAL_UNIT(unit) \ + CONCAT3(kFLEXSPI_CsIntervalUnit, unit, SckCycle) + +#define AHB_WRITE_WAIT_UNIT(unit) \ + CONCAT3(kFLEXSPI_AhbWriteWaitUnit, unit, AhbCycle) + +#define MEMC_FLEXSPI_DEVICE_CONFIG(n) \ + { \ + .flexspiRootClk = DT_INST_PROP(n, spi_max_frequency), \ + .isSck2Enabled = false, \ + .flashSize = DT_INST_PROP(n, size) / 8 / KB(1), \ + .addressShift = DT_INST_REG_ADDR(n) != 0, \ + .CSIntervalUnit = \ + CS_INTERVAL_UNIT( \ + DT_INST_PROP(n, cs_interval_unit)), \ + .CSInterval = DT_INST_PROP(n, cs_interval), \ + .CSHoldTime = DT_INST_PROP(n, cs_hold_time), \ + .CSSetupTime = DT_INST_PROP(n, cs_setup_time), \ + .dataValidTime = DT_INST_PROP(n, data_valid_time), \ + .columnspace = DT_INST_PROP(n, column_space), \ + .enableWordAddress = DT_INST_PROP(n, word_addressable), \ + .AWRSeqIndex = WRITE_DATA, \ + .AWRSeqNumber = 1, \ + .ARDSeqIndex = READ_DATA, \ + .ARDSeqNumber = 1, \ + .AHBWriteWaitUnit = \ + AHB_WRITE_WAIT_UNIT( \ + DT_INST_PROP(n, ahb_write_wait_unit)), \ + .AHBWriteWaitInterval = \ + DT_INST_PROP(n, ahb_write_wait_interval), \ + .enableWriteMask = true, \ + } + +#define MEMC_FLEXSPI_IS66WVQ8M4(n) \ + static const struct memc_flexspi_is66wvq8m4_config \ + memc_flexspi_is66wvq8m4_config_##n = { \ + .port = DT_INST_REG_ADDR(n), \ + .config = MEMC_FLEXSPI_DEVICE_CONFIG(n), \ + }; \ + \ + static struct memc_flexspi_is66wvq8m4_data \ + memc_flexspi_is66wvq8m4_data_##n = { \ + .controller = DEVICE_DT_GET(DT_INST_BUS(n)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + memc_flexspi_is66wvq8m4_init, \ + NULL, \ + &memc_flexspi_is66wvq8m4_data_##n, \ + &memc_flexspi_is66wvq8m4_config_##n,\ + POST_KERNEL, \ + CONFIG_MEMC_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(MEMC_FLEXSPI_IS66WVQ8M4) diff --git a/dts/bindings/mtd/nxp,imx-flexspi-is66wvq8m4.yaml b/dts/bindings/mtd/nxp,imx-flexspi-is66wvq8m4.yaml new file mode 100644 index 00000000000000..4b2f2204adf57c --- /dev/null +++ b/dts/bindings/mtd/nxp,imx-flexspi-is66wvq8m4.yaml @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: ISSI IS66WVQ8M4 pSRAM on NXP FlexSPI bus + +compatible: "nxp,imx-flexspi-is66wvq8m4" + +include: nxp,imx-flexspi-device.yaml From 1fe946e37aa95ab3471632cda1a7db3c16d20d6d Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0273/1389] boards: nxp: rd_rw612_bga: add support for IS66 PSRAM Add support for IS66WVQ8M quadspi PSRAM on the RW612 BGA board, and update board pin control to enable muxing PSRAM pins on the FlexSPI. Signed-off-by: Daniel DeGrasse --- boards/nxp/rd_rw612_bga/doc/index.rst | 2 +- .../rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi | 16 +++++++++++++++ boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi | 20 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/boards/nxp/rd_rw612_bga/doc/index.rst b/boards/nxp/rd_rw612_bga/doc/index.rst index c31df4ab448d99..dae43dd8aea778 100644 --- a/boards/nxp/rd_rw612_bga/doc/index.rst +++ b/boards/nxp/rd_rw612_bga/doc/index.rst @@ -45,7 +45,7 @@ Supported Features +-----------+------------+-----------------------------------+ | I2C | on-chip | i2c | +-----------+------------+-----------------------------------+ -| FLEXSPI | on-chip | flash | +| FLEXSPI | on-chip | flash/memc | +-----------+------------+-----------------------------------+ | TRNG | on-chip | entropy | +-----------+------------+-----------------------------------+ diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi index 04140e2a68c794..db565403583f14 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi @@ -70,5 +70,21 @@ slew-rate = "ultra"; bias-pull-down; }; + + group2 { + pinmux = ; + slew-rate = "normal"; + }; + + group3 { + pinmux = ; + slew-rate = "normal"; + bias-pull-down; + }; }; }; diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi index a9f52c885e3398..21872376294bfa 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi @@ -116,6 +116,7 @@ arduino_i2c: &flexcomm2 { ahb-cacheable; ahb-read-addr-opt; rx-clock-source = <1>; + rx-clock-source-b = <3>; pinctrl-0 = <&pinmux_flexspi>; pinctrl-names = "default"; status = "okay"; @@ -156,6 +157,25 @@ arduino_i2c: &flexcomm2 { }; }; }; + is66wvq8m4: is66wvq8m4@2 { + compatible = "nxp,imx-flexspi-is66wvq8m4"; + /* IS66WVQ8M4 is 4MB, 32MBit pSRAM */ + size = ; + reg = <2>; + spi-max-frequency = <256000000>; + /* PSRAM cannot be enabled while board is in default XIP + * configuration, as it will conflict with flash chip. + */ + status = "disabled"; + cs-interval-unit = <1>; + cs-interval = <5>; + cs-hold-time = <2>; + cs-setup-time = <3>; + data-valid-time = <1>; + column-space = <14>; + ahb-write-wait-unit = <2>; + ahb-write-wait-interval = <0>; + }; }; &dmic0 { From 3675b0616db5d4032e23551bb5315e4197235709 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0274/1389] samples: drivers: memc: add support for RW612 BGA board Since the RW612 BGA board's FlexSPI configuration prevents the board from executing from flash while the PSRAM is configured (unless both are configured by a bootloader prior to XIP), run the MEMC sample from internal code SRAM, and write data to the external PSRAM block via the FlexSPI. Signed-off-by: Daniel DeGrasse --- samples/drivers/memc/boards/rd_rw612_bga.conf | 5 +++++ .../drivers/memc/boards/rd_rw612_bga.overlay | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 samples/drivers/memc/boards/rd_rw612_bga.conf create mode 100644 samples/drivers/memc/boards/rd_rw612_bga.overlay diff --git a/samples/drivers/memc/boards/rd_rw612_bga.conf b/samples/drivers/memc/boards/rd_rw612_bga.conf new file mode 100644 index 00000000000000..60bfc1c6262497 --- /dev/null +++ b/samples/drivers/memc/boards/rd_rw612_bga.conf @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# RW is configured to execute from code ram, so use rom loader to load image +CONFIG_NXP_RW_ROM_RAMLOADER=y diff --git a/samples/drivers/memc/boards/rd_rw612_bga.overlay b/samples/drivers/memc/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..d02a07662da1ab --- /dev/null +++ b/samples/drivers/memc/boards/rd_rw612_bga.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,flash = &sram_code; + }; + + aliases { + sram-ext = &is66wvq8m4; + }; +}; + +&is66wvq8m4 { + status = "okay"; +}; From 0f6babc0feb53d00c5e8d809049165001f2ec33f Mon Sep 17 00:00:00 2001 From: Marcin Kajor Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0275/1389] net: if: Extend the usage of rejoining the multicast groups It may happen that the interface is up but not yet running when we issue the rejoin_ipv6_mcast_groups(). This can be fixed by calling this function again right after the iface is set to 'running' state in the notify_iface_up handler. Signed-off-by: Marcin Kajor --- subsys/net/ip/net_if.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 45db9a00f47e5d..7106c38e735a46 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -4979,6 +4979,18 @@ bool net_if_is_offloaded(struct net_if *iface) net_if_is_socket_offloaded(iface)); } +static void rejoin_multicast_groups(struct net_if *iface) +{ +#if defined(CONFIG_NET_NATIVE_IPV6) + rejoin_ipv6_mcast_groups(iface); + if (l2_flags_get(iface) & NET_L2_MULTICAST) { + join_mcast_allnodes(iface); + } +#else + ARG_UNUSED(iface); +#endif +} + static void notify_iface_up(struct net_if *iface) { /* In many places it's assumed that link address was set with @@ -5005,6 +5017,10 @@ static void notify_iface_up(struct net_if *iface) */ if (!net_if_is_offloaded(iface) && !(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) { + /* Make sure that we update the IPv6 addresses and join the + * multicast groups. + */ + rejoin_multicast_groups(iface); iface_ipv6_start(iface); net_ipv4_autoconf_start(iface); } @@ -5126,13 +5142,6 @@ static void init_igmp(struct net_if *iface) #endif } -static void rejoin_multicast_groups(struct net_if *iface) -{ -#if defined(CONFIG_NET_NATIVE_IPV6) - rejoin_ipv6_mcast_groups(iface); -#endif -} - int net_if_up(struct net_if *iface) { int status = 0; @@ -5190,14 +5199,6 @@ int net_if_up(struct net_if *iface) net_mgmt_event_notify(NET_EVENT_IF_ADMIN_UP, iface); update_operational_state(iface); - if (!net_if_is_offloaded(iface)) { - /* Make sure that we update the IPv6 addresses and join the - * multicast groups. - */ - rejoin_multicast_groups(iface); - net_if_start_dad(iface); - } - out: net_if_unlock(iface); From 3187063a070de60c8356cd3b3e5eeea70e0f6004 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0276/1389] Bluetooth: host: handle not getting a buffer net_buf_alloc(K_FOREVER) can now fail (if run from the syswq). Propagate to the caller instead of asserting. Signed-off-by: Jonathan Rico --- subsys/bluetooth/host/hci_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index d20274ecf068c8..d0737cd85fd4c8 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -253,8 +253,12 @@ struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) LOG_DBG("opcode 0x%04x param_len %u", opcode, param_len); + /* net_buf_alloc(K_FOREVER) can fail when run from the syswq */ buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER); - __ASSERT_NO_MSG(buf); + if (!buf) { + LOG_DBG("Unable to allocate a command buffer"); + return NULL; + } LOG_DBG("buf %p", buf); From cd6dca05cbe43cf39018cfcec0d2744dd5ab19b7 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0277/1389] modem_chat: Allow timeout script chat commands Modem chat scripts should be able to add a script command which is simply a delay. The validation of chat scripts currently disallows chat script commands which only have a timeout set. Update modem_chat to allow modem chat script commands which only have a timeout. Additionally do a bit of cleanup to remove duplicate code. Signed-off-by: Bjarki Arge Andreasen --- subsys/modem/modem_chat.c | 77 ++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index d69eb3dd6fc979..51d1cf2e9b60d1 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -142,6 +142,42 @@ static void modem_chat_script_clear_response_matches(struct modem_chat *chat) chat->matches_size[MODEM_CHAT_MATCHES_INDEX_RESPONSE] = 0; } +static bool modem_chat_script_chat_has_request(struct modem_chat *chat) +{ + const struct modem_chat_script_chat *script_chat = + &chat->script->script_chats[chat->script_chat_it]; + + return script_chat->request_size > 0; +} + +static bool modem_chat_script_chat_has_matches(struct modem_chat *chat) +{ + const struct modem_chat_script_chat *script_chat = + &chat->script->script_chats[chat->script_chat_it]; + + return script_chat->response_matches_size > 0; +} + +static uint16_t modem_chat_script_chat_get_send_timeout(struct modem_chat *chat) +{ + const struct modem_chat_script_chat *script_chat = + &chat->script->script_chats[chat->script_chat_it]; + + return script_chat->timeout; +} + +static bool modem_chat_script_chat_has_send_timeout(struct modem_chat *chat) +{ + return modem_chat_script_chat_get_send_timeout(chat) > 0; +} + +static void modem_chat_script_chat_schedule_send_timeout(struct modem_chat *chat) +{ + uint16_t timeout = modem_chat_script_chat_get_send_timeout(chat); + + k_work_schedule(&chat->script_send_timeout_work, K_MSEC(timeout)); +} + static void modem_chat_script_next(struct modem_chat *chat, bool initial) { const struct modem_chat_script_chat *script_chat; @@ -166,13 +202,15 @@ static void modem_chat_script_next(struct modem_chat *chat, bool initial) script_chat = &chat->script->script_chats[chat->script_chat_it]; - /* Check if request must be sent */ - if (script_chat->request_size > 0) { + /* Continue script */ + if (modem_chat_script_chat_has_request(chat)) { LOG_DBG("sending: %.*s", script_chat->request_size, script_chat->request); modem_chat_script_clear_response_matches(chat); modem_chat_script_send(chat); - } else { + } else if (modem_chat_script_chat_has_matches(chat)) { modem_chat_script_set_response_matches(chat); + } else { + modem_chat_script_chat_schedule_send_timeout(chat); } } @@ -226,22 +264,6 @@ static void modem_chat_script_abort_handler(struct k_work *item) modem_chat_script_stop(chat, MODEM_CHAT_SCRIPT_RESULT_ABORT); } -static bool modem_chat_script_chat_is_no_response(struct modem_chat *chat) -{ - const struct modem_chat_script_chat *script_chat = - &chat->script->script_chats[chat->script_chat_it]; - - return (script_chat->response_matches_size == 0); -} - -static uint16_t modem_chat_script_chat_get_send_timeout(struct modem_chat *chat) -{ - const struct modem_chat_script_chat *script_chat = - &chat->script->script_chats[chat->script_chat_it]; - - return script_chat->timeout; -} - /* Returns true when request part has been sent */ static bool modem_chat_send_script_request_part(struct modem_chat *chat) { @@ -286,7 +308,6 @@ static bool modem_chat_send_script_request_part(struct modem_chat *chat) static void modem_chat_script_send_handler(struct k_work *item) { struct modem_chat *chat = CONTAINER_OF(item, struct modem_chat, script_send_work); - uint16_t timeout; if (chat->script == NULL) { return; @@ -313,15 +334,12 @@ static void modem_chat_script_send_handler(struct k_work *item) break; } - if (modem_chat_script_chat_is_no_response(chat)) { - timeout = modem_chat_script_chat_get_send_timeout(chat); - if (timeout == 0) { - modem_chat_script_next(chat, false); - } else { - k_work_schedule(&chat->script_send_timeout_work, K_MSEC(timeout)); - } - } else { + if (modem_chat_script_chat_has_matches(chat)) { modem_chat_script_set_response_matches(chat); + } else if (modem_chat_script_chat_has_send_timeout(chat)) { + modem_chat_script_chat_schedule_send_timeout(chat); + } else { + modem_chat_script_next(chat, false); } } @@ -773,7 +791,8 @@ int modem_chat_run_script_async(struct modem_chat *chat, const struct modem_chat /* Validate script commands */ for (uint16_t i = 0; i < script->script_chats_size; i++) { if ((script->script_chats[i].request_size == 0) && - (script->script_chats[i].response_matches_size == 0)) { + (script->script_chats[i].response_matches_size == 0) && + (script->script_chats[i].timeout == 0)) { return -EINVAL; } } From fd16bf69ddfa594cb61b597f4c289d5459081a36 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0278/1389] tests: modem_chat: Add test for timeout script chat command Adds test for timeout script chat command, which is a script chat command where only the timeout parameter is set. The script will simply wait for the timeout duration, then move on to the next script chat. Signed-off-by: Bjarki Arge Andreasen --- tests/subsys/modem/modem_chat/src/main.c | 66 ++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index f9a37ecc6cc9a2..e589c34bb9287a 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -193,6 +193,19 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE( MODEM_CHAT_SCRIPT_DEFINE(script_partial, script_partial_cmds, abort_matches, on_script_result, 4); +/*************************************************************************************************/ +/* Script containing timeout script chat command */ +/*************************************************************************************************/ +MODEM_CHAT_SCRIPT_CMDS_DEFINE( + script_timeout_cmd_cmds, + MODEM_CHAT_SCRIPT_CMD_RESP("AT", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP_NONE("", 4000), + MODEM_CHAT_SCRIPT_CMD_RESP("AT", ok_match), +); + +MODEM_CHAT_SCRIPT_DEFINE(script_timeout_cmd, script_timeout_cmd_cmds, abort_matches, + on_script_result, 10); + /*************************************************************************************************/ /* Small echo script and mock transactions */ /*************************************************************************************************/ @@ -610,6 +623,59 @@ ZTEST(modem_chat, test_script_run_dynamic_script_sync) zassert_ok(modem_chat_run_script(&cmd, &stack_script), "Failed to run script"); } +ZTEST(modem_chat, test_script_chat_timeout_cmd) +{ + int ret; + bool called; + + zassert_ok(modem_chat_run_script_async(&cmd, &script_timeout_cmd), + "Failed to start script"); + k_msleep(100); + + /* + * Script sends "AT\r\n"; + */ + ret = modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer)); + zassert_equal(ret, sizeof("AT\r\n") - 1); + zassert_true(memcmp(buffer, "AT\r\n", sizeof("AT\r\n") - 1) == 0, + "Request not sent as expected"); + + /* + * Modem responds OK + */ + modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1); + + /* + * Script waits 4 seconds + */ + k_msleep(3000); + zassert_equal(modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer)), 0); + k_msleep(2000); + + /* + * Script sends "AT\r\n"; + */ + ret = modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer)); + zassert_equal(ret, sizeof("AT\r\n") - 1); + zassert_true(memcmp(buffer, "AT\r\n", sizeof("AT\r\n") - 1) == 0, + "Request not sent as expected"); + + /* + * Modem responds OK + */ + modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1); + k_msleep(100); + + called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT); + zassert_true(called == true, "Script callback should have been called"); + zassert_equal(script_result, MODEM_CHAT_SCRIPT_RESULT_SUCCESS, + "Script should have stopped with success"); + + /* Assert no data was sent except the request */ + zassert_equal(modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer)), 0, + "Script sent too many requests"); +} + /*************************************************************************************************/ /* Test suite */ /*************************************************************************************************/ From 54364ac89cb10a1173edb0419f5c22c220a79e44 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0279/1389] net: lwm2m: Fix pull-context on queue mode Two issues fixed: When pull-context is created, it does not have to wake up the RD client context. Ignore the EPERM warning. When new pull-context creates a new socket, sometimes socket-loop gets to recvfrom() before we have set O_NONBLOCK on the socket. So use ZSOCK_MSG_DONTWAIT on zsock_recvfrom() so it does not block the socket loop. Fixes #71450 Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/lwm2m_engine.c | 4 ++-- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index db7906da4cf9ce..50165c1436f5e2 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -681,8 +681,8 @@ static int socket_recv_message(struct lwm2m_ctx *client_ctx) static struct sockaddr from_addr; from_addr_len = sizeof(from_addr); - len = zsock_recvfrom(client_ctx->sock_fd, in_buf, sizeof(in_buf) - 1, 0, &from_addr, - &from_addr_len); + len = zsock_recvfrom(client_ctx->sock_fd, in_buf, sizeof(in_buf) - 1, ZSOCK_MSG_DONTWAIT, + &from_addr, &from_addr_len); if (len < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index f363ffcb034a9e..3596f432476f16 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -673,32 +673,33 @@ int lwm2m_init_message(struct lwm2m_message *msg) int lwm2m_send_message_async(struct lwm2m_message *msg) { - int ret = 0; #if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER) /* check if body encode buffer is in use => packet is not yet prepared for send */ if (msg->body_encode_buffer.data == msg->cpkt.data) { - ret = prepare_msg_for_send(msg); + int ret = prepare_msg_for_send(msg); + if (ret) { lwm2m_reset_message(msg, true); return ret; } } #endif -#if defined(CONFIG_LWM2M_QUEUE_MODE_ENABLED) - ret = lwm2m_rd_client_connection_resume(msg->ctx); - if (ret) { - lwm2m_reset_message(msg, true); - return ret; + if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED)) { + int ret = lwm2m_rd_client_connection_resume(msg->ctx); + + if (ret && ret != -EPERM) { + lwm2m_reset_message(msg, true); + return ret; + } } -#endif sys_slist_append(&msg->ctx->pending_sends, &msg->node); if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED)) { engine_update_tx_time(); } lwm2m_engine_wake_up(); - return ret; + return 0; } int lwm2m_information_interface_send(struct lwm2m_message *msg) From 50b8baf7aa6916694668ac89771fbbd2fb1b8f1a Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0280/1389] samples: wifi: use soc conf and overlay for espressif boards Currently wifi sample code contains a pair of .conf and .overlay for every single esp32-based board. Files are usually identical. This PR remove all esp32* board files and use common socs instead. Signed-off-by: Sylvio Alves --- samples/net/wifi/boards/esp32c3_luatos_core.conf | 11 ----------- .../wifi/boards/esp32c3_luatos_core_esp32c3_usb.conf | 11 ----------- .../boards/esp32c3_luatos_core_esp32c3_usb.overlay | 9 --------- samples/net/wifi/boards/esp32s2_saola.overlay | 9 --------- samples/net/wifi/boards/esp32s3_devkitm_procpu.conf | 11 ----------- .../net/wifi/boards/esp32s3_devkitm_procpu.overlay | 9 --------- .../net/wifi/boards/esp32s3_luatos_core_procpu.conf | 11 ----------- .../wifi/boards/esp32s3_luatos_core_procpu.overlay | 9 --------- .../wifi/boards/esp32s3_luatos_core_procpu_usb.conf | 11 ----------- .../boards/esp32s3_luatos_core_procpu_usb.overlay | 9 --------- samples/net/wifi/boards/m5stickc_plus_procpu.conf | 11 ----------- samples/net/wifi/boards/m5stickc_plus_procpu.overlay | 9 --------- samples/net/wifi/boards/xiao_esp32c3.conf | 11 ----------- samples/net/wifi/boards/xiao_esp32c3.overlay | 9 --------- samples/net/wifi/boards/xiao_esp32s3_procpu.conf | 11 ----------- samples/net/wifi/boards/xiao_esp32s3_procpu.overlay | 9 --------- samples/net/wifi/boards/yd_esp32_procpu.conf | 11 ----------- samples/net/wifi/boards/yd_esp32_procpu.overlay | 9 --------- .../esp32_procpu.conf} | 0 .../esp32_procpu.overlay} | 0 .../esp32c3.conf} | 0 .../esp32c3.overlay} | 0 .../{boards/esp32s2_saola.conf => socs/esp32s2.conf} | 0 .../esp32c3_devkitm.overlay => socs/esp32s2.overlay} | 0 .../esp32c3_devkitm.conf => socs/esp32s3_procpu.conf} | 0 .../esp32s3_procpu.overlay} | 0 26 files changed, 180 deletions(-) delete mode 100644 samples/net/wifi/boards/esp32c3_luatos_core.conf delete mode 100644 samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.conf delete mode 100644 samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.overlay delete mode 100644 samples/net/wifi/boards/esp32s2_saola.overlay delete mode 100644 samples/net/wifi/boards/esp32s3_devkitm_procpu.conf delete mode 100644 samples/net/wifi/boards/esp32s3_devkitm_procpu.overlay delete mode 100644 samples/net/wifi/boards/esp32s3_luatos_core_procpu.conf delete mode 100644 samples/net/wifi/boards/esp32s3_luatos_core_procpu.overlay delete mode 100644 samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.conf delete mode 100644 samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.overlay delete mode 100644 samples/net/wifi/boards/m5stickc_plus_procpu.conf delete mode 100644 samples/net/wifi/boards/m5stickc_plus_procpu.overlay delete mode 100644 samples/net/wifi/boards/xiao_esp32c3.conf delete mode 100644 samples/net/wifi/boards/xiao_esp32c3.overlay delete mode 100644 samples/net/wifi/boards/xiao_esp32s3_procpu.conf delete mode 100644 samples/net/wifi/boards/xiao_esp32s3_procpu.overlay delete mode 100644 samples/net/wifi/boards/yd_esp32_procpu.conf delete mode 100644 samples/net/wifi/boards/yd_esp32_procpu.overlay rename samples/net/wifi/{boards/esp32_devkitc_wroom_procpu.conf => socs/esp32_procpu.conf} (100%) rename samples/net/wifi/{boards/esp32_devkitc_wroom_procpu.overlay => socs/esp32_procpu.overlay} (100%) rename samples/net/wifi/{boards/esp32_devkitc_wrover_procpu.conf => socs/esp32c3.conf} (100%) rename samples/net/wifi/{boards/esp32_devkitc_wrover_procpu.overlay => socs/esp32c3.overlay} (100%) rename samples/net/wifi/{boards/esp32s2_saola.conf => socs/esp32s2.conf} (100%) rename samples/net/wifi/{boards/esp32c3_devkitm.overlay => socs/esp32s2.overlay} (100%) rename samples/net/wifi/{boards/esp32c3_devkitm.conf => socs/esp32s3_procpu.conf} (100%) rename samples/net/wifi/{boards/esp32c3_luatos_core.overlay => socs/esp32s3_procpu.overlay} (100%) diff --git a/samples/net/wifi/boards/esp32c3_luatos_core.conf b/samples/net/wifi/boards/esp32c3_luatos_core.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/esp32c3_luatos_core.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.conf b/samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.overlay b/samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.overlay deleted file mode 100644 index ea9865cf5f8a3f..00000000000000 --- a/samples/net/wifi/boards/esp32c3_luatos_core_esp32c3_usb.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/esp32s2_saola.overlay b/samples/net/wifi/boards/esp32s2_saola.overlay deleted file mode 100644 index ea9865cf5f8a3f..00000000000000 --- a/samples/net/wifi/boards/esp32s2_saola.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/esp32s3_devkitm_procpu.conf b/samples/net/wifi/boards/esp32s3_devkitm_procpu.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/esp32s3_devkitm_procpu.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32s3_devkitm_procpu.overlay b/samples/net/wifi/boards/esp32s3_devkitm_procpu.overlay deleted file mode 100644 index 4d69fe29493052..00000000000000 --- a/samples/net/wifi/boards/esp32s3_devkitm_procpu.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/esp32s3_luatos_core_procpu.conf b/samples/net/wifi/boards/esp32s3_luatos_core_procpu.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/esp32s3_luatos_core_procpu.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32s3_luatos_core_procpu.overlay b/samples/net/wifi/boards/esp32s3_luatos_core_procpu.overlay deleted file mode 100644 index 4d69fe29493052..00000000000000 --- a/samples/net/wifi/boards/esp32s3_luatos_core_procpu.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.conf b/samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.overlay b/samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.overlay deleted file mode 100644 index 4d69fe29493052..00000000000000 --- a/samples/net/wifi/boards/esp32s3_luatos_core_procpu_usb.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/m5stickc_plus_procpu.conf b/samples/net/wifi/boards/m5stickc_plus_procpu.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/m5stickc_plus_procpu.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/m5stickc_plus_procpu.overlay b/samples/net/wifi/boards/m5stickc_plus_procpu.overlay deleted file mode 100644 index ea9865cf5f8a3f..00000000000000 --- a/samples/net/wifi/boards/m5stickc_plus_procpu.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/xiao_esp32c3.conf b/samples/net/wifi/boards/xiao_esp32c3.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/xiao_esp32c3.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/xiao_esp32c3.overlay b/samples/net/wifi/boards/xiao_esp32c3.overlay deleted file mode 100644 index 4d69fe29493052..00000000000000 --- a/samples/net/wifi/boards/xiao_esp32c3.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/xiao_esp32s3_procpu.conf b/samples/net/wifi/boards/xiao_esp32s3_procpu.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/xiao_esp32s3_procpu.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/xiao_esp32s3_procpu.overlay b/samples/net/wifi/boards/xiao_esp32s3_procpu.overlay deleted file mode 100644 index 4d69fe29493052..00000000000000 --- a/samples/net/wifi/boards/xiao_esp32s3_procpu.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/yd_esp32_procpu.conf b/samples/net/wifi/boards/yd_esp32_procpu.conf deleted file mode 100644 index a72fdf39efa245..00000000000000 --- a/samples/net/wifi/boards/yd_esp32_procpu.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_WIFI=y - -CONFIG_NETWORKING=y -CONFIG_NET_L2_ETHERNET=y - -CONFIG_NET_IPV6=n -CONFIG_NET_IPV4=y -CONFIG_NET_DHCPV4=y -CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y - -CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/yd_esp32_procpu.overlay b/samples/net/wifi/boards/yd_esp32_procpu.overlay deleted file mode 100644 index ea9865cf5f8a3f..00000000000000 --- a/samples/net/wifi/boards/yd_esp32_procpu.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&wifi { - status = "okay"; -}; diff --git a/samples/net/wifi/boards/esp32_devkitc_wroom_procpu.conf b/samples/net/wifi/socs/esp32_procpu.conf similarity index 100% rename from samples/net/wifi/boards/esp32_devkitc_wroom_procpu.conf rename to samples/net/wifi/socs/esp32_procpu.conf diff --git a/samples/net/wifi/boards/esp32_devkitc_wroom_procpu.overlay b/samples/net/wifi/socs/esp32_procpu.overlay similarity index 100% rename from samples/net/wifi/boards/esp32_devkitc_wroom_procpu.overlay rename to samples/net/wifi/socs/esp32_procpu.overlay diff --git a/samples/net/wifi/boards/esp32_devkitc_wrover_procpu.conf b/samples/net/wifi/socs/esp32c3.conf similarity index 100% rename from samples/net/wifi/boards/esp32_devkitc_wrover_procpu.conf rename to samples/net/wifi/socs/esp32c3.conf diff --git a/samples/net/wifi/boards/esp32_devkitc_wrover_procpu.overlay b/samples/net/wifi/socs/esp32c3.overlay similarity index 100% rename from samples/net/wifi/boards/esp32_devkitc_wrover_procpu.overlay rename to samples/net/wifi/socs/esp32c3.overlay diff --git a/samples/net/wifi/boards/esp32s2_saola.conf b/samples/net/wifi/socs/esp32s2.conf similarity index 100% rename from samples/net/wifi/boards/esp32s2_saola.conf rename to samples/net/wifi/socs/esp32s2.conf diff --git a/samples/net/wifi/boards/esp32c3_devkitm.overlay b/samples/net/wifi/socs/esp32s2.overlay similarity index 100% rename from samples/net/wifi/boards/esp32c3_devkitm.overlay rename to samples/net/wifi/socs/esp32s2.overlay diff --git a/samples/net/wifi/boards/esp32c3_devkitm.conf b/samples/net/wifi/socs/esp32s3_procpu.conf similarity index 100% rename from samples/net/wifi/boards/esp32c3_devkitm.conf rename to samples/net/wifi/socs/esp32s3_procpu.conf diff --git a/samples/net/wifi/boards/esp32c3_luatos_core.overlay b/samples/net/wifi/socs/esp32s3_procpu.overlay similarity index 100% rename from samples/net/wifi/boards/esp32c3_luatos_core.overlay rename to samples/net/wifi/socs/esp32s3_procpu.overlay From e6046e71182e18986453cdc45441448ed6924636 Mon Sep 17 00:00:00 2001 From: Bram Vlerick Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0281/1389] tests: i2c: i2c_target_api: fix b_u585i_iot02a test The b_u585i_iot02a platform already has an 'eeprom0' node in the default devicetree. Delete the default node so that the overlay can define the nodes needed for the test. Signed-off-by: Bram Vlerick --- tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay b/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay index f07d43230e9090..c1d15d027cc002 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/b_u585i_iot02a.overlay @@ -10,6 +10,8 @@ * Short Pin PB9 to PH5, and PB8 to PH4, for the test to pass. */ +/delete-node/ &eeprom0; + &i2c1 { eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; From 3207b6411a7028a73ef6e4bf0c11f179d07e8b2d Mon Sep 17 00:00:00 2001 From: Romain Pelletant Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0282/1389] pinctrl: stm32: add remap support for STM32C0 Add remap11 and remap12 support for STM32C0 series Signed-off-by: Romain Pelletant --- drivers/pinctrl/pinctrl_stm32.c | 4 ++-- dts/bindings/pinctrl/st,stm32-pinctrl.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index 53c8f2b193cae6..b6a1b550e8bfb4 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -80,8 +80,8 @@ int stm32_pinmux_init_remap(void) #if REMAP_PA11 || REMAP_PA12 -#if !defined(CONFIG_SOC_SERIES_STM32G0X) -#error "Pin remap property available only on STM32G0 SoC series" +#if !defined(CONFIG_SOC_SERIES_STM32G0X) && !defined(CONFIG_SOC_SERIES_STM32C0X) +#error "Pin remap property available only on STM32G0 and STM32C0 SoC series" #endif LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG); diff --git a/dts/bindings/pinctrl/st,stm32-pinctrl.yaml b/dts/bindings/pinctrl/st,stm32-pinctrl.yaml index b412d5dfddb4de..a9f416026435a9 100644 --- a/dts/bindings/pinctrl/st,stm32-pinctrl.yaml +++ b/dts/bindings/pinctrl/st,stm32-pinctrl.yaml @@ -20,12 +20,12 @@ properties: remap-pa11: type: boolean description: Remaps the PA11 pin to operate as PA9 pin. - Use of this property is restricted to STM32G0 SoCs. + Use of this property is restricted to STM32G0 and STM32C0 SoCs. remap-pa12: type: boolean description: Remaps the PA12 pin to operate as PA10 pin. - Use of this property is restricted to STM32G0 SoCs. + Use of this property is restricted to STM32G0 and STM32C0 SoCs. remap-pa11-pa12: type: boolean From 7449a145de8f20e5a46c5d30ba85fcdc6fda40ea Mon Sep 17 00:00:00 2001 From: Romain Pelletant Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0283/1389] boards: st: add pa11 and pa12 remap Add pa11 and pa12 remap to support USART1 via PA9 and PA10 pins Support for VCP is retablished Signed-off-by: Romain Pelletant --- boards/st/stm32c0116_dk/doc/index.rst | 4 ++-- boards/st/stm32c0116_dk/stm32c0116_dk.dts | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/boards/st/stm32c0116_dk/doc/index.rst b/boards/st/stm32c0116_dk/doc/index.rst index ae1ea0223f0a45..a59086c2930418 100644 --- a/boards/st/stm32c0116_dk/doc/index.rst +++ b/boards/st/stm32c0116_dk/doc/index.rst @@ -97,8 +97,8 @@ Default Zephyr Peripheral Mapping: The STM32C0116 Discovery board is configured as follows: -- UART_2 TX/RX : PA2/PA3 (ST-Link Virtual Port Com) -- UART_1 TX/RX : PA9/PA10 +- UART_2 TX/RX : PA2/PA3 +- UART_1 TX/RX : PA9/PA10 (ST-Link Virtual Port Com) - PWM_1_CH3 : PB6 - ADC1_CH8 : PA8 - LD3 : PB6 diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk.dts b/boards/st/stm32c0116_dk/stm32c0116_dk.dts index 24eca6caf94c0d..00a1b134261d5d 100644 --- a/boards/st/stm32c0116_dk/stm32c0116_dk.dts +++ b/boards/st/stm32c0116_dk/stm32c0116_dk.dts @@ -13,8 +13,8 @@ compatible = "st,stm32c011f6-dk"; chosen { - zephyr,console = &usart2; - zephyr,shell-uart = &usart2; + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; }; @@ -65,6 +65,11 @@ apb1-prescaler = <1>; }; +&pinctrl { + remap-pa11; + remap-pa12; +}; + &usart1 { pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; pinctrl-names = "default"; From 1c7125997ca0c9849e3216e3c1a6b93340e8695c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0284/1389] usb: device_next: Properly store enumeration speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing break inside switch statement to allow UDC context to indicate that current operating speed is High-Speed. Due to missing break statement, the stack always assumed Full-Speed. Signed-off-by: Tomasz Moń --- subsys/usb/device_next/usbd_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c index 338a35e206c237..180d136b186115 100644 --- a/subsys/usb/device_next/usbd_core.c +++ b/subsys/usb/device_next/usbd_core.c @@ -120,6 +120,7 @@ static int event_handler_bus_reset(struct usbd_contex *const uds_ctx) switch (udc_speed) { case UDC_BUS_SPEED_HS: uds_ctx->status.speed = USBD_SPEED_HS; + break; default: uds_ctx->status.speed = USBD_SPEED_FS; } From 906e334580eee0d8c91caa2309267b6c62c7c471 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:38:39 +0200 Subject: [PATCH 0285/1389] doc: sysbuild: Fix namespace example The namespace example seems to have a typo missing the CONFIG_ part of the kconfig argument in the mcuboot target, fix it. Signed-off-by: Declan Snyder --- doc/build/sysbuild/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/build/sysbuild/index.rst b/doc/build/sysbuild/index.rst index 55c0c87504e4b7..295b7767555de2 100644 --- a/doc/build/sysbuild/index.rst +++ b/doc/build/sysbuild/index.rst @@ -170,7 +170,7 @@ applying to both images debug optimizations: :board: reel_board :goals: build :west-args: --sysbuild - :gen-args: -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_DEBUG_OPTIMIZATIONS=y -Dmcuboot_DEBUG_OPTIMIZATIONS=y + :gen-args: -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_DEBUG_OPTIMIZATIONS=y -Dmcuboot_CONFIG_DEBUG_OPTIMIZATIONS=y :compact: .. group-tab:: ``cmake`` @@ -180,7 +180,7 @@ applying to both images debug optimizations: :app: share/sysbuild :board: reel_board :goals: build - :gen-args: -DAPP_DIR=samples/hello_world -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_DEBUG_OPTIMIZATIONS=y -Dmcuboot_DEBUG_OPTIMIZATIONS=y + :gen-args: -DAPP_DIR=samples/hello_world -DSB_CONFIG_BOOTLOADER_MCUBOOT=y -DCONFIG_DEBUG_OPTIMIZATIONS=y -Dmcuboot_CONFIG_DEBUG_OPTIMIZATIONS=y :compact: See the following subsections for more information. From 22696149aef6b12e9520f8fc86c42db5d60dc3b4 Mon Sep 17 00:00:00 2001 From: Matthias Alleman Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0286/1389] drivers: ethernet: ksz8863 Fix wrong register for tail tag enable A wrong register address was used to enable tail tagging for the ksz8863 device. Signed-off-by: Matthias Alleman --- drivers/ethernet/dsa_ksz8xxx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ethernet/dsa_ksz8xxx.c b/drivers/ethernet/dsa_ksz8xxx.c index 5ab7a894a7d187..9cf136f7b0114e 100644 --- a/drivers/ethernet/dsa_ksz8xxx.c +++ b/drivers/ethernet/dsa_ksz8xxx.c @@ -281,9 +281,9 @@ static int dsa_ksz8xxx_switch_setup(const struct ksz8xxx_data *pdev) #if defined(CONFIG_DSA_KSZ_TAIL_TAGGING) /* Enable tail tag feature */ - dsa_ksz8xxx_read_reg(pdev, KSZ8863_GLOBAL_CTRL10, &tmp); + dsa_ksz8xxx_read_reg(pdev, KSZ8863_GLOBAL_CTRL1, &tmp); tmp |= KSZ8863_GLOBAL_CTRL1_TAIL_TAG_EN; - dsa_ksz8xxx_write_reg(pdev, KSZ8863_GLOBAL_CTRL10, tmp); + dsa_ksz8xxx_write_reg(pdev, KSZ8863_GLOBAL_CTRL1, tmp); #else /* Disable tail tag feature */ dsa_ksz8xxx_read_reg(pdev, KSZ8863_GLOBAL_CTRL1, &tmp); From 65c6dac8f20622f08dfef05dd0a37116b92fc985 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0287/1389] mbedtls: compile FFDH support in PSA mode Include `psa_crypto_ffdh.c` when compiling MbedTLS with PSA support, as `MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY` references the included functions. Signed-off-by: Jordan Yates --- modules/mbedtls/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 929ea17eceae7b..01a7ed09c28ea8 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -119,6 +119,7 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_cipher.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_driver_wrappers_no_static.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_ecp.c + ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_ffdh.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_hash.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_mac.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_rsa.c From fe8259ed95955460f9046be69c2a6420768a7329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0288/1389] docs: nvme: Fix formatting issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an improperly formatted bullet list due to missing empty line. Signed-off-by: Benjamin Cabé --- doc/services/storage/disk/nvme.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/services/storage/disk/nvme.rst b/doc/services/storage/disk/nvme.rst index efb6a3d7e1fd22..8debbdb18901ab 100644 --- a/doc/services/storage/disk/nvme.rst +++ b/doc/services/storage/disk/nvme.rst @@ -12,9 +12,10 @@ Driver design ************* The driver is sliced up in 3 main parts: -- NVMe controller :zephyr_file:`drivers/disk/nvme/nvme_controller.c` -- NVMe commands :zephyr_file:`drivers/disk/nvme/nvme_cmd.c` -- NVMe namespace :zephyr_file:`drivers/disk/nvme/nvme_namespace.c` + +- NVMe controller: :zephyr_file:`drivers/disk/nvme/nvme_controller.c` +- NVMe commands: :zephyr_file:`drivers/disk/nvme/nvme_cmd.c` +- NVMe namespace: :zephyr_file:`drivers/disk/nvme/nvme_namespace.c` Where the NVMe controller is the root of the device driver. This is the one that will get device driver instances. Note that this is only what DTS describes: the NVMe controller, and none of its namespaces (disks). From 9c723f9756bd7226fdd3fbf0c74c0b0731fc0cc4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0289/1389] llext: add support for STT_OBJECT relocations These relocations are needed e.g. when an LLEXT is built from multiple files and they share data objects. Signed-off-by: Guennadi Liakhovetski --- subsys/llext/llext.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index c92f49abd604ac..d0a04ff7d8c68c 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -471,7 +471,7 @@ static int llext_count_export_syms(struct llext_loader *ldr, struct llext *ext) name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); - if (stt == STT_FUNC && stb == STB_GLOBAL) { + if ((stt == STT_FUNC || stt == STT_OBJECT) && stb == STB_GLOBAL) { LOG_DBG("function symbol %d, name %s, type tag %d, bind %d, sect %d", i, name, stt, stb, sect); ext->sym_tab.sym_cnt++; @@ -562,7 +562,8 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext) uint32_t stb = ELF_ST_BIND(sym.st_info); unsigned int sect = sym.st_shndx; - if (stt == STT_FUNC && stb == STB_GLOBAL && sect != SHN_UNDEF) { + if ((stt == STT_FUNC || stt == STT_OBJECT) && + stb == STB_GLOBAL && sect != SHN_UNDEF) { enum llext_mem mem_idx = ldr->sect_map[sect]; const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); @@ -659,6 +660,7 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, if (stt != STT_FUNC && stt != STT_SECTION && + stt != STT_OBJECT && (stt != STT_NOTYPE || sym_tbl.st_shndx != SHN_UNDEF)) { continue; } From e867b04d8cef244f08737ce2ff2f9b18c5009585 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0290/1389] tests/kernel/context: Detect spurious wakes during timeout check In 972a4d9f6f82c811281fd53ef27a028bf2880955 the test was relaxed to allow a possible parallel thread waking the CPU during the idle timeout checks. How this was done though, a system timer driver which wakes the kernel spuriously a bit before the correct deadline would not be detected, even though it should. Let's fix this, ensuring the timer has been called when we check the wake time in inside the expected range. Signed-off-by: Alberto Escolar Piedras --- tests/kernel/context/src/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/kernel/context/src/main.c b/tests/kernel/context/src/main.c index ff0e0196c90a89..516ddb1ef5bd24 100644 --- a/tests/kernel/context/src/main.c +++ b/tests/kernel/context/src/main.c @@ -245,6 +245,9 @@ static void _test_kernel_cpu_idle(int atomic) k_cpu_idle(); } } while ((idle_loops++ < CONFIG_MAX_IDLE_WAKES) && (idle_timer_done == false)); + zassert_true(idle_timer_done, + "The CPU was waken spuriously too many times (%d > %d)", + idle_loops, CONFIG_MAX_IDLE_WAKES); dt = k_uptime_ticks() - t0; zassert_true(abs((int32_t) (dt - dur)) <= slop, "Inaccurate wakeup, idled for %d ticks, expected %d", From cfa78c35df9e1bb03b723fe834d55eb76246f7ba Mon Sep 17 00:00:00 2001 From: Debbie Martin Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0291/1389] arch: arm: cortex-r: Add compiler tuning for Cortex-R82 Change the GCC toolchain configuration to make use of the Cortex-R82 target. When Cortex-R82 was added as a GCC toolchain option, the GCC version of the Zephyr SDK did not support Cortex-R82 tuning. Zephyr was therefore compiled compiled for the Armv8.4-A architecture. Since Zephyr SDK 0.15.0 (which updated GCC from 10.3.0 to 12.1.0) coupled with Zephyr 3.2, the Cortex-R82 target is supported. The Armv8-R AArch64 architecture does not support the EL3 exception level. EL3 support is therefore made conditional on Armv8-R vs Armv8-A. Signed-off-by: Debbie Martin --- arch/arm64/core/fatal.c | 2 ++ arch/arm64/core/reset.S | 5 +++++ arch/arm64/core/reset.c | 5 +++++ cmake/gcc-m-cpu.cmake | 2 +- include/zephyr/arch/arm64/lib_helpers.h | 4 +++- 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index 5d475e4c655db7..84ff767508ed14 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -313,11 +313,13 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) far = read_far_el1(); elr = read_elr_el1(); break; +#if !defined(CONFIG_ARMV8_R) case MODE_EL3: esr = read_esr_el3(); far = read_far_el3(); elr = read_elr_el3(); break; +#endif /* CONFIG_ARMV8_R */ } #ifdef CONFIG_ARM64_STACK_PROTECTION diff --git a/arch/arm64/core/reset.S b/arch/arm64/core/reset.S index cfcffec4ce7a5c..5e406bea1323d5 100644 --- a/arch/arm64/core/reset.S +++ b/arch/arm64/core/reset.S @@ -43,6 +43,7 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__reset_prep_c) switch_el x0, 3f, 2f, 1f 3: +#if !defined(CONFIG_ARMV8_R) /* Reinitialize SCTLR from scratch in EL3 */ ldr w0, =(SCTLR_EL3_RES1 | SCTLR_I_BIT | SCTLR_SA_BIT) msr sctlr_el3, x0 @@ -55,6 +56,7 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__reset_prep_c) msr sp_el1, x24 b out +#endif /* CONFIG_ARMV8_R */ 2: /* Disable alignment fault checking */ mrs x0, sctlr_el2 @@ -216,7 +218,9 @@ stack_init_done: switch_el: switch_el x0, 3f, 2f, 1f + 3: +#if !defined(CONFIG_ARMV8_R) /* EL3 init */ bl z_arm64_el3_init @@ -224,6 +228,7 @@ switch_el: adr x0, switch_el bl z_arm64_el3_get_next_el eret +#endif /* CONFIG_ARMV8_R */ 2: /* EL2 init */ diff --git a/arch/arm64/core/reset.c b/arch/arm64/core/reset.c index f96783318f40cc..03cf389007d949 100644 --- a/arch/arm64/core/reset.c +++ b/arch/arm64/core/reset.c @@ -41,6 +41,8 @@ void z_arm64_el_highest_init(void) barrier_isync_fence_full(); } + +#if !defined(CONFIG_ARMV8_R) enum el3_next_el { EL3_TO_EL2, EL3_TO_EL1_NO_EL2, @@ -113,6 +115,7 @@ void z_arm64_el3_init(void) z_arm64_el2_init(); } } +#endif /* CONFIG_ARMV8_R */ void z_arm64_el2_init(void) { @@ -195,6 +198,7 @@ void z_arm64_el1_init(void) barrier_isync_fence_full(); } +#if !defined(CONFIG_ARMV8_R) void z_arm64_el3_get_next_el(uint64_t switch_addr) { uint64_t spsr; @@ -214,3 +218,4 @@ void z_arm64_el3_get_next_el(uint64_t switch_addr) write_spsr_el3(spsr); } +#endif /* CONFIG_ARMV8_R */ diff --git a/cmake/gcc-m-cpu.cmake b/cmake/gcc-m-cpu.cmake index ae10132dfc04c0..8b02d7bee86c93 100644 --- a/cmake/gcc-m-cpu.cmake +++ b/cmake/gcc-m-cpu.cmake @@ -83,7 +83,7 @@ elseif("${ARCH}" STREQUAL "arm64") elseif(CONFIG_CPU_CORTEX_A72) set(GCC_M_CPU cortex-a72) elseif(CONFIG_CPU_CORTEX_R82) - set(GCC_M_ARCH armv8.4-a+nolse) + set(GCC_M_CPU cortex-r82) endif() elseif("${ARCH}" STREQUAL "arc") if(CONFIG_CPU_EM4_FPUS) diff --git a/include/zephyr/arch/arm64/lib_helpers.h b/include/zephyr/arch/arm64/lib_helpers.h index 56dfa1f936503b..0f3d9d563abe24 100644 --- a/include/zephyr/arch/arm64/lib_helpers.h +++ b/include/zephyr/arch/arm64/lib_helpers.h @@ -70,8 +70,10 @@ MAKE_REG_HELPER(hcr_el2); MAKE_REG_HELPER(id_aa64pfr0_el1); MAKE_REG_HELPER(id_aa64mmfr0_el1); MAKE_REG_HELPER(mpidr_el1); -MAKE_REG_HELPER(par_el1) +MAKE_REG_HELPER(par_el1); +#if !defined(CONFIG_ARMV8_R) MAKE_REG_HELPER(scr_el3); +#endif /* CONFIG_ARMV8_R */ MAKE_REG_HELPER(tpidrro_el0); MAKE_REG_HELPER(vmpidr_el2); MAKE_REG_HELPER(sp_el0); From d76885a07f502bcc5234f2c0499fe468dc56cb3b Mon Sep 17 00:00:00 2001 From: Nicolas Goualard Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0292/1389] boards: Round Display for Xiao Added the Round Display for Xiao boards as a shield. Added a xiao_adc node to Xiao board dtsi files. Signed-off-by: Nicolas Goualard --- .../seeeduino_xiao/seeed_xiao_connector.dtsi | 1 + .../seeed/xiao_ble/seeed_xiao_connector.dtsi | 1 + .../xiao_esp32c3/seeed_xiao_connector.dtsi | 1 + .../xiao_esp32s3/seeed_xiao_connector.dtsi | 1 + .../Kconfig.defconfig | 23 +++++ .../seeed_xiao_round_display/Kconfig.shield | 5 + .../doc/img/seeed_xiao_round_display.webp | Bin 0 -> 19940 bytes .../seeed_xiao_round_display/doc/index.rst | 40 ++++++++ .../seeed_xiao_round_display.overlay | 87 ++++++++++++++++++ samples/subsys/display/lvgl/README.rst | 3 +- 10 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 boards/shields/seeed_xiao_round_display/Kconfig.defconfig create mode 100644 boards/shields/seeed_xiao_round_display/Kconfig.shield create mode 100644 boards/shields/seeed_xiao_round_display/doc/img/seeed_xiao_round_display.webp create mode 100644 boards/shields/seeed_xiao_round_display/doc/index.rst create mode 100644 boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay diff --git a/boards/seeed/seeeduino_xiao/seeed_xiao_connector.dtsi b/boards/seeed/seeeduino_xiao/seeed_xiao_connector.dtsi index e4709327113f8e..b149504e0a2738 100644 --- a/boards/seeed/seeeduino_xiao/seeed_xiao_connector.dtsi +++ b/boards/seeed/seeeduino_xiao/seeed_xiao_connector.dtsi @@ -30,3 +30,4 @@ xiao_spi: &sercom0 {}; xiao_i2c: &sercom2 {}; xiao_serial: &sercom4 {}; xiao_dac: &dac0 {}; +xiao_adc: &adc {}; diff --git a/boards/seeed/xiao_ble/seeed_xiao_connector.dtsi b/boards/seeed/xiao_ble/seeed_xiao_connector.dtsi index 4f0c1ad983fbc9..e4c7077c9224a3 100644 --- a/boards/seeed/xiao_ble/seeed_xiao_connector.dtsi +++ b/boards/seeed/xiao_ble/seeed_xiao_connector.dtsi @@ -30,3 +30,4 @@ xiao_spi: &spi2 {}; xiao_i2c: &i2c1 {}; xiao_serial: &uart0 {}; +xiao_adc: &adc {}; diff --git a/boards/seeed/xiao_esp32c3/seeed_xiao_connector.dtsi b/boards/seeed/xiao_esp32c3/seeed_xiao_connector.dtsi index 08bd5d76d9ff0f..23eab39a85cb8a 100644 --- a/boards/seeed/xiao_esp32c3/seeed_xiao_connector.dtsi +++ b/boards/seeed/xiao_esp32c3/seeed_xiao_connector.dtsi @@ -27,3 +27,4 @@ xiao_spi: &spi2 {}; xiao_i2c: &i2c0 {}; xiao_serial: &uart0 {}; +xiao_adc: &adc0 {}; diff --git a/boards/seeed/xiao_esp32s3/seeed_xiao_connector.dtsi b/boards/seeed/xiao_esp32s3/seeed_xiao_connector.dtsi index 73fe66d28dcc9e..cc2f2f34f142c7 100644 --- a/boards/seeed/xiao_esp32s3/seeed_xiao_connector.dtsi +++ b/boards/seeed/xiao_esp32s3/seeed_xiao_connector.dtsi @@ -27,3 +27,4 @@ xiao_spi: &spi2 {}; xiao_i2c: &i2c0 {}; xiao_serial: &uart0 {}; +xiao_adc: &adc0 {}; diff --git a/boards/shields/seeed_xiao_round_display/Kconfig.defconfig b/boards/shields/seeed_xiao_round_display/Kconfig.defconfig new file mode 100644 index 00000000000000..81cbf3807452a2 --- /dev/null +++ b/boards/shields/seeed_xiao_round_display/Kconfig.defconfig @@ -0,0 +1,23 @@ +# Copyright (c) 2024 Nicolas Goualard +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_SEEED_XIAO_ROUND_DISPLAY + +if DISPLAY + +if LVGL + +config INPUT + default y + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +config LV_COLOR_16_SWAP + default y + +endif # LVGL +endif # DISPLAY + +endif # SHIELD_XIAO_ROUND_DISPLAY diff --git a/boards/shields/seeed_xiao_round_display/Kconfig.shield b/boards/shields/seeed_xiao_round_display/Kconfig.shield new file mode 100644 index 00000000000000..0d0ed03c59b1b5 --- /dev/null +++ b/boards/shields/seeed_xiao_round_display/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nicolas Goualard +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_SEEED_XIAO_ROUND_DISPLAY + def_bool $(shields_list_contains,seeed_xiao_round_display) diff --git a/boards/shields/seeed_xiao_round_display/doc/img/seeed_xiao_round_display.webp b/boards/shields/seeed_xiao_round_display/doc/img/seeed_xiao_round_display.webp new file mode 100644 index 0000000000000000000000000000000000000000..7da04f4e91beab0e76bb30ee618408c20a5f819b GIT binary patch literal 19940 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 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + chosen { + zephyr,display = &gc9a01_xiao_round_display; + }; + + vbatt { + compatible = "voltage-divider"; + io-channels = <&xiao_adc 0>; + output-ohms = <470000>; + full-ohms = <940000>; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&chsc6x_xiao_round_display>; + }; + + aliases { + rtc = &pcf8563_xiao_round_display; + }; +}; + +&xiao_adc { + status = "okay"; +}; + +/* + * xiao_serial uses pins D6 and D7 of the Xiao, which are used respectively to + * control the screen backlight and as touch controller interrupt. + */ +&xiao_serial { + status = "disabled"; +}; + +&xiao_i2c { + clock-frequency = < I2C_BITRATE_FAST >; + + pcf8563_xiao_round_display: pcf8563@51 { + status = "okay"; + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + + chsc6x_xiao_round_display: chsc6x@2e { + status = "okay"; + compatible = "chipsemi,chsc6x"; + reg = <0x2e>; + irq-gpios = <&xiao_d 7 GPIO_ACTIVE_LOW>; + }; +}; + +&xiao_spi { + status = "okay"; + cs-gpios = <&xiao_d 1 GPIO_ACTIVE_LOW>, <&xiao_d 2 GPIO_ACTIVE_LOW>; + + gc9a01_xiao_round_display: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + spi-max-frequency = ; + cmd-data-gpios = <&xiao_d 3 GPIO_ACTIVE_HIGH>; + pixel-format = ; + width = <240>; + height = <240>; + display-inversion; + }; + + sdhc_xiao_round_display: sdhc@1 { + compatible = "zephyr,sdhc-spi-slot"; + reg = <1>; + status = "okay"; + mmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; + spi-max-frequency = ; + }; +}; diff --git a/samples/subsys/display/lvgl/README.rst b/samples/subsys/display/lvgl/README.rst index a4e2f401bda70b..259413c4ac30b9 100644 --- a/samples/subsys/display/lvgl/README.rst +++ b/samples/subsys/display/lvgl/README.rst @@ -36,11 +36,12 @@ Requirements ************ Display shield and a board which provides a configuration -for Arduino connectors, for example: +for corresponding connectors, for example: - :ref:`adafruit_2_8_tft_touch_v2` and :ref:`nrf52840dk_nrf52840` - :ref:`buydisplay_2_8_tft_touch_arduino` and :ref:`nrf52840dk_nrf52840` - :ref:`ssd1306_128_shield` and :ref:`frdm_k64f` +- :ref:`seeed_xiao_round_display` and :ref:`xiao_ble` or a board with an integrated display: From f0aed030293ba542db8f0180d49d73a0bcb046dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0293/1389] tfm: cmake: Delete dead CMake code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code appears to be dead so we delete it. Signed-off-by: Sebastian Bøe --- modules/trusted-firmware-m/CMakeLists.txt | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 6dde3956c15f6a..5e551777080ff4 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -15,21 +15,6 @@ set(TFM_VALID_PARTITIONS TFM_PARTITION_FIRMWARE_UPDATE ) -# List of all crypto modules that can be enabled/disabled -# Corresponds to the *_MODULE_DISABLED configs in 'trusted-firmware-m/secure_fw/partitions/crypto/Kconfig' -set(TFM_CRYPTO_MODULES - CRYPTO_RNG_MODULE - CRYPTO_KEY_MODULE - CRYPTO_AEAD_MODULE - CRYPTO_MAC_MODULE - CRYPTO_HASH_MODULE - CRYPTO_CIPHER_MODULE - CRYPTO_ASYM_SIGN_MODULE - CRYPTO_ASYM_ENCRYPT_MODULE - CRYPTO_KEY_DERIVATION_MODULE - ) - - if (CONFIG_BUILD_WITH_TFM) # PSA API awareness for the Non-Secure application target_compile_definitions(app PRIVATE "TFM_PSA_API") @@ -148,14 +133,6 @@ if (CONFIG_BUILD_WITH_TFM) list(APPEND TFM_CMAKE_ARGS -D${partition}=${val}) endforeach() - # Enable TFM crypto modules as specified in Kconfig - foreach(module ${TFM_CRYPTO_MODULES}) - if (CONFIG_TFM_${module}_ENABLED) - # list(APPEND TFM_ENABLED_CRYPTO_MODULES_ARG ${module}) - list(APPEND TFM_CMAKE_ARGS -D${module}_ENABLED=True) - endif() - endforeach() - set(TFM_BINARY_DIR ${CMAKE_BINARY_DIR}/tfm) set(PSA_ARCH_TESTS_PATH ${ZEPHYR_CURRENT_MODULE_DIR}/../psa-arch-tests) From 78496567c3c30d14a715aa52879ad7d74da06bd2 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0294/1389] linker: Move iterable subalign value from header to kconfig Add a Kconfig option for iterable section subalignment. Signed-off-by: Pieter De Gendt --- Kconfig.zephyr | 7 +++++++ include/zephyr/linker/iterable_sections.h | 6 +----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Kconfig.zephyr b/Kconfig.zephyr index edb9a7959303df..fd9076a38d94f6 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -316,6 +316,13 @@ config LINKER_USE_RELAX endmenu # "Linker Sections" +config LINKER_ITERABLE_SUBALIGN + int + default 8 if 64BIT + default 4 + help + Hidden option for the default subalignment of iterable sections. + config LINKER_DEVNULL_SUPPORT bool default y if CPU_CORTEX_M || (RISCV && !64BIT) diff --git a/include/zephyr/linker/iterable_sections.h b/include/zephyr/linker/iterable_sections.h index 397ff155e032fb..3eb4e9527b8d10 100644 --- a/include/zephyr/linker/iterable_sections.h +++ b/include/zephyr/linker/iterable_sections.h @@ -32,11 +32,7 @@ *(SORT_BY_NAME(._##struct_type.static.*)); \ _CONCAT(_##struct_type, _list_end) = . -#ifdef CONFIG_64BIT -#define Z_LINK_ITERABLE_SUBALIGN 8 -#else -#define Z_LINK_ITERABLE_SUBALIGN 4 -#endif +#define Z_LINK_ITERABLE_SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN /** * @brief Define a read-only iterable section output. From 2723c239f1a53f1f7bc639019a756e5a84878808 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0295/1389] cmake: linker: Use kconfig for iterable section subalign Replace the hard-coded 4 with the Kconfig symbol CONFIG_LINKER_ITERABLE_SECTION_SUBALIGN . Signed-off-by: Pieter De Gendt --- cmake/linker_script/common/common-ram.cmake | 82 +++++++++--------- cmake/linker_script/common/common-rom.cmake | 86 +++++++++---------- subsys/net/conn_mgr/CMakeLists.txt | 2 +- subsys/net/l2/wifi/CMakeLists.txt | 2 +- tests/misc/iterable_sections/CMakeLists.txt | 20 ++--- .../net/lib/http_server/common/CMakeLists.txt | 4 +- .../net/lib/http_server/crime/CMakeLists.txt | 2 +- .../lib/http_server/prototype/CMakeLists.txt | 2 +- tests/net/lib/http_server/tls/CMakeLists.txt | 2 +- 9 files changed, 101 insertions(+), 101 deletions(-) diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index f2ac29fd0d9a34..04f6637a9e16a6 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -18,10 +18,10 @@ zephyr_linker_section_configure(SECTION device_states ) if(CONFIG_PM_DEVICE) - zephyr_iterable_section(NAME pm_device_slots GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME pm_device_slots GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() -zephyr_iterable_section(NAME log_dynamic GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +zephyr_iterable_section(NAME log_dynamic GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_USERSPACE) # All kernel objects within are assumed to be either completely @@ -32,34 +32,34 @@ if(CONFIG_USERSPACE) # _static_kernel_objects_begin = .; endif() -zephyr_iterable_section(NAME k_timer GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_mem_slab GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_heap GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_mutex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_stack GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_msgq GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_mbox GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_pipe GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_sem GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_queue GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_condvar GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME k_event GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +zephyr_iterable_section(NAME k_timer GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_mem_slab GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_heap GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_mutex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_stack GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_msgq GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_mbox GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_pipe GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_sem GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_queue GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_condvar GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME k_event GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME net_buf_pool GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +zephyr_iterable_section(NAME net_buf_pool GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_NETWORKING) - zephyr_iterable_section(NAME net_if GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME net_if_dev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME net_l2 GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME eth_bridge GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME net_if GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME net_if_dev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME net_l2 GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME eth_bridge GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_SENSING) - zephyr_iterable_section(NAME sensing_sensor GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME sensing_sensor GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_UART_MUX) - zephyr_iterable_section(NAME uart_mux GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME uart_mux GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_USB_DEVICE_STACK) @@ -82,8 +82,8 @@ if(CONFIG_USB_DEVICE_BOS) endif() if(CONFIG_RTIO) - zephyr_iterable_section(NAME rtio GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME rtio_iodev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME rtio GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME rtio_iodev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() #if(CONFIG_USERSPACE) @@ -92,44 +92,44 @@ endif() # if(CONFIG_ZTEST) - zephyr_iterable_section(NAME ztest_suite_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME ztest_suite_stats GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME ztest_unit_test GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME ztest_test_rule GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME ztest_expected_result_entry GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME ztest_suite_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME ztest_suite_stats GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME ztest_unit_test GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME ztest_test_rule GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME ztest_expected_result_entry GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_ZBUS) - zephyr_iterable_section(NAME zbus_observer GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME zbus_channel_observation_mask GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME zbus_observer GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME zbus_channel_observation_mask GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_UVB) - zephyr_iterable_section(NAME uvb_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME uvb_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_LOG) - zephyr_iterable_section(NAME log_mpsc_pbuf GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME log_msg_ptr GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME log_mpsc_pbuf GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME log_msg_ptr GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_PCIE) - zephyr_iterable_section(NAME pcie_dev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME pcie_dev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_USB_DEVICE_STACK OR CONFIG_USB_DEVICE_STACK_NEXT) - zephyr_iterable_section(NAME usb_cfg_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME usbd_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME usbd_class_fs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME usbd_class_hs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME usb_cfg_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME usbd_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME usbd_class_fs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME usbd_class_hs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_USB_HOST_STACK) - zephyr_iterable_section(NAME usbh_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) - zephyr_iterable_section(NAME usbh_class_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME usbh_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME usbh_class_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_DEVICE_MUTABLE) - zephyr_iterable_section(NAME device_mutable GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) + zephyr_iterable_section(NAME device_mutable GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index 77cd911ab4fa03..dfd5ba8b9e3483 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -8,7 +8,7 @@ zephyr_linker_section_obj_level(SECTION init LEVEL POST_KERNEL) zephyr_linker_section_obj_level(SECTION init LEVEL APPLICATION) zephyr_linker_section_obj_level(SECTION init LEVEL SMP) -zephyr_iterable_section(NAME device NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME device NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_GEN_SW_ISR_TABLE AND NOT CONFIG_DYNAMIC_INTERRUPTS) # ld align has been changed to subalign to provide identical behavior scatter vs. ld. @@ -89,98 +89,98 @@ zephyr_linker_section_configure( ) if(CONFIG_NET_SOCKETS) - zephyr_iterable_section(NAME net_socket_register KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME net_socket_register KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_NET_L2_PPP) - zephyr_iterable_section(NAME ppp_protocol_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME ppp_protocol_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() -zephyr_iterable_section(NAME bt_l2cap_fixed_chan KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME bt_l2cap_fixed_chan KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_BT_CLASSIC) - zephyr_iterable_section(NAME bt_l2cap_br_fixed_chan KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_l2cap_br_fixed_chan KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_BT_CONN) - zephyr_iterable_section(NAME bt_conn_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_conn_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() -zephyr_iterable_section(NAME bt_gatt_service_static KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME bt_gatt_service_static KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_BT_MESH) - zephyr_iterable_section(NAME bt_mesh_subnet_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) - zephyr_iterable_section(NAME bt_mesh_app_key_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_mesh_subnet_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME bt_mesh_app_key_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) - zephyr_iterable_section(NAME bt_mesh_hb_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_mesh_hb_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_BT_MESH_FRIEND) - zephyr_iterable_section(NAME bt_mesh_friend_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_mesh_friend_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_BT_MESH_LOW_POWER) - zephyr_iterable_section(NAME bt_mesh_lpn_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_mesh_lpn_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_BT_MESH_PROXY) - zephyr_iterable_section(NAME bt_mesh_proxy_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_mesh_proxy_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_EC_HOST_CMD) - zephyr_iterable_section(NAME ec_host_cmd_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME ec_host_cmd_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_SETTINGS) - zephyr_iterable_section(NAME settings_handler_static KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME settings_handler_static KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_SENSING) - zephyr_iterable_section(NAME sensing_sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME sensing_sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_SENSOR_INFO) - zephyr_iterable_section(NAME sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_SENSOR_ASYNC_API) - zephyr_iterable_section(NAME sensor_decoder_api KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME sensor_decoder_api KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_MCUMGR) - zephyr_iterable_section(NAME mcumgr_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME mcumgr_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() -zephyr_iterable_section(NAME k_p4wq_initparam KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME k_p4wq_initparam KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_EMUL) - zephyr_iterable_section(NAME emul KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME emul KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_DNS_SD) - zephyr_iterable_section(NAME dns_sd_rec KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME dns_sd_rec KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_PCIE) - zephyr_iterable_section(NAME irq_alloc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME irq_alloc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() -zephyr_iterable_section(NAME log_strings KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME log_strings KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME log_const KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME log_const KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME shell KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME shell KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME shell_root_cmds KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME shell_root_cmds KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME shell_subcmds KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME shell_subcmds KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME shell_dynamic_subcmds KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME shell_dynamic_subcmds KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME cfb_font KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME cfb_font KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -zephyr_iterable_section(NAME tracing_backend KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME tracing_backend KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) zephyr_linker_section(NAME zephyr_dbg_info KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT}) zephyr_linker_section_configure(SECTION zephyr_dbg_info INPUT ".zephyr_dbg_info" KEEP) @@ -191,39 +191,39 @@ if (CONFIG_DEVICE_DEPS) zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass2* KEEP SORT NAME PASS NOT LINKER_DEVICE_DEPS_PASS1) endif() -zephyr_iterable_section(NAME _static_thread_data KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME _static_thread_data KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if (CONFIG_BT_IAS) - zephyr_iterable_section(NAME bt_ias_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME bt_ias_cb KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if (CONFIG_LOG) - zephyr_iterable_section(NAME log_link KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) - zephyr_iterable_section(NAME log_backend KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME log_link KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME log_backend KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if (CONFIG_HTTP_SERVER) - zephyr_iterable_section(NAME http_service_desc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME http_service_desc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_INPUT) - zephyr_iterable_section(NAME input_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME input_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_USBD_MSC_CLASS) - zephyr_iterable_section(NAME usbd_msc_lun KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME usbd_msc_lun KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_ZBUS) - zephyr_iterable_section(NAME zbus_channel KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) - zephyr_iterable_section(NAME zbus_observer KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) - zephyr_iterable_section(NAME zbus_channel_observation KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME zbus_channel KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME zbus_observer KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME zbus_channel_observation KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_GNSS) - zephyr_iterable_section(NAME gnss_data_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME gnss_data_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() if(CONFIG_GNSS_SATELLITES) - zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) + zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() diff --git a/subsys/net/conn_mgr/CMakeLists.txt b/subsys/net/conn_mgr/CMakeLists.txt index 567bbf07d69e65..68ca0f1388fa0f 100644 --- a/subsys/net/conn_mgr/CMakeLists.txt +++ b/subsys/net/conn_mgr/CMakeLists.txt @@ -10,4 +10,4 @@ zephyr_library_sources( ) zephyr_linker_sources(DATA_SECTIONS conn_mgr.ld) -zephyr_iterable_section(NAME conn_mgr_conn_binding GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +zephyr_iterable_section(NAME conn_mgr_conn_binding GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) diff --git a/subsys/net/l2/wifi/CMakeLists.txt b/subsys/net/l2/wifi/CMakeLists.txt index aaf825599f009c..c834c5bfc2f756 100644 --- a/subsys/net/l2/wifi/CMakeLists.txt +++ b/subsys/net/l2/wifi/CMakeLists.txt @@ -17,5 +17,5 @@ zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_UTILS wifi_utils.c) # Linker section placement for wifi_nm_instance iterable structure zephyr_linker_sources_ifdef(CONFIG_WIFI_NM DATA_SECTIONS wifi_nm.ld) if (CONFIG_WIFI_NM) -zephyr_iterable_section(NAME wifi_nm_instance GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +zephyr_iterable_section(NAME wifi_nm_instance GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() diff --git a/tests/misc/iterable_sections/CMakeLists.txt b/tests/misc/iterable_sections/CMakeLists.txt index 1a187eace6d8fe..350c2a5ca0efed 100644 --- a/tests/misc/iterable_sections/CMakeLists.txt +++ b/tests/misc/iterable_sections/CMakeLists.txt @@ -8,15 +8,15 @@ FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) zephyr_linker_sources(DATA_SECTIONS sections-ram.ld) -zephyr_iterable_section(NAME test_ram GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME test_ram2 GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME test_ram_named GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME test_ram_numeric NUMERIC GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) -zephyr_iterable_section(NAME ramn_alt GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +zephyr_iterable_section(NAME test_ram GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME test_ram2 GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME test_ram_named GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME test_ram_numeric NUMERIC GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME ramn_alt GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) zephyr_linker_sources(SECTIONS sections-rom.ld) -zephyr_iterable_section(NAME test_rom KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) -zephyr_iterable_section(NAME test_rom2 KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) -zephyr_iterable_section(NAME test_rom_named KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) -zephyr_iterable_section(NAME test_rom_numeric NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) -zephyr_iterable_section(NAME romn_alt KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME test_rom KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME test_rom2 KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME test_rom_named KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME test_rom_numeric NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME romn_alt KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) diff --git a/tests/net/lib/http_server/common/CMakeLists.txt b/tests/net/lib/http_server/common/CMakeLists.txt index 1a775236a5d9dc..add7abe2de3447 100644 --- a/tests/net/lib/http_server/common/CMakeLists.txt +++ b/tests/net/lib/http_server/common/CMakeLists.txt @@ -8,5 +8,5 @@ FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) zephyr_linker_sources(SECTIONS sections-rom.ld) -zephyr_iterable_section(NAME http_resource_desc_service_A KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) -zephyr_iterable_section(NAME http_resource_desc_service_B KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME http_resource_desc_service_A KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +zephyr_iterable_section(NAME http_resource_desc_service_B KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) diff --git a/tests/net/lib/http_server/crime/CMakeLists.txt b/tests/net/lib/http_server/crime/CMakeLists.txt index 9ccfbe570b3847..d991ae1d3f6bd9 100644 --- a/tests/net/lib/http_server/crime/CMakeLists.txt +++ b/tests/net/lib/http_server/crime/CMakeLists.txt @@ -21,4 +21,4 @@ generate_inc_file_for_target(app ${source_file_not_found} ${gen_dir}/not_found_p generate_inc_file_for_target(app ${source_file_not_found} ${gen_dir}/not_found_page.html.gz.inc --gzip) zephyr_linker_sources(SECTIONS sections-rom.ld) -zephyr_iterable_section(NAME http_resource_desc_test_http_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME http_resource_desc_test_http_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) diff --git a/tests/net/lib/http_server/prototype/CMakeLists.txt b/tests/net/lib/http_server/prototype/CMakeLists.txt index 4842b309490796..8ba8aa71fc523b 100644 --- a/tests/net/lib/http_server/prototype/CMakeLists.txt +++ b/tests/net/lib/http_server/prototype/CMakeLists.txt @@ -15,4 +15,4 @@ set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) target_link_libraries(app PRIVATE zephyr_interface zephyr) zephyr_linker_sources(SECTIONS sections-rom.ld) -zephyr_iterable_section(NAME http_resource_desc_test_http_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME http_resource_desc_test_http_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) diff --git a/tests/net/lib/http_server/tls/CMakeLists.txt b/tests/net/lib/http_server/tls/CMakeLists.txt index f72aa8b44769ec..35f1805f63e468 100644 --- a/tests/net/lib/http_server/tls/CMakeLists.txt +++ b/tests/net/lib/http_server/tls/CMakeLists.txt @@ -51,4 +51,4 @@ FILE(GLOB app_sources src/main.c) target_sources(app PRIVATE ${app_sources}) zephyr_linker_sources(SECTIONS sections-rom.ld) -zephyr_iterable_section(NAME http_resource_desc_test_http_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +zephyr_iterable_section(NAME http_resource_desc_test_http_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) From 32cf4f079963682161a94140a873cb04df41c971 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0296/1389] west: openocd: find path intree when run package from another PC, the openocd path may not the same, so try to use ZEPHYR_BASE when not aligned Signed-off-by: Hake Huang --- scripts/west_commands/runners/openocd.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/west_commands/runners/openocd.py b/scripts/west_commands/runners/openocd.py index dd7c6882a36632..3377705687971e 100644 --- a/scripts/west_commands/runners/openocd.py +++ b/scripts/west_commands/runners/openocd.py @@ -11,6 +11,7 @@ from os import path from pathlib import Path +from zephyr_ext_common import ZEPHYR_BASE try: from elftools.elf.elffile import ELFFile @@ -40,7 +41,14 @@ def __init__(self, cfg, pre_init=None, reset_halt_cmd=DEFAULT_OPENOCD_RESET_HALT target_handle=DEFAULT_OPENOCD_TARGET_HANDLE): super().__init__(cfg) - support = path.join(cfg.board_dir, 'support') + if not path.exists(cfg.board_dir): + # try to find the board support in-tree + cfg_board_path = path.normpath(cfg.board_dir) + _temp_path = cfg_board_path.split("boards/")[1] + support = path.join(ZEPHYR_BASE, "boards", _temp_path, 'support') + else: + support = path.join(cfg.board_dir, 'support') + if not config: default = path.join(support, 'openocd.cfg') From 19711991fd46a53f9f2eacc938d5f670ac49a906 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0297/1389] twister: openocd hander: add LPC script CMSIS-DAP support add LPC script CMSIS-DAP support Signed-off-by: Hake Huang --- .../src/twister_harness/device/hardware_adapter.py | 3 +++ scripts/pylib/twister/twisterlib/handlers.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py index 21d9c7378e4fe7..98375873eb9055 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/hardware_adapter.py @@ -82,6 +82,9 @@ def _prepare_runner_args(self) -> tuple[list[str], list[str]]: elif runner == 'openocd' and self.device_config.product == 'EDBG CMSIS-DAP': extra_args.append('--cmd-pre-init') extra_args.append(f'cmsis_dap_serial {board_id}') + elif runner == "openocd" and self.device_config.product == "LPC-LINK2 CMSIS-DAP": + extra_args.append("--cmd-pre-init") + extra_args.append(f'adapter serial {board_id}') elif runner == 'jlink': base_args.append(f'--tool-opt=-SelectEmuBySN {board_id}') elif runner == 'stm32cubeprogrammer': diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index d6dff8f0195666..eaef473af71d74 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -511,6 +511,9 @@ def _create_command(self, runner, hardware): elif runner == "openocd" and product == "EDBG CMSIS-DAP": command_extra_args.append("--cmd-pre-init") command_extra_args.append("cmsis_dap_serial %s" % board_id) + elif runner == "openocd" and product == "LPC-LINK2 CMSIS-DAP": + command_extra_args.append("--cmd-pre-init") + command_extra_args.append("adapter serial %s" % board_id) elif runner == "jlink": command.append("--tool-opt=-SelectEmuBySN %s" % board_id) elif runner == "linkserver": From 2b299b7e6e6144e72ffa164045bf184443ba9b19 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0298/1389] debug: stack: coding guidelines: cast unused arguments to void - added missing ARG_UNUSED Signed-off-by: frei tycho --- include/zephyr/debug/stack.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zephyr/debug/stack.h b/include/zephyr/debug/stack.h index 9053dfb8d62c01..365560a06245bf 100644 --- a/include/zephyr/debug/stack.h +++ b/include/zephyr/debug/stack.h @@ -38,6 +38,8 @@ static inline void log_stack_usage(const struct k_thread *thread) thread, tname, unused, size - unused, size, pcnt); } +#else + ARG_UNUSED(thread); #endif } #endif /* ZEPHYR_INCLUDE_DEBUG_STACK_H_ */ From a577603f89a373dd4274766c52637c1a7849a4f0 Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0299/1389] soc: espressif: add misssing external xtal kconfig entry External XTAL usage is missing a Bootstrap Cycle configuration in Kconfig, causing build to failure when CONFIG_RTC_CLK_SRC_EXT_CRYS is selected. Fixes #72190 Signed-off-by: Sylvio Alves --- soc/espressif/esp32/Kconfig.rtc | 17 +++++++++++++++++ soc/espressif/esp32c3/Kconfig.rtc | 17 +++++++++++++++++ soc/espressif/esp32s2/Kconfig.rtc | 17 +++++++++++++++++ soc/espressif/esp32s3/Kconfig.rtc | 17 +++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/soc/espressif/esp32/Kconfig.rtc b/soc/espressif/esp32/Kconfig.rtc index bfbddc28ebb6c6..ea14eeaf098aee 100644 --- a/soc/espressif/esp32/Kconfig.rtc +++ b/soc/espressif/esp32/Kconfig.rtc @@ -74,4 +74,21 @@ config RTC_XTAL_CAL_RETRY Increase this option if the 32k crystal oscillator does not start and switches to internal RC. +config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES + int "Bootstrap cycles for external 32kHz crystal" + depends on ESP_SYSTEM_RTC_EXT_XTAL + default 5 + range 0 32768 + help + To reduce the startup time of an external RTC crystal, + we bootstrap it with a 32kHz square wave for a fixed number of cycles. + Setting 0 will disable bootstrapping (if disabled, the crystal may take + longer to start up or fail to oscillate under some conditions). + + If this value is too high, a faulty crystal may initially start and then fail. + If this value is too low, an otherwise good crystal may not start. + + To accurately determine if the crystal has started, + set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000). + endif # SOC_SERIES_ESP32 diff --git a/soc/espressif/esp32c3/Kconfig.rtc b/soc/espressif/esp32c3/Kconfig.rtc index fcd91f9ff5c8ed..b0f2e47f565795 100644 --- a/soc/espressif/esp32c3/Kconfig.rtc +++ b/soc/espressif/esp32c3/Kconfig.rtc @@ -47,4 +47,21 @@ config RTC_CLK_CAL_CYCLES In case more value will help improve the definition of the launch of the crystal. If the crystal could not start, it will be switched to internal RC. +config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES + int "Bootstrap cycles for external 32kHz crystal" + depends on ESP_SYSTEM_RTC_EXT_XTAL + default 0 + range 0 32768 + help + To reduce the startup time of an external RTC crystal, + we bootstrap it with a 32kHz square wave for a fixed number of cycles. + Setting 0 will disable bootstrapping (if disabled, the crystal may take + longer to start up or fail to oscillate under some conditions). + + If this value is too high, a faulty crystal may initially start and then fail. + If this value is too low, an otherwise good crystal may not start. + + To accurately determine if the crystal has started, + set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000). + endif # SOC_SERIES_ESP32C3 diff --git a/soc/espressif/esp32s2/Kconfig.rtc b/soc/espressif/esp32s2/Kconfig.rtc index 837ab8623e5b18..61ca8d3a9df9b0 100644 --- a/soc/espressif/esp32s2/Kconfig.rtc +++ b/soc/espressif/esp32s2/Kconfig.rtc @@ -73,4 +73,21 @@ config RTC_XTAL_CAL_RETRY Increase this option if the 32k crystal oscillator does not start and switches to internal RC. +config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES + int "Bootstrap cycles for external 32kHz crystal" + depends on ESP_SYSTEM_RTC_EXT_XTAL + default 0 + range 0 32768 + help + To reduce the startup time of an external RTC crystal, + we bootstrap it with a 32kHz square wave for a fixed number of cycles. + Setting 0 will disable bootstrapping (if disabled, the crystal may take + longer to start up or fail to oscillate under some conditions). + + If this value is too high, a faulty crystal may initially start and then fail. + If this value is too low, an otherwise good crystal may not start. + + To accurately determine if the crystal has started, + set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000). + endif # SOC_SERIES_ESP32S2 diff --git a/soc/espressif/esp32s3/Kconfig.rtc b/soc/espressif/esp32s3/Kconfig.rtc index 526d4b909c94bf..9c5d7d834baa8a 100644 --- a/soc/espressif/esp32s3/Kconfig.rtc +++ b/soc/espressif/esp32s3/Kconfig.rtc @@ -43,4 +43,21 @@ config RTC_CLK_CAL_CYCLES In case more value will help improve the definition of the launch of the crystal. If the crystal could not start, it will be switched to internal RC. +config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES + int "Bootstrap cycles for external 32kHz crystal" + depends on ESP_SYSTEM_RTC_EXT_XTAL + default 0 + range 0 32768 + help + To reduce the startup time of an external RTC crystal, + we bootstrap it with a 32kHz square wave for a fixed number of cycles. + Setting 0 will disable bootstrapping (if disabled, the crystal may take + longer to start up or fail to oscillate under some conditions). + + If this value is too high, a faulty crystal may initially start and then fail. + If this value is too low, an otherwise good crystal may not start. + + To accurately determine if the crystal has started, + set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000). + endif # SOC_SERIES_ESP32S3 From f38def37c8f0337f7ab710726abe887b762f9853 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0300/1389] riscv_machine_timer: fix maximum allowed cycles between reports There are two issues being fixed here: 1) The code currently clamps timeout length so not to overflow the computed cycle difference variable or the sys_clock_announce() argument's range. But this completely fails to take into account the case where two successive timeouts with enough time between them will still overflow the cycle difference and/or the tick count. 2) If a timeout with K_TICKS_FOREVER is provided then the comparator is set with UINT64_MAX which is bogus. Not only this value doesn't make much sense in the context of a running cycle counter, but it also opens the possibility for the same cycle diff and/or ticks overflow as above. Fix both of those by clamping the actual number of cycles to wait for based on the previous report occurrence rather than clamping the timeout ticks. Signed-off-by: Nicolas Pitre --- drivers/timer/riscv_machine_timer.c | 54 +++++++++++++++++++---------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/timer/riscv_machine_timer.c b/drivers/timer/riscv_machine_timer.c index abfb28a9628acd..36e29c6aadb318 100644 --- a/drivers/timer/riscv_machine_timer.c +++ b/drivers/timer/riscv_machine_timer.c @@ -78,6 +78,32 @@ /* the unsigned long cast limits divisions to native CPU register width */ #define cycle_diff_t unsigned long +#define CYCLE_DIFF_MAX (~(cycle_diff_t)0) + +/* + * We have two constraints on the maximum number of cycles we can wait for. + * + * 1) sys_clock_announce() accepts at most INT32_MAX ticks. + * + * 2) The number of cycles between two reports must fit in a cycle_diff_t + * variable before converting it to ticks. + * + * Then: + * + * 3) Pick the smallest between (1) and (2). + * + * 4) Take into account some room for the unavoidable IRQ servicing latency. + * Let's use 3/4 of the max range. + * + * Finally let's add the LSB value to the result so to clear out a bunch of + * consecutive set bits coming from the original max values to produce a + * nicer literal for assembly generation. + */ +#define CYCLES_MAX_1 ((uint64_t)INT32_MAX * (uint64_t)CYC_PER_TICK) +#define CYCLES_MAX_2 ((uint64_t)CYCLE_DIFF_MAX) +#define CYCLES_MAX_3 MIN(CYCLES_MAX_1, CYCLES_MAX_2) +#define CYCLES_MAX_4 (CYCLES_MAX_3 / 2 + CYCLES_MAX_3 / 4) +#define CYCLES_MAX (CYCLES_MAX_4 + LSB_GET(CYCLES_MAX_4)) static struct k_spinlock lock; static uint64_t last_count; @@ -170,27 +196,19 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } - if (ticks == K_TICKS_FOREVER) { - set_mtimecmp(UINT64_MAX); - return; - } - - /* - * Clamp the max period length to a number of cycles that can fit - * in half the range of a cycle_diff_t for native width divisions - * to be usable elsewhere. Also clamp it to half the range of an - * int32_t as this is the type used for elapsed tick announcements. - * The half range gives us extra room to cope with the unavoidable IRQ - * servicing latency. The compiler should optimize away the least - * restrictive of those tests automatically. - */ - ticks = CLAMP(ticks, 0, (cycle_diff_t)-1 / 2 / CYC_PER_TICK); - ticks = CLAMP(ticks, 0, INT32_MAX / 2); - k_spinlock_key_t key = k_spin_lock(&lock); - uint64_t cyc = (last_ticks + last_elapsed + ticks) * CYC_PER_TICK; + uint64_t cyc; + if (ticks == K_TICKS_FOREVER) { + cyc = last_count + CYCLES_MAX; + } else { + cyc = (last_ticks + last_elapsed + ticks) * CYC_PER_TICK; + if ((cyc - last_count) > CYCLES_MAX) { + cyc = last_count + CYCLES_MAX; + } + } set_mtimecmp(cyc); + k_spin_unlock(&lock, key); } From b028135b836ecdf2dd351e020ef93e41a42fee5c Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0301/1389] arm_arch_timer: properly fix cycles overflow with GDB stub In commit 606825551203 ("drivers/timer/arm_arch_timer: Fix cycles overflow with GDB stub") an extra TO_CYCLE_DIFF() macro was introduced to bypass the cycle_diff_t type cast in some cases. The actual fix consists in defining that type properly in the first place. That's the very reason why such type was abstracted. Signed-off-by: Nicolas Pitre --- drivers/timer/arm_arch_timer.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/timer/arm_arch_timer.c b/drivers/timer/arm_arch_timer.c index 718fecea582987..7ffef8bf643834 100644 --- a/drivers/timer/arm_arch_timer.c +++ b/drivers/timer/arm_arch_timer.c @@ -22,14 +22,11 @@ static uint32_t cyc_per_tick; #if defined(CONFIG_GDBSTUB) /* When interactively debugging, the cycle diff can overflow 32-bit variable */ -#define TO_CYCLE_DIFF(x) (x) +#define cycle_diff_t uint64_t #else -/* Convert to 32-bit for fast division */ -#define TO_CYCLE_DIFF(x) ((cycle_diff_t)(x)) -#endif - /* the unsigned long cast limits divisors to native CPU register width */ #define cycle_diff_t unsigned long +#endif static struct k_spinlock lock; static uint64_t last_cycle; @@ -66,7 +63,7 @@ static void arm_arch_timer_compare_isr(const void *arg) uint64_t curr_cycle = arm_arch_timer_count(); uint64_t delta_cycles = curr_cycle - last_cycle; - uint32_t delta_ticks = TO_CYCLE_DIFF(delta_cycles) / CYC_PER_TICK; + uint32_t delta_ticks = (cycle_diff_t)delta_cycles / CYC_PER_TICK; last_cycle += (cycle_diff_t)delta_ticks * CYC_PER_TICK; last_tick += delta_ticks; From 3d95bbf6071488b453e4ca918e81fb1b2440fdc0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0302/1389] arm_arch_timer: fix maximum allowed cycles between reports The code currently clamps timeout length so not to overflow the computed cycle difference variable or the sys_clock_announce() argument's range. But this completely fails to take into account the case where two successive timeouts with enough time between them will still overflow the cycle difference and/or the tick count. Fix this by clamping the actual number of cycles to wait for based on the previous report occurrence rather than clamping the timeout ticks. Signed-off-by: Nicolas Pitre --- drivers/timer/arm_arch_timer.c | 75 ++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/drivers/timer/arm_arch_timer.c b/drivers/timer/arm_arch_timer.c index 7ffef8bf643834..885eb3a369b1c2 100644 --- a/drivers/timer/arm_arch_timer.c +++ b/drivers/timer/arm_arch_timer.c @@ -27,6 +27,40 @@ static uint32_t cyc_per_tick; /* the unsigned long cast limits divisors to native CPU register width */ #define cycle_diff_t unsigned long #endif +#define CYCLE_DIFF_MAX (~(cycle_diff_t)0) + +/* + * We have two constraints on the maximum number of cycles we can wait for. + * + * 1) sys_clock_announce() accepts at most INT32_MAX ticks. + * + * 2) The number of cycles between two reports must fit in a cycle_diff_t + * variable before converting it to ticks. + * + * Then: + * + * 3) Pick the smallest between (1) and (2). + * + * 4) Take into account some room for the unavoidable IRQ servicing latency. + * Let's use 3/4 of the max range. + * + * Finally let's add the LSB value to the result so to clear out a bunch of + * consecutive set bits coming from the original max values to produce a + * nicer literal for assembly generation. + */ +#define CYCLES_MAX_1 ((uint64_t)INT32_MAX * (uint64_t)CYC_PER_TICK) +#define CYCLES_MAX_2 ((uint64_t)CYCLE_DIFF_MAX) +#define CYCLES_MAX_3 MIN(CYCLES_MAX_1, CYCLES_MAX_2) +#define CYCLES_MAX_4 (CYCLES_MAX_3 / 2 + CYCLES_MAX_3 / 4) +#define CYCLES_MAX_5 (CYCLES_MAX_4 + LSB_GET(CYCLES_MAX_4)) + +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME +/* precompute CYCLES_MAX at driver init to avoid runtime double divisions */ +static uint64_t cycles_max; +#define CYCLES_MAX cycles_max +#else +#define CYCLES_MAX CYCLES_MAX_5 +#endif static struct k_spinlock lock; static uint64_t last_cycle; @@ -106,39 +140,29 @@ static void arm_arch_timer_compare_isr(const void *arg) void sys_clock_set_timeout(int32_t ticks, bool idle) { -#if defined(CONFIG_TICKLESS_KERNEL) - - if (ticks == K_TICKS_FOREVER) { - if (idle) { - return; - } - ticks = INT32_MAX; + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + return; } - /* - * Clamp the max period length to a number of cycles that can fit - * in half the range of a cycle_diff_t for native width divisions - * to be usable elsewhere. Also clamp it to half the range of an - * int32_t as this is the type used for elapsed tick announcements. - * The half range gives us one bit of extra room to cope with the - * unavoidable IRQ servicing latency (we never need as much but this - * is simple). The compiler should optimize away the least restrictive - * of those tests automatically. - */ - ticks = CLAMP(ticks, 0, (cycle_diff_t)-1 / 2 / CYC_PER_TICK); - ticks = CLAMP(ticks, 0, INT32_MAX / 2); + if (idle && ticks == K_TICKS_FOREVER) { + return; + } k_spinlock_key_t key = k_spin_lock(&lock); - uint64_t next_cycle = (last_tick + last_elapsed + ticks) * CYC_PER_TICK; + uint64_t next_cycle; + + if (ticks == K_TICKS_FOREVER) { + next_cycle = last_cycle + CYCLES_MAX; + } else { + next_cycle = (last_tick + last_elapsed + ticks) * CYC_PER_TICK; + if ((next_cycle - last_cycle) > CYCLES_MAX) { + next_cycle = last_cycle + CYCLES_MAX; + } + } arm_arch_timer_set_compare(next_cycle); arm_arch_timer_set_irq_mask(false); k_spin_unlock(&lock, key); - -#else /* CONFIG_TICKLESS_KERNEL */ - ARG_UNUSED(ticks); - ARG_UNUSED(idle); -#endif } uint32_t sys_clock_elapsed(void) @@ -210,6 +234,7 @@ static int sys_clock_driver_init(void) arm_arch_timer_init(); #ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME cyc_per_tick = sys_clock_hw_cycles_per_sec() / CONFIG_SYS_CLOCK_TICKS_PER_SEC; + cycles_max = CYCLES_MAX_5; #endif arm_arch_timer_enable(true); last_tick = arm_arch_timer_count() / CYC_PER_TICK; From 94505e68acd9f13aed53bbdc6810b8fcbe8ad190 Mon Sep 17 00:00:00 2001 From: Romain Pelletant Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0303/1389] boards: st: add adc-keys support for stm32c0116_dk Add support for stm32c0116_dk joystick based on adc-keys gem Signed-off-by: Romain Pelletant --- boards/st/stm32c0116_dk/stm32c0116_dk.dts | 48 ++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk.dts b/boards/st/stm32c0116_dk/stm32c0116_dk.dts index 00a1b134261d5d..f9791268886a9b 100644 --- a/boards/st/stm32c0116_dk/stm32c0116_dk.dts +++ b/boards/st/stm32c0116_dk/stm32c0116_dk.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include / { model = "STMicroelectronics STM32C0116-DK Discovery board"; @@ -41,6 +42,38 @@ label = "reset button"; gpios = <&gpiof 2 GPIO_ACTIVE_LOW>; status = "okay"; + zephyr,code = ; + }; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&adc1 8>; + keyup-threshold-mv = <3300>; + + select_key { + press-thresholds-mv = <0>; + zephyr,code = ; + }; + + left_key { + press-thresholds-mv = <670>; + zephyr,code = ; + }; + + down_key { + press-thresholds-mv = <1320>; + zephyr,code = ; + }; + + up_key { + press-thresholds-mv = <2010>; + zephyr,code = ; + }; + + right_key { + press-thresholds-mv = <2650>; + zephyr,code = ; }; }; @@ -109,8 +142,21 @@ pinctrl-0 = <&adc1_in8_pa8>; pinctrl-names = "default"; st,adc-clock-source = ; - st,adc-prescaler = <4>; + st,adc-prescaler = <2>; status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + channel@8 { + reg = <0x8>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,vref-mv = <3300>; + }; + }; &die_temp { From 201bedf8d26dee4a1d18b9c820f1d99129deb1b3 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:40 +0200 Subject: [PATCH 0304/1389] modules: nanopb: Pull upstream fixes Update nanopb with upstream fixes for selecting the correct protoc executable. Signed-off-by: Pieter De Gendt --- modules/nanopb/nanopb.cmake | 1 + submanifests/optional.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nanopb/nanopb.cmake b/modules/nanopb/nanopb.cmake index 5158090aae9258..c57f89c6ed8e62 100644 --- a/modules/nanopb/nanopb.cmake +++ b/modules/nanopb/nanopb.cmake @@ -4,6 +4,7 @@ include_guard(GLOBAL) +set(NANOPB_SRC_ROOT_FOLDER ${ZEPHYR_NANOPB_MODULE_DIR}) list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_NANOPB_MODULE_DIR}/extra) find_package(Nanopb REQUIRED) diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index 1e278cc8f6da41..82007d5ae263bf 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -22,7 +22,7 @@ manifest: groups: - optional - name: nanopb - revision: f6187b05a5eaf753faa0e29a5acd77dd0544d474 + revision: 7f88274070afa5edfaf608f4d8e32f3d3c1de139 path: modules/lib/nanopb remote: upstream groups: From ff1a7745e050e8d2212ef543816a45fddb364332 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0305/1389] doc: posix: impl: add missing ref tags Previously, the :ref: tag was missing in front of two links to the System Calls page. Signed-off-by: Chris Friedt --- doc/services/portability/posix/implementation/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/services/portability/posix/implementation/index.rst b/doc/services/portability/posix/implementation/index.rst index 361b0405576cd8..1a3756ae2c09d1 100644 --- a/doc/services/portability/posix/implementation/index.rst +++ b/doc/services/portability/posix/implementation/index.rst @@ -18,7 +18,7 @@ Unlike other multi-purpose POSIX operating systems .. note:: Unlike the Linux kernel or FreeBSD, Zephyr does not maintain a static table of system call numbers for each supported architecture, but instead generates system calls dynamically at - build time. See `System Calls ` for more information. + build time. See :ref:`System Calls ` for more information. Design ====== @@ -73,5 +73,5 @@ Some general design considerations: } - POSIX API calls should be provided as regular callable C functions; if a Zephyr - `System Call ` is needed as part of the implementation, the declaration and the + :ref:`System Call ` is needed as part of the implementation, the declaration and the implementation of that system call should be hidden behind the POSIX API. From 898e2b2e7bed4c39f3d66edd0a15c4eebd997aff Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0306/1389] doc: posix: overview: correct typo (needed plural threads) Correct the typo on thread so that it reads as the plural threads. Signed-off-by: Chris Friedt --- doc/services/portability/posix/overview/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst index 744740ad8ff098..ffe58f75224b8c 100644 --- a/doc/services/portability/posix/overview/index.rst +++ b/doc/services/portability/posix/overview/index.rst @@ -38,7 +38,7 @@ Benefits of POSIX support in Zephyr include: POSIX Subprofiles ================= -While Zephyr supports running multiple :ref:`thread ` (possibly in an +While Zephyr supports running multiple :ref:`threads ` (possibly in an :ref:`SMP ` configuration), as well as :ref:`Virtual Memory and MMUs `, Zephyr code and data normally share a common address space. The Zephyr kernel executable code and the application executable code are From cbccd50a68beb2cf67cfb61613eecb8ce7a92eab Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0307/1389] doc: posix: overview: link to memory domain documentation Link to the Memory Domains document in the overview. Signed-off-by: Chris Friedt --- doc/services/portability/posix/overview/index.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst index ffe58f75224b8c..cd00b68b1a7213 100644 --- a/doc/services/portability/posix/overview/index.rst +++ b/doc/services/portability/posix/overview/index.rst @@ -41,9 +41,10 @@ POSIX Subprofiles While Zephyr supports running multiple :ref:`threads ` (possibly in an :ref:`SMP ` configuration), as well as :ref:`Virtual Memory and MMUs `, Zephyr code and data normally share a -common address space. The Zephyr kernel executable code and the application executable code are -typically compiled into the same binary artifact. From that perspective, Zephyr apps can be seen -as running in the context of a single process. +common address space that is partitioned into separate :ref:`Memory Domains `. The +Zephyr kernel executable code and the application executable code are typically compiled into the +same binary artifact. From that perspective, Zephyr apps can be seen as running in the context of +a single process. While multi-purpose operating systems (OS) offer full POSIX conformance, Real-Time Operating Systems (RTOS) such as Zephyr typically serve a fixed-purpose, have limited hardware resources, From 278f432b6930b9b1c73e3b6e6d5f5a635cf98610 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0308/1389] doc: posix: conformance: define realtime signals option group Link the option _POSIX_REALTIME_SIGNALS to the option group POSIX_REALTIME_SIGNALS since it is well-defined in the spec. Add the definition to the option_groups page. Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/option_groups/index.rst | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index a59e4bf69de2fd..d2055ed85625b2 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -67,7 +67,7 @@ POSIX System Interfaces _POSIX_MAPPED_FILES, -1, :ref:`†` _POSIX_MEMORY_PROTECTION, -1, :ref:`†` :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` - _POSIX_REALTIME_SIGNALS, -1, :ref:`†` + :ref:`_POSIX_REALTIME_SIGNALS`, -1, :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index b05f902bbdd547..e284af76d02547 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -151,6 +151,19 @@ Group. For more information on developing Zephyr applications in the C programming language, please refer to :ref:`details`. +.. _posix_option_group_realtime_signals: + +POSIX_REALTIME_SIGNALS +====================== + +.. csv-table:: POSIX_REALTIME_SIGNALS + :header: API, Supported + :widths: 50,10 + + sigqueue(), + sigtimedwait(), + sigwaitinfo(), + .. _posix_option_group_signal_jump: POSIX_SIGNAL_JUMP From f3a77bbf5142712b7608e653c109f70959afe87d Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0309/1389] posix: fs: create a separate Kconfig option for fsync Create CONFIG_POSIX_FSYNC to match the spec. Signed-off-by: Chris Friedt --- include/zephyr/posix/unistd.h | 2 +- lib/os/fdtable.c | 2 ++ lib/posix/options/Kconfig.fs | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index c8974fdc8628a6..7cc96a93e21370 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -42,7 +42,7 @@ extern "C" { #define _POSIX_CHOWN_RESTRICTED (-1L) #define _POSIX_CLOCK_SELECTION Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) #define _POSIX_CPUTIME (-1L) -#define _POSIX_FSYNC (-1L) +#define _POSIX_FSYNC Z_SC_VAL_IFDEF(CONFIG_POSIX_FSYNC, _POSIX_VERSION) #define _POSIX_IPV6 Z_SC_VAL_IFDEF(CONFIG_NET_IPV6, _POSIX_VERSION) #define _POSIX_JOB_CONTROL (-1L) #define _POSIX_MAPPED_FILES _POSIX_VERSION diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 1fd42ad1208cf6..e02bc2f661f41d 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -354,6 +354,7 @@ int close(int fd) } FUNC_ALIAS(close, _close, int); +#ifdef CONFIG_POSIX_FSYNC int fsync(int fd) { if (_check_fd(fd) < 0) { @@ -363,6 +364,7 @@ int fsync(int fd) return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_FSYNC); } FUNC_ALIAS(fsync, _fsync, int); +#endif /* CONFIG_POSIX_FSYNC */ off_t lseek(int fd, off_t offset, int whence) { diff --git a/lib/posix/options/Kconfig.fs b/lib/posix/options/Kconfig.fs index e4d5f1dea6e44f..bff95a906a9cfa 100644 --- a/lib/posix/options/Kconfig.fs +++ b/lib/posix/options/Kconfig.fs @@ -10,10 +10,19 @@ menuconfig POSIX_FS help This enables POSIX style file system related APIs. +if POSIX_FS + config POSIX_MAX_OPEN_FILES int "Maximum number of open file descriptors" default 16 - depends on POSIX_FS help Maximum number of open files. Note that this setting is additionally bounded by CONFIG_POSIX_MAX_FDS. + +config POSIX_FSYNC + bool "Support for fsync()" + default y + help + This enables fsync() support. + +endif # POSIX_FS From 6533c5d983d3d3944a61a0435a7c7e20fdb5ef88 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0310/1389] doc: posix: link _POSIX_FSYNC to kconfig option Link _POSIX_FSYNC to CONFIG_POSIX_FSYNC instead of CONFIG_POSIX_FS. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- doc/services/portability/posix/conformance/index.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 636e2f72c2079f..47646cd488448b 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -60,7 +60,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :header: Symbol, Support, Remarks :widths: 50, 10, 50 - :ref:`_POSIX_FSYNC `, -1, + :ref:`_POSIX_FSYNC `, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` :ref:`_POSIX_MEMLOCK `, -1, :ref:`_POSIX_MEMLOCK_RANGE `, -1, :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index d2055ed85625b2..3b9e675899687c 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -82,7 +82,7 @@ POSIX System Interfaces _POSIX_ADVISORY_INFO, -1, _POSIX_CPUTIME, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` - _POSIX_FSYNC, 200809L, :kconfig:option:`CONFIG_POSIX_FS` + :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` _POSIX_IPV6, 200809L, :kconfig:option:`CONFIG_NET_IPV6` _POSIX_MEMLOCK, -1, _POSIX_MEMLOCK_RANGE, -1, @@ -148,7 +148,7 @@ XSI System Interfaces :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_FSYNC, 200809L, :kconfig:option:`CONFIG_POSIX_FS` + :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` _POSIX_THREAD_PROCESS_SHARED, -1, From 1bf1bfd873bca0d733ca241b11ed0df6f27cc8db Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0311/1389] doc: posix: add links and make minor corrections Add a link to _POSIX_CLOCK_MONOTONIC, correct the _POSIX_RAW_SOCKETS kconfig option. Define _POSIX_CHOWN_RESTRICTED and _POSIX_NO_TRUNC so that they conform to the spec. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 8 ++++---- doc/services/portability/posix/conformance/index.rst | 12 ++++++------ include/zephyr/posix/unistd.h | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 47646cd488448b..a8f214ef2aacb9 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -71,7 +71,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`_POSIX_THREAD_CPUTIME `, -1, _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` _POSIX_THREAD_PRIO_PROTECT, -1, - :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` (will fail with ``ENOSYS``:ref:`†`) + :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` _POSIX_THREAD_SPORADIC_SERVER, -1, .. _posix_aep_pse52: @@ -153,9 +153,9 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 _POSIX_CPUTIME, -1, _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING `, -1, - _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS` - _POSIX_SPAWN, -1, - _POSIX_SPORADIC_SERVER, -1, + _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` + _POSIX_SPAWN, -1, :ref:`†` + _POSIX_SPORADIC_SERVER, -1, :ref:`†` .. _IEEE 1003.1-2017: https://standards.ieee.org/ieee/1003.1/7101/ .. _IEEE 1003.13-2003: https://standards.ieee.org/ieee/1003.13/3322/ diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 3b9e675899687c..69e77eed89c358 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -87,14 +87,14 @@ POSIX System Interfaces _POSIX_MEMLOCK, -1, _POSIX_MEMLOCK_RANGE, -1, :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` - _POSIX_MONOTONIC_CLOCK, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` _POSIX_PRIORITIZED_IO, -1, - :ref:`_POSIX_PRIORITY_SCHEDULING`, -1, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` (will fail with ``ENOSYS``:ref:`†`) - _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS` + :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` + _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` _POSIX_SHARED_MEMORY_OBJECTS, -1, - _POSIX_SPAWN, -1, - _POSIX_SPORADIC_SERVER, -1, - _POSIX_SYNCHRONIZED_IO, -1, :kconfig:option:`CONFIG_POSIX_FS` + _POSIX_SPAWN, -1, :ref:`†` + _POSIX_SPORADIC_SERVER, -1, :ref:`†` + _POSIX_SYNCHRONIZED_IO, -1, :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` _POSIX_THREAD_CPUTIME, -1, diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index 7cc96a93e21370..f829ebac235139 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -38,22 +38,22 @@ extern "C" { /* Constants for Options and Option Groups */ #define _POSIX_ADVISORY_INFO (-1L) #define _POSIX_ASYNCHRONOUS_IO Z_SC_VAL_IFDEF(CONFIG_POSIX_ASYNCHRONOUS_IO, _POSIX_VERSION) -#define _POSIX_BARRIERS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_CHOWN_RESTRICTED (-1L) +#define _POSIX_BARRIERS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_BARRIER, _POSIX_VERSION) +#define _POSIX_CHOWN_RESTRICTED (0) #define _POSIX_CLOCK_SELECTION Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) #define _POSIX_CPUTIME (-1L) #define _POSIX_FSYNC Z_SC_VAL_IFDEF(CONFIG_POSIX_FSYNC, _POSIX_VERSION) #define _POSIX_IPV6 Z_SC_VAL_IFDEF(CONFIG_NET_IPV6, _POSIX_VERSION) #define _POSIX_JOB_CONTROL (-1L) -#define _POSIX_MAPPED_FILES _POSIX_VERSION +#define _POSIX_MAPPED_FILES (-1L) #define _POSIX_MEMLOCK (-1L) #define _POSIX_MEMLOCK_RANGE (-1L) #define _POSIX_MEMORY_PROTECTION (-1L) #define _POSIX_MESSAGE_PASSING Z_SC_VAL_IFDEF(CONFIG_POSIX_MQUEUE, _POSIX_VERSION) #define _POSIX_MONOTONIC_CLOCK Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_NO_TRUNC (-1L) +#define _POSIX_NO_TRUNC (0) #define _POSIX_PRIORITIZED_IO (-1L) -#define _POSIX_PRIORITY_SCHEDULING (-1L) +#define _POSIX_PRIORITY_SCHEDULING Z_SC_VAL_IFDEF(CONFIG_POSIX_PRIORITY_SCHEDULING, _POSIX_VERSION) #define _POSIX_RAW_SOCKETS Z_SC_VAL_IFDEF(CONFIG_NET_SOCKETS_PACKET, _POSIX_VERSION) #define _POSIX_READER_WRITER_LOCKS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) #define _POSIX_REALTIME_SIGNALS (-1L) From 49d66b46a9c1ba88286352d54960497c75f83fa0 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0312/1389] MAINTAINERS: GNSS: Add collaborators Add tomi-font and fabiobaltieri as collaborators of the "Drivers: GNSS" area Signed-off-by: Bjarki Arge Andreasen --- MAINTAINERS.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index dcd454fdf068d7..9781a9d29703f9 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1323,6 +1323,9 @@ Release Notes: status: maintained maintainers: - bjarki-trackunit + collaborators: + - tomi-font + - fabiobaltieri files: - doc/hardware/peripherals/gnss.rst - drivers/gnss/ From 4499634f7c72f3d51271b16cc73395638665374d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0313/1389] MAINTAINERS: replace SebastianBoe with Vge0rge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace SebastianBoe with Vge0rge as he is taking over my responsibilities. This affects misc. TF-M modules. Vge0rge is the upstream TF-M maintainer for nordic. Signed-off-by: Sebastian Bøe --- MAINTAINERS.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 9781a9d29703f9..f1d8a75b0a7eb0 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3823,7 +3823,7 @@ TF-M Integration: maintainers: - d3zd3z collaborators: - - SebastianBoe + - Vge0rge - ithinuel files: - samples/tfm_integration/ @@ -4681,7 +4681,7 @@ West: maintainers: - d3zd3z collaborators: - - SebastianBoe + - Vge0rge - ithinuel files: - modules/trusted-firmware-m/ @@ -4693,7 +4693,7 @@ West: maintainers: - d3zd3z collaborators: - - SebastianBoe + - Vge0rge - ithinuel files: [] labels: @@ -4717,7 +4717,7 @@ West: maintainers: - d3zd3z collaborators: - - SebastianBoe + - Vge0rge - ithinuel files: [] labels: From 2aa9467487e8c9fc19335e4ea568424982427071 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0314/1389] drivers: linker: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- include/zephyr/linker/linker-defs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/zephyr/linker/linker-defs.h b/include/zephyr/linker/linker-defs.h index f2737c7f6f2c21..ec37a3718d5e05 100644 --- a/include/zephyr/linker/linker-defs.h +++ b/include/zephyr/linker/linker-defs.h @@ -159,7 +159,7 @@ extern char __gcov_bss_size[]; /* end address of image, used by newlib for the heap */ extern char _end[]; -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay)) extern char __ccm_data_rom_start[]; extern char __ccm_start[]; extern char __ccm_data_start[]; @@ -171,14 +171,14 @@ extern char __ccm_noinit_end[]; extern char __ccm_end[]; #endif -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay)) extern char __itcm_start[]; extern char __itcm_end[]; extern char __itcm_size[]; extern char __itcm_load_start[]; #endif -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)) extern char __dtcm_data_start[]; extern char __dtcm_data_end[]; extern char __dtcm_bss_start[]; @@ -190,7 +190,7 @@ extern char __dtcm_start[]; extern char __dtcm_end[]; #endif -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay)) extern char __ocm_data_start[]; extern char __ocm_data_end[]; extern char __ocm_bss_start[]; From 21d3f16b3ba33548591e18cb3bb245f3467047e7 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0315/1389] drivers: regulator: Smartbond: Fix current and voltage get functions Argument to FIELD_GET macro was mixed up resulting in incorrect values being reported for voltage and current Signed-off-by: Jerzy Kasenberg --- drivers/regulator/regulator_da1469x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/regulator_da1469x.c b/drivers/regulator/regulator_da1469x.c index 50887e4b4531b1..ad3db8f99525a4 100644 --- a/drivers/regulator/regulator_da1469x.c +++ b/drivers/regulator/regulator_da1469x.c @@ -307,7 +307,7 @@ static int regulator_da1469x_get_voltage(const struct device *dev, uint16_t idx; if (config->desc->voltage_idx_mask) { - idx = FIELD_GET(CRG_TOP->POWER_CTRL_REG, config->desc->voltage_idx_mask); + idx = FIELD_GET(config->desc->voltage_idx_mask, CRG_TOP->POWER_CTRL_REG); } else { idx = 0; } @@ -358,8 +358,8 @@ static int regulator_da1469x_get_current_limit(const struct device *dev, if (config->desc->current_ranges == NULL) { return -ENOTSUP; } - idx = FIELD_GET(*config->desc->dcdc_register, - DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MAX_HV_Msk); + idx = FIELD_GET(DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MAX_HV_Msk, + *config->desc->dcdc_register); ret = linear_range_group_get_value(config->desc->current_ranges, 1, idx, curr_ua); return ret; From 514573e04ccb35f8e9f50985d3e4b1171b019664 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0316/1389] drivers: rtc: stm32: check for NULL pointer Check for NULL rtc_time pointer in get_time() function. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 1051c8fc0d1dab..00b433db201687 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -253,7 +253,12 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr #if HW_SUBSECOND_SUPPORT const struct rtc_stm32_config *cfg = dev->config; uint32_t rtc_subsecond; -#endif +#endif /* HW_SUBSECOND_SUPPORT */ + + if (timeptr == NULL) { + LOG_ERR("NULL rtc_time pointer"); + return -EINVAL; + } int err = k_mutex_lock(&data->lock, K_NO_WAIT); @@ -282,7 +287,7 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr rtc_time = LL_RTC_TIME_Get(RTC); #if HW_SUBSECOND_SUPPORT rtc_subsecond = LL_RTC_TIME_GetSubSecond(RTC); -#endif +#endif /* HW_SUBSECOND_SUPPORT */ } while (rtc_time != LL_RTC_TIME_Get(RTC)); } while (rtc_date != LL_RTC_DATE_Get(RTC)); From 7159826aac25bed8df899d4cc4eb43ca9bf10f7c Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0317/1389] drivers: rtc: stm32: INF log msg to DBG Turn INF log msg to DBG. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 00b433db201687..cecd7ca9a25c86 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -196,7 +196,7 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t return err; } - LOG_INF("Setting clock"); + LOG_DBG("Setting clock"); #if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) LL_PWR_EnableBkUpAccess(); From da935b952991a2b0bfa24004ea0ffd5493e1f3a0 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0318/1389] usb: device: get rid of the partial initialization called by SYS_INIT Part of the initialization is done in the static usb_device_init() function called by SYS_INIT(). We can move part of it, which initialize the descriptor and calls usb_set_config(), to usb_enable(). This allow some usb_get_device_descriptor() dependencies called at application desired point. Also make sure that usb_fix_descriptor() is called only once. Signed-off-by: Johann Fischer --- subsys/usb/device/usb_descriptor.c | 12 ++++++-- subsys/usb/device/usb_device.c | 44 +++++++++++++----------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/subsys/usb/device/usb_descriptor.c b/subsys/usb/device/usb_descriptor.c index 5f75fe97c4f92b..325989dc7fdee2 100644 --- a/subsys/usb/device/usb_descriptor.c +++ b/subsys/usb/device/usb_descriptor.c @@ -505,12 +505,18 @@ static int usb_fix_descriptor(struct usb_desc_header *head) uint8_t *usb_get_device_descriptor(void) { + static bool initialized; + LOG_DBG("__usb_descriptor_start %p", __usb_descriptor_start); LOG_DBG("__usb_descriptor_end %p", __usb_descriptor_end); - if (usb_fix_descriptor(__usb_descriptor_start)) { - LOG_ERR("Failed to fixup USB descriptor"); - return NULL; + if (!initialized) { + if (usb_fix_descriptor(__usb_descriptor_start)) { + LOG_ERR("Failed to fixup USB descriptor"); + return NULL; + } + + initialized = true; } return (uint8_t *) __usb_descriptor_start; diff --git a/subsys/usb/device/usb_device.c b/subsys/usb/device/usb_device.c index aeb4df1a3f09bf..41c813a61b46d3 100644 --- a/subsys/usb/device/usb_device.c +++ b/subsys/usb/device/usb_device.c @@ -1595,7 +1595,7 @@ int usb_enable(usb_dc_status_callback status_cb) { int ret; struct usb_dc_ep_cfg_data ep0_cfg; - struct usb_device_descriptor *dev_desc = (void *)usb_dev.descriptors; + struct usb_device_descriptor *dev_desc; /* Prevent from calling usb_enable form different context. * This should only be called once. @@ -1609,12 +1609,27 @@ int usb_enable(usb_dc_status_callback status_cb) goto out; } + /* + * If usb_dev.descriptors is equal to NULL (usb_dev has static + * specifier), then usb_get_device_descriptor() and usb_set_config() + * are likely not called yet. If so, set the configuration here. + */ + if (usb_dev.descriptors == NULL) { + usb_set_config(usb_get_device_descriptor()); + if (usb_dev.descriptors == NULL) { + LOG_ERR("Failed to configure USB device stack"); + ret = -1; + goto out; + } + } + /* Enable VBUS if needed */ ret = usb_vbus_set(true); if (ret < 0) { goto out; } + dev_desc = (void *)usb_dev.descriptors; usb_dev.user_status_callback = status_cb; usb_register_status_callback(forward_status_cb); usb_dc_set_status_callback(forward_status_cb); @@ -1693,32 +1708,11 @@ int usb_enable(usb_dc_status_callback status_cb) return ret; } -/* - * This function configures the USB device stack based on USB descriptor and - * usb_cfg_data. - */ +#if defined(CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT) static int usb_device_init(void) { - uint8_t *device_descriptor; - - if (usb_dev.enabled == true) { - return -EALREADY; - } - - /* register device descriptor */ - device_descriptor = usb_get_device_descriptor(); - if (!device_descriptor) { - LOG_ERR("Failed to configure USB device stack"); - return -1; - } - - usb_set_config(device_descriptor); - - if (IS_ENABLED(CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT)) { - return usb_enable(NULL); - } - - return 0; + return usb_enable(NULL); } SYS_INIT(usb_device_init, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY); +#endif From bb53582d62859d5dabaac672724dd9d8fca8460e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0319/1389] tests: usb: add usb_set_config() call to desc_sections test With the previous changes, usb_set_config() is no longer called by default at boot time, causing the test to fail. Signed-off-by: Johann Fischer --- tests/subsys/usb/desc_sections/src/desc_sections.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/subsys/usb/desc_sections/src/desc_sections.c b/tests/subsys/usb/desc_sections/src/desc_sections.c index 5100f1b90aefbb..0277462b68d76d 100644 --- a/tests/subsys/usb/desc_sections/src/desc_sections.c +++ b/tests/subsys/usb/desc_sections/src/desc_sections.c @@ -203,6 +203,7 @@ ZTEST(desc_sections, test_desc_sections) { struct usb_desc_header *head; + usb_set_config(usb_get_device_descriptor()); TC_PRINT("__usb_descriptor_start %p\n", __usb_descriptor_start); TC_PRINT("__usb_descriptor_end %p\n", __usb_descriptor_end); TC_PRINT("USB Descriptor table span %d\n", From b2583965008d44f019402384f69506a660dafdac Mon Sep 17 00:00:00 2001 From: Philippe Schumacher Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0320/1389] net: lwm2m: efficent cbor record data structure The record data structure is better aligned. Each record saves 24 bytes. Signed-off-by: Philippe Schumacher --- subsys/net/lib/lwm2m/lwm2m_senml_cbor.patch | 34 ++++++++++++++----- subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h | 10 +++--- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor.patch b/subsys/net/lib/lwm2m/lwm2m_senml_cbor.patch index 41bb3f0a5d4ddd..20b64f91f4aba1 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor.patch +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor.patch @@ -1,5 +1,5 @@ diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.c b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.c -index c12f477cce..f41b81275d 100644 +index 8b136cccf0b..ca935f9f60a 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.c +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.c @@ -4,7 +4,7 @@ @@ -41,7 +41,7 @@ index c12f477cce..f41b81275d 100644 if (!tmp_result) { zcbor_trace_file(state); diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.h b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.h -index a36f8782c6..b913fb78e9 100644 +index 8060c2cd932..7316e8fb2c6 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.h +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.h @@ -4,7 +4,7 @@ @@ -66,7 +66,7 @@ index a36f8782c6..b913fb78e9 100644 const uint8_t *payload, size_t payload_len, struct lwm2m_senml *result, diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.c b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.c -index 94926c531f..5521917853 100644 +index d63baab5bcb..cbeef1b4e18 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.c +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.c @@ -4,7 +4,7 @@ @@ -114,7 +114,7 @@ index 94926c531f..5521917853 100644 if (!tmp_result) { zcbor_trace_file(state); diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.h b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.h -index df2f0ac6a1..8fa1eedb2b 100644 +index 8bfba2d834e..fe644015f63 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.h +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.h @@ -4,7 +4,7 @@ @@ -139,7 +139,7 @@ index df2f0ac6a1..8fa1eedb2b 100644 uint8_t *payload, size_t payload_len, const struct lwm2m_senml *input, diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h -index 77649036ef..f0a2958072 100644 +index ad1d0bef58d..662329d1680 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h @@ -4,7 +4,7 @@ @@ -151,7 +151,7 @@ index 77649036ef..f0a2958072 100644 * Generated with a --default-max-qty of 99 */ -@@ -20,14 +20,18 @@ +@@ -20,14 +20,17 @@ extern "C" { #endif @@ -163,7 +163,6 @@ index 77649036ef..f0a2958072 100644 - * See `zcbor --help` for more information about --default-max-qty - */ -#define DEFAULT_MAX_QTY 99 -+ +enum lwm2m_senml_cbor_key { + lwm2m_senml_cbor_key_bn = -2, + lwm2m_senml_cbor_key_bt = -3, @@ -178,7 +177,26 @@ index 77649036ef..f0a2958072 100644 struct record_bn { struct zcbor_string record_bn; -@@ -118,7 +122,7 @@ struct record { +@@ -104,21 +107,21 @@ struct record_key_value_pair_m { + + struct record { + struct record_bn record_bn; +- bool record_bn_present; + struct record_bt record_bt; +- bool record_bt_present; + struct record_n record_n; +- bool record_n_present; + struct record_t record_t; +- bool record_t_present; + struct record_union_r record_union; +- bool record_union_present; + struct record_key_value_pair_m record_key_value_pair_m[5]; + size_t record_key_value_pair_m_count; ++ bool record_bn_present; ++ bool record_bt_present; ++ bool record_n_present; ++ bool record_t_present; ++ bool record_union_present; }; struct lwm2m_senml { diff --git a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h index dbb5a368551316..662329d1680150 100644 --- a/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h +++ b/subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h @@ -107,17 +107,17 @@ struct record_key_value_pair_m { struct record { struct record_bn record_bn; - bool record_bn_present; struct record_bt record_bt; - bool record_bt_present; struct record_n record_n; - bool record_n_present; struct record_t record_t; - bool record_t_present; struct record_union_r record_union; - bool record_union_present; struct record_key_value_pair_m record_key_value_pair_m[5]; size_t record_key_value_pair_m_count; + bool record_bn_present; + bool record_bt_present; + bool record_n_present; + bool record_t_present; + bool record_union_present; }; struct lwm2m_senml { From f86b9564e2bddafeb9437062adbfafa503278d02 Mon Sep 17 00:00:00 2001 From: Nithin Ramesh Myliattil Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0321/1389] Bluetoioth: CAP: Shell: Added qos config to unicast_start cmd For cap_initiator unicast_start command, qos configuration is added. Signed-off-by: Nithin Ramesh Myliattil --- subsys/bluetooth/audio/shell/cap_initiator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/bluetooth/audio/shell/cap_initiator.c b/subsys/bluetooth/audio/shell/cap_initiator.c index 074af102863f08..ae6e3351e3079b 100644 --- a/subsys/bluetooth/audio/shell/cap_initiator.c +++ b/subsys/bluetooth/audio/shell/cap_initiator.c @@ -247,6 +247,7 @@ static int cmd_cap_initiator_unicast_start(const struct shell *sh, size_t argc, group_stream_params[start_param.count].stream = &stream_param[start_param.count].stream->bap_stream; + group_stream_params[start_param.count].qos = &uni_stream->qos; pair_params[pair_cnt + j].tx_param = &group_stream_params[start_param.count]; @@ -277,6 +278,7 @@ static int cmd_cap_initiator_unicast_start(const struct shell *sh, size_t argc, stream_param[start_param.count].codec_cfg = &uni_stream->codec_cfg; group_stream_params[start_param.count].stream = &stream_param[start_param.count].stream->bap_stream; + group_stream_params[start_param.count].qos = &uni_stream->qos; pair_params[pair_cnt + j].rx_param = &group_stream_params[start_param.count]; From 77f68a83cf25040693275e1e7522ac53982b5f1b Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0322/1389] posix: barrier: remove deprecated and non-std declaration macro Remove the deprecated macro PTHREAD_BARRIER_DEFINE(). This was deprecated prior to v3.4.0 and technically should have been removed prior to v3.6.0. Users should instead use the standard POSIX call, pthread_barrier_init() to initialize a pthread_barrier_t. Signed-off-by: Chris Friedt --- include/zephyr/posix/pthread.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 2cc05b6df25859..7cd0f7e1160921 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -276,20 +276,6 @@ int pthread_mutexattr_init(pthread_mutexattr_t *attr); */ int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); -/** - * @brief Declare a pthread barrier - * - * Declaration API for a pthread barrier. This is not a - * POSIX API, it's provided to better conform with Zephyr's allocation - * strategies for kernel objects. - * - * @param name Symbol name of the barrier - * @param count Thread count, same as the "count" argument to - * pthread_barrier_init() - * @deprecated Use @ref pthread_barrier_init instead. - */ -#define PTHREAD_BARRIER_DEFINE(name, count) pthread_barrier_t name = -1 __DEPRECATED_MACRO - #define PTHREAD_BARRIER_SERIAL_THREAD 1 /* From c2c0d6c21429297b9f56483599824946de27f609 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0323/1389] input: it8xxx2_kbd: fix col_size build warning range Fix the range check for col_size to allow a configuration with less than 16 columns. Not sure why the minimum was set so high but there's no reason I can tell for it. Signed-off-by: Fabio Baltieri --- drivers/input/input_ite_it8xxx2_kbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/input_ite_it8xxx2_kbd.c b/drivers/input/input_ite_it8xxx2_kbd.c index 5e62e6ee32e1a4..53b0cd13233eed 100644 --- a/drivers/input/input_ite_it8xxx2_kbd.c +++ b/drivers/input/input_ite_it8xxx2_kbd.c @@ -241,4 +241,4 @@ DEVICE_DT_INST_DEFINE(0, &it8xxx2_kbd_init, NULL, BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "only one ite,it8xxx2-kbd compatible node can be supported"); BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, row_size), 1, 8), "invalid row-size"); -BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, col_size), 16, 18), "invalid col-size"); +BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, col_size), 1, 18), "invalid col-size"); From 6b33a26333fb9df593f2fbdace0efc287835b0f4 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:38:41 +0200 Subject: [PATCH 0324/1389] input: it8xxx2_kbd: mask out KSOL and KSOH1 register access KSOL and KSOH1 registers are used not only by the kbd driver, but potentially by other GPIOs attached to the keyboard scanning pins. Mask write access to those registers to ensure drivers don't step over each other. Signed-off-by: Fabio Baltieri --- drivers/input/input_ite_it8xxx2_kbd.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/input/input_ite_it8xxx2_kbd.c b/drivers/input/input_ite_it8xxx2_kbd.c index 53b0cd13233eed..5681b331833229 100644 --- a/drivers/input/input_ite_it8xxx2_kbd.c +++ b/drivers/input/input_ite_it8xxx2_kbd.c @@ -16,6 +16,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(input_ite_it8xxx2_kbd); @@ -58,24 +59,27 @@ static void it8xxx2_kbd_drive_column(const struct device *dev, int col) const struct it8xxx2_kbd_config *const config = dev->config; const struct input_kbd_matrix_common_config *common = &config->common; struct kscan_it8xxx2_regs *const inst = config->base; - int mask; + const uint32_t kso_mask = BIT_MASK(common->col_size); + const uint8_t ksol_mask = kso_mask & 0xff; + const uint8_t ksoh1_mask = (kso_mask >> 8) & 0xff; + uint32_t kso_val; /* Tri-state all outputs */ if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) { - mask = 0x3ffff; + kso_val = kso_mask; /* Assert all outputs */ } else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) { - mask = 0; + kso_val = 0; /* Assert a single output */ } else { - mask = 0x3ffff ^ BIT(col); + kso_val = kso_mask ^ BIT(col); } /* Set KSO[17:0] output data */ - inst->KBS_KSOL = (uint8_t) (mask & 0xff); - inst->KBS_KSOH1 = (uint8_t) ((mask >> 8) & 0xff); + inst->KBS_KSOL = (inst->KBS_KSOL & ~ksol_mask) | (kso_val & ksol_mask); + inst->KBS_KSOH1 = (inst->KBS_KSOH1 & ~ksoh1_mask) | ((kso_val >> 8) & ksoh1_mask); if (common->col_size > 16) { - inst->KBS_KSOH2 = (uint8_t) ((mask >> 16) & 0xff); + inst->KBS_KSOH2 = (kso_val >> 16) & 0xff; } } @@ -138,6 +142,9 @@ static int it8xxx2_kbd_init(const struct device *dev) const struct input_kbd_matrix_common_config *common = &config->common; struct it8xxx2_kbd_data *data = dev->data; struct kscan_it8xxx2_regs *const inst = config->base; + const uint32_t kso_mask = BIT_MASK(common->col_size); + const uint8_t ksol_mask = kso_mask & 0xff; + const uint8_t ksoh1_mask = (kso_mask >> 8) & 0xff; int status; /* Disable wakeup and interrupt of KSI pins before configuring */ @@ -171,8 +178,8 @@ static int it8xxx2_kbd_init(const struct device *dev) } /* KSO[17:0] pins output low */ - inst->KBS_KSOL = 0x00; - inst->KBS_KSOH1 = 0x00; + inst->KBS_KSOL = inst->KBS_KSOL & ~ksol_mask; + inst->KBS_KSOH1 = inst->KBS_KSOH1 & ~ksoh1_mask; if (common->col_size > 16) { inst->KBS_KSOH2 = 0x00; } From 4d2c3a5bfb59e4e62721d14367ef3326bc89565b Mon Sep 17 00:00:00 2001 From: Abram Early Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0325/1389] mcuboot: Remove OVERWRITE_ONLY from DIRECT_XIP modes. Fixes #71111 Signed-off-by: Abram Early --- modules/Kconfig.mcuboot | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index a2e1803b138995..b46c709d8ef446 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -199,7 +199,6 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP bool "MCUboot has been configured for DirectXIP operation" select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE select MCUBOOT_BOOTLOADER_NO_DOWNGRADE - select MCUBOOT_IMGTOOL_OVERWRITE_ONLY help MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode MCUboot can boot from either partition and will @@ -215,7 +214,6 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT select MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE select MCUBOOT_BOOTLOADER_NO_DOWNGRADE - select MCUBOOT_IMGTOOL_OVERWRITE_ONLY help MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode MCUboot will boot the application with the higher version From 976cc74b7ae3af4142bbe2f1e7d5d7b22bea3cf4 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0326/1389] Bluetooth: controller: Sync ISO Establishment fixes - Introduce variable in lll_sync_iso for sync establishment timeout - Introduce estab_failed flag in event_done_extra struct to convey establishment failure from LLL. - Fix ull_sync_iso_estab_done always sending success - Return correct HCI error depending on prepare state Signed-off-by: Morten Priess --- subsys/bluetooth/controller/ll_sw/lll.h | 3 ++ .../bluetooth/controller/ll_sw/lll_sync_iso.h | 2 + .../ll_sw/nordic/lll/lll_sync_iso.c | 1 + .../bluetooth/controller/ll_sw/ull_sync_iso.c | 40 ++++++++++++------- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 129637fd6a820e..7c8aadf5efa0db 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -503,6 +503,9 @@ struct event_done_extra { struct { uint16_t trx_cnt; uint8_t crc_valid:1; +#if defined(CONFIG_BT_CTLR_SYNC_ISO) + uint8_t estab_failed:1; +#endif /* CONFIG_BT_CTLR_SYNC_ISO */ #if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) && \ defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT) /* Used to inform ULL that periodic diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h index c81d7d21e00e18..4038a04486ec61 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h @@ -55,6 +55,8 @@ struct lll_sync_iso { uint8_t stream_curr:5; + uint8_t establish_events:3; + uint8_t next_chan_use; /* Encryption */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c index aef8512e68e6fe..fcc37fc52d873f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c @@ -456,6 +456,7 @@ static void isr_rx_estab(void *param) LL_ASSERT(e); e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_ESTAB; + e->estab_failed = 0U; e->trx_cnt = trx_cnt; e->crc_valid = crc_ok; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index 807c2a7719561b..bd312a5cf4b586 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -464,6 +464,9 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, lll->payload_count |= (uint64_t)bi->payload_count_framing[3] << 24; lll->payload_count |= (uint64_t)(bi->payload_count_framing[4] & 0x7f) << 32; + /* Set establishment event countdown */ + lll->establish_events = CONN_ESTAB_COUNTDOWN; + if (lll->enc && (bi_size == PDU_BIG_INFO_ENCRYPTED_SIZE)) { const uint8_t BIG3[4] = {0x33, 0x47, 0x49, 0x42}; struct ccm *ccm_rx; @@ -651,22 +654,25 @@ void ull_sync_iso_estab_done(struct node_rx_event_done *done) struct node_rx_sync_iso *se; struct node_rx_pdu *rx; - /* switch to normal prepare */ - mfy_lll_prepare.fp = lll_sync_iso_prepare; + if (done->extra.trx_cnt || done->extra.estab_failed) { + /* Switch to normal prepare */ + mfy_lll_prepare.fp = lll_sync_iso_prepare; - /* Get reference to ULL context */ - sync_iso = CONTAINER_OF(done->param, struct ll_sync_iso_set, ull); + /* Get reference to ULL context */ + sync_iso = CONTAINER_OF(done->param, struct ll_sync_iso_set, ull); - /* Prepare BIG Sync Established */ - rx = (void *)sync_iso->sync->iso.node_rx_estab; - rx->hdr.type = NODE_RX_TYPE_SYNC_ISO; - rx->hdr.handle = sync_iso_handle_get(sync_iso); - rx->rx_ftr.param = sync_iso; + /* Prepare BIG Sync Established */ + rx = (void *)sync_iso->sync->iso.node_rx_estab; + rx->hdr.type = NODE_RX_TYPE_SYNC_ISO; + rx->hdr.handle = sync_iso_handle_get(sync_iso); + rx->rx_ftr.param = sync_iso; - se = (void *)rx->pdu; - se->status = BT_HCI_ERR_SUCCESS; + se = (void *)rx->pdu; + se->status = done->extra.estab_failed ? + BT_HCI_ERR_CONN_FAIL_TO_ESTAB : BT_HCI_ERR_SUCCESS; - ll_rx_put_sched(rx->hdr.link, rx); + ll_rx_put_sched(rx->hdr.link, rx); + } ull_sync_iso_done(done); } @@ -871,9 +877,15 @@ static void timeout_cleanup(struct ll_sync_iso_set *sync_iso) /* Populate the Sync Lost which will be enqueued in disabled_cb */ rx = (void *)&sync_iso->node_rx_lost; rx->hdr.handle = sync_iso_handle_get(sync_iso); - rx->hdr.type = NODE_RX_TYPE_SYNC_ISO_LOST; rx->rx_ftr.param = sync_iso; - *((uint8_t *)rx->pdu) = BT_HCI_ERR_CONN_TIMEOUT; + + if (mfy_lll_prepare.fp == lll_sync_iso_prepare) { + rx->hdr.type = NODE_RX_TYPE_SYNC_ISO_LOST; + *((uint8_t *)rx->pdu) = BT_HCI_ERR_CONN_TIMEOUT; + } else { + rx->hdr.type = NODE_RX_TYPE_SYNC_ISO; + *((uint8_t *)rx->pdu) = BT_HCI_ERR_CONN_FAIL_TO_ESTAB; + } /* Stop Sync ISO Ticker */ handle = sync_iso_handle_get(sync_iso); From 35b01646f4bdab3e82a099338a887cfb5d230b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20S=C3=B8rensen?= Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0327/1389] boards: added missing arduino defines to nRF5340 Audio DK board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nRF5340 Audio DK board definition was missing Arduino Shield definitions. Signed-off-by: Tim Sørensen --- .../nrf5340_audio_dk_nrf5340_cpuapp.yaml | 4 ++++ ...rf5340_audio_dk_nrf5340_cpuapp_common.dtsi | 22 ++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml index 9c131a6c9d46be..a4433e7e030cb8 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml @@ -9,6 +9,10 @@ toolchain: ram: 448 flash: 1024 supported: + - arduino_adc + - arduino_i2c + - arduino_serial + - arduino_spi - gpio - i2s - spi diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi index 6ad1591bd4533d..278f78530780a8 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi @@ -25,6 +25,17 @@ }; }; + arduino_adc: analog-connector { + compatible = "arduino,uno-adc"; + #io-channel-cells = <1>; + io-channel-map = <0 &adc 1>, /* A0 = P0.4 = AIN1 */ + <1 &adc 2>, /* A1 = P0.5 = AIN2 */ + <2 &adc 4>, /* A2 = P0.6 = AIN4 */ + <3 &adc 5>, /* A3 = P0.7 = AIN5 */ + <4 &adc 6>, /* A4 = P0.25 = AIN6 */ + <5 &adc 7>; /* A5 = P0.26 = AIN7 */ + }; + pmic { compatible = "nordic,npm1100"; nordic,iset-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; @@ -120,7 +131,7 @@ arduino_serial: &uart1 { pinctrl-names = "default", "sleep"; }; -&i2c1 { +arduino_i2c: &i2c1 { compatible = "nordic,nrf-twim"; status = "okay"; pinctrl-0 = <&i2c1_default>; @@ -172,14 +183,15 @@ arduino_serial: &uart1 { }; }; -&spi4 { +arduino_spi: &spi4 { compatible = "nordic,nrf-spim"; status = "okay"; - cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>, <&gpio0 17 GPIO_ACTIVE_LOW>; + cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>, + <&gpio0 11 GPIO_ACTIVE_LOW>, <&gpio0 17 GPIO_ACTIVE_LOW>; pinctrl-0 = <&spi4_default>; pinctrl-1 = <&spi4_sleep>; pinctrl-names = "default", "sleep"; - sdhc0: sdhc@0 { + sdhc0: sdhc@1 { compatible = "zephyr,sdhc-spi-slot"; reg = <0>; status = "okay"; @@ -191,7 +203,7 @@ arduino_serial: &uart1 { spi-max-frequency = <8000000>; }; - cs47l63: cs47l63@1 { + cs47l63: cs47l63@2 { compatible = "cirrus,cs47l63"; reg = <1>; spi-max-frequency = <8000000>; From 94adb56379776f0a5c6045b4f6cc8798fcb70c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20S=C3=B8rensen?= Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0328/1389] tests: drivers: adc: adc_api: added nRF5340 Audio DK overlay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The adc_api test was missing an overlay file for the nRF5340 Audio Dk board. Signed-off-by: Tim Sørensen --- .../adc_api/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/drivers/adc/adc_api/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay diff --git a/tests/drivers/adc/adc_api/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay b/tests/drivers/adc/adc_api/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..2af48efc4d1d47 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay @@ -0,0 +1,7 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Benjamin Björnsson + */ + +#include "nordic,nrf-saadc-common.dtsi" From 9c66c33f34c1e69a0894ce524a4bfe58d4f53ec7 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0329/1389] MAINTAINERS: Add overlay-le-audio.conf to Bluetooth Audio Add the overlay-le-audio.conf overlay for the BT tester to the Bluetooth Audio group, so that changes to that file will notify the right people. Signed-off-by: Emil Gydesen --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index f1d8a75b0a7eb0..147df7d96088dd 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -447,6 +447,7 @@ Bluetooth Audio: - tests/bluetooth/audio/ - tests/bsim/bluetooth/audio/ - tests/bluetooth/shell/audio.conf + - tests/bluetooth/tester/overlay-le-audio.conf - doc/connectivity/bluetooth/api/audio/ - samples/bluetooth/broadcast_audio*/ - samples/bluetooth/hap*/ From 5d91d50bc2acad2f35e2a37a5a9ce2812798fa2d Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0330/1389] soc: ambiq: apollo4x: Kconfig Update Selections Add Selections to match HAL updates Signed-off-by: Richard Wheatley --- soc/ambiq/apollo4x/Kconfig | 3 +++ west.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/soc/ambiq/apollo4x/Kconfig b/soc/ambiq/apollo4x/Kconfig index a224512cd08dd0..dc1cdda6a9be51 100644 --- a/soc/ambiq/apollo4x/Kconfig +++ b/soc/ambiq/apollo4x/Kconfig @@ -11,3 +11,6 @@ config SOC_SERIES_APOLLO4X select CPU_HAS_ARM_MPU select HAS_SWO select AMBIQ_HAL + select CPU_HAS_DCACHE + select CPU_HAS_ICACHE + select HAS_PM diff --git a/west.yml b/west.yml index ff8a6d79e60131..3df717bf0e5ff8 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: 326d061d85c4384ff7811ab04f3ed3c66d436fb1 + revision: 705f1cbb1ccbdaac7613eb7b27c208c8f592e0c4 path: modules/hal/ambiq groups: - hal From 44c50b503a60b4fa6a04d7cadaba5066822b0d45 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0331/1389] dts: arm: ambiq: Fix Flash Controller Fix the flash controller for Ambiq apollo4p processors. Signed-off-by: Richard Wheatley --- dts/arm/ambiq/ambiq_apollo4p.dtsi | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/dts/arm/ambiq/ambiq_apollo4p.dtsi b/dts/arm/ambiq/ambiq_apollo4p.dtsi index a3abd1093e9364..68e692908f8601 100644 --- a/dts/arm/ambiq/ambiq_apollo4p.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p.dtsi @@ -23,12 +23,7 @@ compatible = "arm,cortex-m4f"; reg = <0>; }; - }; - /* MRAM region */ - flash0: flash@18000 { - compatible = "soc-nv-flash"; - reg = <0x00018000 0x1e8000>; }; /* TCM */ @@ -47,6 +42,20 @@ soc { compatible = "ambiq,apollo4p", "ambiq,apollo4x", "simple-bus"; + flash: flash-controller@18000 { + compatible = "ambiq,flash-controller"; + reg = <0x00018000 0x1e8000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* Flash region */ + flash0: flash@18000 { + compatible = "soc-nv-flash"; + reg = <0x00018000 0x1e8000>; + }; + }; + pwrcfg: pwrcfg@40021000 { compatible = "ambiq,pwrctrl"; reg = <0x40021000 0x400>; From 832657b3c8632fde11d41f98dfdc822ec1eb7233 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0332/1389] dts: arm: ambiq: apollo4p CPU state Added CPU Power Management states Signed-off-by: Richard Wheatley --- dts/arm/ambiq/ambiq_apollo4p.dtsi | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/dts/arm/ambiq/ambiq_apollo4p.dtsi b/dts/arm/ambiq/ambiq_apollo4p.dtsi index 68e692908f8601..aa95ff80c9adb3 100644 --- a/dts/arm/ambiq/ambiq_apollo4p.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p.dtsi @@ -22,8 +22,35 @@ cpu0: cpu@0 { compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&idle &suspend_to_ram>; }; + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + /* + * As Apollo4 datasheet, run_to_sleep and sleep_to_run + * transition time are both lower than 1us, but + * considering the software overhead we set a + * bigger value. + */ + min-residency-us = <100>; + exit-latency-us = <5>; + }; + suspend_to_ram: suspend_to_ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + /* + * As Apollo4 datasheet, run_to_deepsleep transition + * time is lower than 1us and deepsleep_to_run + * transition time is about 25us, but considering + * the software overhead, we set a bigger value. + */ + min-residency-us = <2000>; + exit-latency-us = <125>; + }; + }; }; /* TCM */ From 2a572e7658ed07932ecfd3dce711b946a4f89d83 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0333/1389] soc: ambiq: apollo4x Added Power Management to Ambiq apollo4p SOCs Signed-off-by: Richard Wheatley --- soc/ambiq/apollo4x/CMakeLists.txt | 1 + soc/ambiq/apollo4x/Kconfig.defconfig | 5 ++ soc/ambiq/apollo4x/power.c | 105 +++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 soc/ambiq/apollo4x/power.c diff --git a/soc/ambiq/apollo4x/CMakeLists.txt b/soc/ambiq/apollo4x/CMakeLists.txt index 19f7fa032af3af..5ff65e2ba351ec 100644 --- a/soc/ambiq/apollo4x/CMakeLists.txt +++ b/soc/ambiq/apollo4x/CMakeLists.txt @@ -5,5 +5,6 @@ zephyr_sources(soc.c) zephyr_include_directories(.) +zephyr_sources_ifdef(CONFIG_PM power.c) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/ambiq/apollo4x/Kconfig.defconfig b/soc/ambiq/apollo4x/Kconfig.defconfig index 182adf42cd541e..c8b0d5cbaf0548 100644 --- a/soc/ambiq/apollo4x/Kconfig.defconfig +++ b/soc/ambiq/apollo4x/Kconfig.defconfig @@ -6,4 +6,9 @@ if SOC_SERIES_APOLLO4X rsource "Kconfig.defconfig.apollo4*" +# Need to enlarge the IDLE stack size because the power +# management operations are executed in the idle task +config IDLE_STACK_SIZE + default 2048 if PM + endif # SOC_SERIES_APOLLO4X diff --git a/soc/ambiq/apollo4x/power.c b/soc/ambiq/apollo4x/power.c new file mode 100644 index 00000000000000..8fe8557ba7ed4b --- /dev/null +++ b/soc/ambiq/apollo4x/power.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Ambiq LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include + +/* ambiq-sdk includes */ +#include + +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + + __disable_irq(); + __set_BASEPRI(0); + + switch (state) { + case PM_STATE_SUSPEND_TO_IDLE: + /* Put ARM core to normal sleep. */ + am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_NORMAL); + break; + case PM_STATE_SUSPEND_TO_RAM: + /* Put ARM core to deep sleep. */ + /* Cotex-m: power down, register value preserve.*/ + /* Cache: power down*/ + /* Flash: power down*/ + /* Sram: retention*/ + am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); + break; + default: + LOG_DBG("Unsupported power state %u", state); + break; + } +} + +/** + * @brief PM State Exit Post Operations + * + * For PM_STATE_SUSPEND_TO_IDLE: + * Nothing is needed after soc woken up. + * + * For PM_STATE_SUSPEND_TO_RAM: + * Flash, cache, sram automatically switch + * to active state on wake up + * + * @param state PM State + * @param substate_id Unused + * + */ +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + + __enable_irq(); + irq_unlock(0); +} + +static int ambiq_power_init(void) +{ + am_hal_pwrctrl_mcu_memory_config_t sMcuMemCfg = { + .eCacheCfg = AM_HAL_PWRCTRL_CACHE_NONE, + .bRetainCache = true, + .eDTCMCfg = AM_HAL_PWRCTRL_DTCM_384K, + .eRetainDTCM = AM_HAL_PWRCTRL_DTCM_384K, + .bEnableNVM0 = true, + .bRetainNVM0 = false + }; + + am_hal_pwrctrl_sram_memcfg_t sSRAMCfg = { + .eSRAMCfg = AM_HAL_PWRCTRL_SRAM_ALL, + .eActiveWithMCU = AM_HAL_PWRCTRL_SRAM_NONE, + .eActiveWithGFX = AM_HAL_PWRCTRL_SRAM_NONE, + .eActiveWithDISP = AM_HAL_PWRCTRL_SRAM_NONE, + .eActiveWithDSP = AM_HAL_PWRCTRL_SRAM_NONE, + .eSRAMRetain = AM_HAL_PWRCTRL_SRAM_ALL + }; + + am_hal_pwrctrl_dsp_memory_config_t sDSPMemCfg = { + .bEnableICache = false, + .bRetainCache = false, + .bEnableRAM = false, + .bActiveRAM = false, + .bRetainRAM = false + }; + + am_hal_pwrctrl_mcu_memory_config(&sMcuMemCfg); + am_hal_pwrctrl_sram_config(&sSRAMCfg); + am_hal_pwrctrl_dsp_memory_config(AM_HAL_DSP0, &sDSPMemCfg); + + am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_CRYPTO); + + return 0; +} + +SYS_INIT(ambiq_power_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From 3bb01f1274c19f49f2b7d3b18b1e07804a8a0068 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0334/1389] soc: ambiq: Add Clocks per tick Define System clocks per tick Signed-off-by: Richard Wheatley --- soc/ambiq/Kconfig.defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/ambiq/Kconfig.defconfig b/soc/ambiq/Kconfig.defconfig index 2d0efbe54242ea..70a7507a4c1750 100644 --- a/soc/ambiq/Kconfig.defconfig +++ b/soc/ambiq/Kconfig.defconfig @@ -12,4 +12,7 @@ config CORTEX_M_SYSTICK config SYS_CLOCK_HW_CYCLES_PER_SEC default 32768 if AMBIQ_STIMER_TIMER +config SYS_CLOCK_TICKS_PER_SEC + default 1024 + endif # SOC_FAMILY_AMBIQ From 235a88e7c3289eb40263c472b8041905d6756d5e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0335/1389] scripts: west: commands: completion: add bash completion for twister Add bash shell completion for the "west twister" command. Signed-off-by: Henrik Brix Andersen --- .../completion/west-completion.bash | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index d812e8933b1b79..cff8817c1eb915 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -930,6 +930,175 @@ __comp_west_blobs() esac } +__comp_west_twister() +{ + local bool_opts=" + --aggressive-no-clean + --all -l + --all-deltas -D + --allow-installed-plugin + --build-only -b + --clobber-output -c + --cmake-only + --coverage -C + --create-rom-ram-report + --detailed-skipped-report + --detailed-test-id + --device-flash-with-test + --device-testing + --disable-suite-name-check + --disable-unrecognized-section-test + --disable-warnings-as-errors -W + --dry-run -y + --emulation-only + --enable-asan + --enable-coverage + --enable-lsan + --enable-size-report + --enable-slow -S + --enable-slow-only + --enable-ubsan + --enable-valgrind + --flash-before + --footprint-from-buildlog + --force-color + --force-platform -K + --force-toolchain + --ignore-platform-key + --inline-logs -i + --integration -G + --last-metrics -m + --list-tags + --list-tests + --make -k + --ninja -N + --no-clean -n + --no-detailed-test-id + --no-update -u + --only-failed -f + --overflow-as-errors + --persistent-hardware-map + --platform-reports + --prep-artifacts-for-testing + --quarantine-verify + --retry-build-errors + --short-build-path + --show-footprint + --shuffle-tests + --test-only + --test-tree + --timestamps + --verbose -v + " + + local dir_opts=" + --alt-config-root + --board-root -A + --coverage-basedir + --outdir -O + --report-dir -o + --testsuite-root -T + " + + local file_opts=" + --compare-report + --device-serial + --device-serial-pty + --gcov-tool + --generate-hardware-map + --hardware-map + --load-tests -F + --log-file + --package-artifacts + --pre-script + --quarantine-list + --save-tests -E + --size -z + --test-config + " + + local special_opts=" + --coverage-platform + --coverage-tool + --exclude-platform -P + --filter + --platform -p + --runtime-artifact-cleanup -M + " + + local other_opts=" + --arch -a + --coverage-formats + --device-flash-timeout + --device-serial-baud + --exclude-tag -e + --extra-args -x + --fixture -X + --footprint-threshold -H + --jobs -j + --level + --pytest-args + --report-name + --report-suffix + --retry-failed + --retry-interval + --scenario --test -s + --seed + --shuffle-tests-seed + --sub-test + --subset -B + --tag -t + --timeout-multiplier + --vendor + --west-flash + --west-runner + " + + all_opts="$bool_opts $dir_opts $file_opts $special_opts $other_opts" + + case "$prev" in + --platform|-p|--exclude-platform|-P|--coverage-platform) + __set_comp_west_boards + return + ;; + + --coverage-tool) + __set_comp "gcovr lcov" + return + ;; + + --filter) + __set_comp "buildable runnable" + return + ;; + + --runtime-artifact-cleanup|-M) + __set_comp "all pass" + return + ;; + + $(__west_to_extglob "$dir_opts") ) + __set_comp_dirs + return + ;; + + $(__west_to_extglob "$file_opts") ) + __set_comp_files + return + ;; + + # We don't know how to autocomplete those + $(__west_to_extglob "$other_opts") ) + return + ;; + esac + + case "$cur" in + -*) + __set_comp $all_opts + ;; + esac +} __comp_west() { @@ -963,6 +1132,7 @@ __comp_west() zephyr-export spdx blobs + twister ) local cmds=(${builtin_cmds[*]} ${zephyr_ext_cmds[*]}) From 7a39f7223a37872f6718acd4ed5ffb8b414d30a3 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0336/1389] boards stm32h747i_disco: Add missing mdio node Akin to the changes in ab29ee5e0b3e07afdca308255487703d940ced32 Add missing mdio node for stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7 Without this, samples/net/sockets/echo_server fails to build in this board. Signed-off-by: Alberto Escolar Piedras --- .../stm32h747i_disco_stm32h747xx_m7.dts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts index 8f27eb0f8365df..a660f92af1772a 100644 --- a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts +++ b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts @@ -130,9 +130,7 @@ */ status = "okay"; pinctrl-0 = <ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 - ð_mdc_pc1 ð_rxd0_pc4 ð_rxd1_pc5 ð_tx_en_pg11 @@ -141,6 +139,18 @@ pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &rng { status = "okay"; }; From dd3a9043616b472773789ad1c7fd517978f7392c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0337/1389] drivers: fix bad SPDX-License-Identifier header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix typo in SPDX header Signed-off-by: Benjamin Cabé --- drivers/adc/Kconfig.ad559x | 2 +- drivers/dac/Kconfig.ad559x | 2 +- drivers/dac/Kconfig.ad569x | 2 +- drivers/mfd/Kconfig.ad559x | 2 +- drivers/mfd/Kconfig.axp192 | 2 +- drivers/mfd/Kconfig.bd8lb600fs | 2 +- drivers/mfd/Kconfig.max20335 | 2 +- drivers/mfd/Kconfig.max31790 | 2 +- drivers/mfd/Kconfig.nct38xx | 2 +- drivers/mfd/Kconfig.npm1300 | 2 +- drivers/mfd/Kconfig.npm6001 | 2 +- drivers/mfd/Kconfig.tle9104 | 2 +- drivers/regulator/Kconfig.adp5360 | 2 +- drivers/regulator/Kconfig.axp192 | 2 +- drivers/regulator/Kconfig.max20335 | 2 +- drivers/regulator/Kconfig.npm1100 | 2 +- drivers/regulator/Kconfig.npm1300 | 2 +- drivers/regulator/Kconfig.npm6001 | 2 +- drivers/regulator/Kconfig.nxp_vref | 2 +- drivers/regulator/Kconfig.pca9420 | 2 +- drivers/sdhc/Kconfig.esp32 | 2 +- drivers/sdhc/Kconfig.imx | 2 +- drivers/sdhc/Kconfig.mcux_sdif | 2 +- drivers/sdhc/Kconfig.sam_hsmci | 2 +- drivers/sdhc/Kconfig.spi | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/adc/Kconfig.ad559x b/drivers/adc/Kconfig.ad559x index 7c5f65bb745581..70cb0474a0274f 100644 --- a/drivers/adc/Kconfig.ad559x +++ b/drivers/adc/Kconfig.ad559x @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config ADC_AD559X bool "AD559x ADC driver" diff --git a/drivers/dac/Kconfig.ad559x b/drivers/dac/Kconfig.ad559x index 5266680199f3fd..7bfcccb492e817 100644 --- a/drivers/dac/Kconfig.ad559x +++ b/drivers/dac/Kconfig.ad559x @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config DAC_AD559X bool "AD559x DAC driver" diff --git a/drivers/dac/Kconfig.ad569x b/drivers/dac/Kconfig.ad569x index e40e8fc8e3beb8..0b6b6ab2e108a1 100644 --- a/drivers/dac/Kconfig.ad569x +++ b/drivers/dac/Kconfig.ad569x @@ -1,5 +1,5 @@ # Copyright (c) 2024 Jan Kubiznak -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config DAC_AD569X bool "Analog Devices AD5691 / AD5692 / AD5693 DAC driver" diff --git a/drivers/mfd/Kconfig.ad559x b/drivers/mfd/Kconfig.ad559x index 1597f60e3b244f..ff0a49549428da 100644 --- a/drivers/mfd/Kconfig.ad559x +++ b/drivers/mfd/Kconfig.ad559x @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 menuconfig MFD_AD559X bool "Analog AD559x I2C/SPI configurable ADC/DAC/GPIO chip" diff --git a/drivers/mfd/Kconfig.axp192 b/drivers/mfd/Kconfig.axp192 index fed776d3656456..da76c4cc615a8f 100644 --- a/drivers/mfd/Kconfig.axp192 +++ b/drivers/mfd/Kconfig.axp192 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Martin Kiepfer -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_AXP192 bool "AXP192 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.bd8lb600fs b/drivers/mfd/Kconfig.bd8lb600fs index 4029f1f2e85cbe..752eb942fe41ef 100644 --- a/drivers/mfd/Kconfig.bd8lb600fs +++ b/drivers/mfd/Kconfig.bd8lb600fs @@ -1,5 +1,5 @@ # Copyright (c) 2024 SILA Embedded Solutions GmbH -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_BD8LB600FS bool "BD8LB600FS low side switch multi-function device driver" diff --git a/drivers/mfd/Kconfig.max20335 b/drivers/mfd/Kconfig.max20335 index 3d146de17f089e..bc9ee006edc176 100644 --- a/drivers/mfd/Kconfig.max20335 +++ b/drivers/mfd/Kconfig.max20335 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_MAX20335 bool "MAX20335 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.max31790 b/drivers/mfd/Kconfig.max31790 index 2c542982d9fb05..1e2e9ac4e111ab 100644 --- a/drivers/mfd/Kconfig.max31790 +++ b/drivers/mfd/Kconfig.max31790 @@ -1,5 +1,5 @@ # Copyright (c) 2024 SILA Embedded Solutions GmbH -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_MAX31790 bool "Maxim Integrated MAX31790 I2C configurable PWM controller" diff --git a/drivers/mfd/Kconfig.nct38xx b/drivers/mfd/Kconfig.nct38xx index aa852d974bb1b3..743e07689b6a59 100644 --- a/drivers/mfd/Kconfig.nct38xx +++ b/drivers/mfd/Kconfig.nct38xx @@ -1,5 +1,5 @@ # Copyright (c) 2023 Google, LLC -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_NCT38XX bool "Nuvton NCT38xx multi-function device driver" diff --git a/drivers/mfd/Kconfig.npm1300 b/drivers/mfd/Kconfig.npm1300 index 506508bd902103..56a54f3005ab84 100644 --- a/drivers/mfd/Kconfig.npm1300 +++ b/drivers/mfd/Kconfig.npm1300 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_NPM1300 bool "nPM1300 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.npm6001 b/drivers/mfd/Kconfig.npm6001 index b81c942f2d63c2..46c0bc0d9c5488 100644 --- a/drivers/mfd/Kconfig.npm6001 +++ b/drivers/mfd/Kconfig.npm6001 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_NPM6001 bool "nPM6001 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.tle9104 b/drivers/mfd/Kconfig.tle9104 index 8432e067adbf0d..e102eec013b68d 100644 --- a/drivers/mfd/Kconfig.tle9104 +++ b/drivers/mfd/Kconfig.tle9104 @@ -1,5 +1,5 @@ # Copyright (c) 2024 SILA Embedded Solutions GmbH -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_TLE9104 bool "Infineon TLE9104 SPI powertrain switch" diff --git a/drivers/regulator/Kconfig.adp5360 b/drivers/regulator/Kconfig.adp5360 index 0785ba54abf0ad..f93df2ef163ed6 100644 --- a/drivers/regulator/Kconfig.adp5360 +++ b/drivers/regulator/Kconfig.adp5360 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_ADP5360 bool "ADP5360 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.axp192 b/drivers/regulator/Kconfig.axp192 index 8c8fad5cdb44ce..b56868ccdb7a11 100644 --- a/drivers/regulator/Kconfig.axp192 +++ b/drivers/regulator/Kconfig.axp192 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Martin Kiepfer -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_AXP192 bool "X-Power AXP192 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.max20335 b/drivers/regulator/Kconfig.max20335 index a92743afdb5367..df0eafe5158139 100644 --- a/drivers/regulator/Kconfig.max20335 +++ b/drivers/regulator/Kconfig.max20335 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_MAX20335 bool "MAX20335 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.npm1100 b/drivers/regulator/Kconfig.npm1100 index 56301a7beca2f2..97c7cbefc35b03 100644 --- a/drivers/regulator/Kconfig.npm1100 +++ b/drivers/regulator/Kconfig.npm1100 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NPM1100 bool "nPM1100 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.npm1300 b/drivers/regulator/Kconfig.npm1300 index 997934cabb7988..19adee0ebab2f3 100644 --- a/drivers/regulator/Kconfig.npm1300 +++ b/drivers/regulator/Kconfig.npm1300 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NPM1300 bool "nPM1300 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.npm6001 b/drivers/regulator/Kconfig.npm6001 index a9c290475deac4..d171a4bdd6f9d5 100644 --- a/drivers/regulator/Kconfig.npm6001 +++ b/drivers/regulator/Kconfig.npm6001 @@ -1,5 +1,5 @@ # Copyright (c) 2022 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NPM6001 bool "nPM6001 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.nxp_vref b/drivers/regulator/Kconfig.nxp_vref index 3bfb068b786568..b26614b75daaa5 100644 --- a/drivers/regulator/Kconfig.nxp_vref +++ b/drivers/regulator/Kconfig.nxp_vref @@ -1,5 +1,5 @@ # Copyright 2023 NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NXP_VREF bool "NXP VREF peripheral driver" diff --git a/drivers/regulator/Kconfig.pca9420 b/drivers/regulator/Kconfig.pca9420 index 9a2d2377c61475..bf87ed50d23af2 100644 --- a/drivers/regulator/Kconfig.pca9420 +++ b/drivers/regulator/Kconfig.pca9420 @@ -1,5 +1,5 @@ # Copyright (c) 2021, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_PCA9420 bool "NXP PCA9420 PMIC regulator driver" diff --git a/drivers/sdhc/Kconfig.esp32 b/drivers/sdhc/Kconfig.esp32 index e5c505885bcf0e..cf95a4317a03b8 100644 --- a/drivers/sdhc/Kconfig.esp32 +++ b/drivers/sdhc/Kconfig.esp32 @@ -1,5 +1,5 @@ # Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config SDHC_ESP32 bool "ESP32 SDHC Driver" diff --git a/drivers/sdhc/Kconfig.imx b/drivers/sdhc/Kconfig.imx index 48e47a126212ad..47bb84db553f2b 100644 --- a/drivers/sdhc/Kconfig.imx +++ b/drivers/sdhc/Kconfig.imx @@ -1,5 +1,5 @@ # Copyright (c) 2022, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config IMX_USDHC bool "NXP IMX USDHC Driver" diff --git a/drivers/sdhc/Kconfig.mcux_sdif b/drivers/sdhc/Kconfig.mcux_sdif index 528df6de763aaf..2b66a42e5641dc 100644 --- a/drivers/sdhc/Kconfig.mcux_sdif +++ b/drivers/sdhc/Kconfig.mcux_sdif @@ -1,5 +1,5 @@ # Copyright 2022, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MCUX_SDIF bool "NXP MCUX SDIF Driver" diff --git a/drivers/sdhc/Kconfig.sam_hsmci b/drivers/sdhc/Kconfig.sam_hsmci index 68265dcabed1c4..fca9bafdaffebe 100644 --- a/drivers/sdhc/Kconfig.sam_hsmci +++ b/drivers/sdhc/Kconfig.sam_hsmci @@ -1,5 +1,5 @@ # Copyright 2023 Nikhef -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config SAM_HSMCI bool "ATMEL SAM HSMCI driver" diff --git a/drivers/sdhc/Kconfig.spi b/drivers/sdhc/Kconfig.spi index 555f11619b0aec..ce861f1d02df4b 100644 --- a/drivers/sdhc/Kconfig.spi +++ b/drivers/sdhc/Kconfig.spi @@ -1,5 +1,5 @@ # Copyright (c) 2022, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config SPI_SDHC bool "SD protocol over SPI bus" From 166b16901516e57b462104b938332df232f7aa0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0338/1389] dts: fix bad SPDX-License-Identifier header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix typo in SPDX header Signed-off-by: Benjamin Cabé --- dts/bindings/charger/maxim,max20335-charger.yaml | 2 +- dts/bindings/regulator/adi,adp5360-regulator.yaml | 2 +- dts/bindings/regulator/cirrus,cp9314.yaml | 2 +- dts/bindings/regulator/maxim,max20335-regulator.yaml | 2 +- dts/bindings/regulator/nordic,npm1100.yaml | 2 +- dts/bindings/regulator/nordic,npm1300-regulator.yaml | 2 +- dts/bindings/regulator/nordic,npm6001-regulator.yaml | 2 +- dts/bindings/regulator/nxp,pca9420.yaml | 2 +- dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml | 2 +- dts/bindings/regulator/renesas,da1469x-regulator.yaml | 2 +- dts/bindings/regulator/x-powers,axp192-regulator.yaml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dts/bindings/charger/maxim,max20335-charger.yaml b/dts/bindings/charger/maxim,max20335-charger.yaml index 3fe44c92908f12..00fc9c41f11b39 100644 --- a/dts/bindings/charger/maxim,max20335-charger.yaml +++ b/dts/bindings/charger/maxim,max20335-charger.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: Maxim MAX20335 battery charger diff --git a/dts/bindings/regulator/adi,adp5360-regulator.yaml b/dts/bindings/regulator/adi,adp5360-regulator.yaml index e54a305e80f892..05d173826029b7 100644 --- a/dts/bindings/regulator/adi,adp5360-regulator.yaml +++ b/dts/bindings/regulator/adi,adp5360-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Analog Devices ADP3560 PMIC diff --git a/dts/bindings/regulator/cirrus,cp9314.yaml b/dts/bindings/regulator/cirrus,cp9314.yaml index c5b3c973b44e6e..9718c20b39145a 100644 --- a/dts/bindings/regulator/cirrus,cp9314.yaml +++ b/dts/bindings/regulator/cirrus,cp9314.yaml @@ -1,5 +1,5 @@ # Copyright (c) 2024 Cirrus Logic, Inc. -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Cirrus CP9314 Buck Switched Cap DC/DC Converter diff --git a/dts/bindings/regulator/maxim,max20335-regulator.yaml b/dts/bindings/regulator/maxim,max20335-regulator.yaml index d23a1fdf1c1ef5..90324568172c29 100644 --- a/dts/bindings/regulator/maxim,max20335-regulator.yaml +++ b/dts/bindings/regulator/maxim,max20335-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Maxim MAX20335 PMIC diff --git a/dts/bindings/regulator/nordic,npm1100.yaml b/dts/bindings/regulator/nordic,npm1100.yaml index b70523cfadd375..bf1a77a2ac83d3 100644 --- a/dts/bindings/regulator/nordic,npm1100.yaml +++ b/dts/bindings/regulator/nordic,npm1100.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Nordic nPM1100 PMIC diff --git a/dts/bindings/regulator/nordic,npm1300-regulator.yaml b/dts/bindings/regulator/nordic,npm1300-regulator.yaml index e0fc28ff8be4e9..cdb0999b23a964 100644 --- a/dts/bindings/regulator/nordic,npm1300-regulator.yaml +++ b/dts/bindings/regulator/nordic,npm1300-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Nordic nPM1300 PMIC diff --git a/dts/bindings/regulator/nordic,npm6001-regulator.yaml b/dts/bindings/regulator/nordic,npm6001-regulator.yaml index 378f6c0a8ecd1f..731ebe828c3b4d 100644 --- a/dts/bindings/regulator/nordic,npm6001-regulator.yaml +++ b/dts/bindings/regulator/nordic,npm6001-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2022 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Nordic nPM6001 PMIC diff --git a/dts/bindings/regulator/nxp,pca9420.yaml b/dts/bindings/regulator/nxp,pca9420.yaml index 2e4584d0a67dce..10e48a13348d00 100644 --- a/dts/bindings/regulator/nxp,pca9420.yaml +++ b/dts/bindings/regulator/nxp,pca9420.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2021 NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | NXP PCA9420 PMIC diff --git a/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml b/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml index 2034ccd2c0fae3..2dc1c7d0e891e5 100644 --- a/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml +++ b/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 TOKITA Hiroshi -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | RaspberryPi Pico core supply regurator diff --git a/dts/bindings/regulator/renesas,da1469x-regulator.yaml b/dts/bindings/regulator/renesas,da1469x-regulator.yaml index 2537b7e09d7da8..d8a064a179f5d3 100644 --- a/dts/bindings/regulator/renesas,da1469x-regulator.yaml +++ b/dts/bindings/regulator/renesas,da1469x-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Renesas Electronics Corporation -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Renesas Smartbond(tm) LDO and DCDC regulators diff --git a/dts/bindings/regulator/x-powers,axp192-regulator.yaml b/dts/bindings/regulator/x-powers,axp192-regulator.yaml index 9072e80727b35d..5fcbda2c8471e7 100644 --- a/dts/bindings/regulator/x-powers,axp192-regulator.yaml +++ b/dts/bindings/regulator/x-powers,axp192-regulator.yaml @@ -1,6 +1,6 @@ # Copyright (c), 2021 NXP # Copyright (c), 2023 Martin Kiepfer -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | AXP192 PMIC From 1bdf37b7752724584d79999b381cc127d4fb0a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0339/1389] samples: fix bad SPDX-License-Identifier header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix typo in SPDX header Signed-off-by: Benjamin Cabé --- samples/subsys/mgmt/updatehub/overlay-802154.conf | 2 +- samples/subsys/mgmt/updatehub/overlay-ot.conf | 2 +- samples/subsys/mgmt/updatehub/overlay-wifi.conf | 2 +- samples/subsys/mgmt/updatehub/prj.conf | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/subsys/mgmt/updatehub/overlay-802154.conf b/samples/subsys/mgmt/updatehub/overlay-802154.conf index 0af13d78c26c08..05820f8800f3fc 100644 --- a/samples/subsys/mgmt/updatehub/overlay-802154.conf +++ b/samples/subsys/mgmt/updatehub/overlay-802154.conf @@ -1,5 +1,5 @@ # Copyright (c) 2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Disable default configs CONFIG_BT=n diff --git a/samples/subsys/mgmt/updatehub/overlay-ot.conf b/samples/subsys/mgmt/updatehub/overlay-ot.conf index d425f950a31ef9..cfd0742469efc1 100644 --- a/samples/subsys/mgmt/updatehub/overlay-ot.conf +++ b/samples/subsys/mgmt/updatehub/overlay-ot.conf @@ -1,5 +1,5 @@ # Copyright (c) 2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Disable default configs CONFIG_BT=n diff --git a/samples/subsys/mgmt/updatehub/overlay-wifi.conf b/samples/subsys/mgmt/updatehub/overlay-wifi.conf index de1fc9b8616fd9..4d3b3b9cf31f92 100644 --- a/samples/subsys/mgmt/updatehub/overlay-wifi.conf +++ b/samples/subsys/mgmt/updatehub/overlay-wifi.conf @@ -1,5 +1,5 @@ # Copyright (c) 2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Disable default configs CONFIG_NET_L2_ETHERNET=n diff --git a/samples/subsys/mgmt/updatehub/prj.conf b/samples/subsys/mgmt/updatehub/prj.conf index 0ea9be14f7a79f..e3b57ae4f339f5 100644 --- a/samples/subsys/mgmt/updatehub/prj.conf +++ b/samples/subsys/mgmt/updatehub/prj.conf @@ -1,5 +1,5 @@ # Copyright (c) 2018-2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 CONFIG_FLASH=y CONFIG_STREAM_FLASH=y CONFIG_FLASH_MAP=y From 85c1fc14484599f53255caab401a710fce313431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0340/1389] mgmt: fix bad SPDX-License-Identifier header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix typo in SPDX header Signed-off-by: Benjamin Cabé --- subsys/mgmt/hawkbit/Kconfig | 2 +- subsys/mgmt/updatehub/CMakeLists.txt | 2 +- subsys/mgmt/updatehub/Kconfig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subsys/mgmt/hawkbit/Kconfig b/subsys/mgmt/hawkbit/Kconfig index b0c3b35c1aff09..e2011fd4cadd1a 100644 --- a/subsys/mgmt/hawkbit/Kconfig +++ b/subsys/mgmt/hawkbit/Kconfig @@ -1,5 +1,5 @@ # Copyright (c) 2020 Linumiz -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 menuconfig HAWKBIT bool "Eclipse hawkBit Firmware Over-the-Air support" diff --git a/subsys/mgmt/updatehub/CMakeLists.txt b/subsys/mgmt/updatehub/CMakeLists.txt index 067e6168d97921..7db24bf51e2d7a 100644 --- a/subsys/mgmt/updatehub/CMakeLists.txt +++ b/subsys/mgmt/updatehub/CMakeLists.txt @@ -1,7 +1,7 @@ # # Copyright (c) 2018-2023 O.S.Systems # -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # zephyr_syscall_header( diff --git a/subsys/mgmt/updatehub/Kconfig b/subsys/mgmt/updatehub/Kconfig index bc1c4fb1d1c70c..93859499e5977f 100644 --- a/subsys/mgmt/updatehub/Kconfig +++ b/subsys/mgmt/updatehub/Kconfig @@ -1,5 +1,5 @@ # Copyright (c) 2018-2023 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 menuconfig UPDATEHUB bool"UpdateHub Firmware Over-the-Air support" From 3916d6b7d4a8861f4b2a8b3bc6a74b2ec81e1286 Mon Sep 17 00:00:00 2001 From: Armando Visconti Date: Sun, 26 May 2024 22:38:42 +0200 Subject: [PATCH 0341/1389] drivers/sensor: lsm6dsl: use sensor APIs to convert to units Make use of sensor_ug_to_ms2() and sensor_10udegrees_to_rad() APIs to convert from raw values into proper units (i.e. m/s^2 for accel and rad/s for gyro). It also improves measurement precision. Fixes #63980 Signed-off-by: Armando Visconti --- drivers/sensor/st/lsm6dsl/lsm6dsl.c | 21 +++++++++------------ drivers/sensor/st/lsm6dsl/lsm6dsl.h | 13 +++++-------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/sensor/st/lsm6dsl/lsm6dsl.c b/drivers/sensor/st/lsm6dsl/lsm6dsl.c index 0a0f35258045e4..a29b18e8fea17d 100644 --- a/drivers/sensor/st/lsm6dsl/lsm6dsl.c +++ b/drivers/sensor/st/lsm6dsl/lsm6dsl.c @@ -472,14 +472,12 @@ static int lsm6dsl_sample_fetch(const struct device *dev, static inline void lsm6dsl_accel_convert(struct sensor_value *val, int raw_val, float sensitivity) { - double dval; + int64_t dval; - /* Sensitivity is exposed in mg/LSB */ + /* Sensitivity is exposed in ug/LSB */ /* Convert to m/s^2 */ - dval = (double)(raw_val) * (double)sensitivity * SENSOR_G_DOUBLE / 1000; - val->val1 = (int32_t)dval; - val->val2 = (((int32_t)(dval * 1000)) % 1000) * 1000; - + dval = (int64_t)raw_val * sensitivity; + sensor_ug_to_ms2(dval, val); } static inline int lsm6dsl_accel_get_channel(enum sensor_channel chan, @@ -522,13 +520,12 @@ static int lsm6dsl_accel_channel_get(enum sensor_channel chan, static inline void lsm6dsl_gyro_convert(struct sensor_value *val, int raw_val, float sensitivity) { - double dval; + int64_t dval; - /* Sensitivity is exposed in mdps/LSB */ - /* Convert to rad/s */ - dval = (double)(raw_val * (double)sensitivity * SENSOR_DEG2RAD_DOUBLE / 1000); - val->val1 = (int32_t)dval; - val->val2 = (((int32_t)(dval * 1000)) % 1000) * 1000; + /* Sensitivity is exposed in udps/LSB */ + /* So, calculate value in 10 udps unit and then to rad/s */ + dval = (int64_t)raw_val * sensitivity / 10; + sensor_10udegrees_to_rad(dval, val); } static inline int lsm6dsl_gyro_get_channel(enum sensor_channel chan, diff --git a/drivers/sensor/st/lsm6dsl/lsm6dsl.h b/drivers/sensor/st/lsm6dsl/lsm6dsl.h index da176f4f6923f5..524cc6bd314c64 100644 --- a/drivers/sensor/st/lsm6dsl/lsm6dsl.h +++ b/drivers/sensor/st/lsm6dsl/lsm6dsl.h @@ -553,14 +553,11 @@ #define LSM6DSL_REG_Z_OFS_USR 0x75 -/* Accel sensor sensitivity grain is 0.061 mg/LSB */ -#define SENSI_GRAIN_XL (61LL / 1000.0) - -/* Gyro sensor sensitivity grain is 4.375 mdps/LSB */ -#define SENSI_GRAIN_G (4375LL / 1000.0) -#define SENSOR_PI_DOUBLE (SENSOR_PI / 1000000.0) -#define SENSOR_DEG2RAD_DOUBLE (SENSOR_PI_DOUBLE / 180) -#define SENSOR_G_DOUBLE (SENSOR_G / 1000000.0) +/* Accel sensor sensitivity grain is 61 ug/LSB */ +#define SENSI_GRAIN_XL 61LL + +/* Gyro sensor sensitivity grain is 4375 udps/LSB */ +#define SENSI_GRAIN_G 4375LL #if CONFIG_LSM6DSL_ACCEL_FS == 0 #define LSM6DSL_ACCEL_FS_RUNTIME 1 From 635d48bc98d58e2a544ad30fd38de5b7f7f37418 Mon Sep 17 00:00:00 2001 From: Nick Ward Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0342/1389] drivers: gpio: shell: add toggle command Usage: gpio toggle [device] [pin] Also added Kconfig option so this command can be removed if resources need to be conserved. Signed-off-by: Nick Ward --- drivers/gpio/Kconfig | 7 +++++++ drivers/gpio/gpio_shell.c | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 12caaac1378d26..45d0129841e30c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -29,6 +29,13 @@ config GPIO_SHELL_INFO_CMD This command provides a shell user extra information about gpio controller reserved pins and line names. +config GPIO_SHELL_TOGGLE_CMD + bool "GPIO Shell toggle command" + default y + depends on GPIO_SHELL + help + Enable GPIO Shell toggle command. + config GPIO_SHELL_BLINK_CMD bool "GPIO Shell blink command" default y diff --git a/drivers/gpio/gpio_shell.c b/drivers/gpio/gpio_shell.c index 48d7e95f7a7525..7bb6b9c58cd863 100644 --- a/drivers/gpio/gpio_shell.c +++ b/drivers/gpio/gpio_shell.c @@ -381,6 +381,26 @@ static int cmd_gpio_set(const struct shell *sh, size_t argc, char **argv) return 0; } +static int cmd_gpio_toggle(const struct shell *sh, size_t argc, char **argv) +{ + struct sh_gpio gpio; + int ret = 0; + + ret = get_sh_gpio(sh, argv, &gpio); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + ret = gpio_pin_toggle(gpio.dev, gpio.pin); + if (ret != 0) { + shell_error(sh, "error: %d", ret); + return ret; + } + + return 0; +} + /* 500 msec = 1/2 sec */ #define SLEEP_TIME_MS 500 @@ -595,6 +615,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio, SHELL_CMD_ARG(set, &sub_gpio_dev, "Set GPIO pin value\n" "Usage: gpio set ", cmd_gpio_set, 4, 0), + SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_TOGGLE_CMD, toggle, &sub_gpio_dev, + "Toggle GPIO pin\n" + "Usage: gpio toggle ", cmd_gpio_toggle, 3, 0), SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_BLINK_CMD, blink, &sub_gpio_dev, "Blink GPIO pin\n" "Usage: gpio blink ", cmd_gpio_blink, 3, 0), From 71dc326f8f647b5008f572ab7a6e4fe356ff8e99 Mon Sep 17 00:00:00 2001 From: Nick Ward Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0343/1389] drivers: sensor: adxl362: fix temperature conversion It was missing the test condition for the temperature sensor. Signed-off-by: Nick Ward --- drivers/sensor/adi/adxl362/adxl362.c | 3 ++- drivers/sensor/adi/adxl362/adxl362.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/sensor/adi/adxl362/adxl362.c b/drivers/sensor/adi/adxl362/adxl362.c index 9d387881182134..fcd94b1792bb7d 100644 --- a/drivers/sensor/adi/adxl362/adxl362.c +++ b/drivers/sensor/adi/adxl362/adxl362.c @@ -561,7 +561,8 @@ static void adxl362_accel_convert(struct sensor_value *val, int accel, static void adxl362_temp_convert(struct sensor_value *val, int temp) { /* See sensitivity and bias specifications in table 1 of datasheet */ - int milli_c = (temp - ADXL362_TEMP_BIAS_LSB) * ADXL362_TEMP_MC_PER_LSB; + int milli_c = (temp - ADXL362_TEMP_BIAS_LSB) * ADXL362_TEMP_MC_PER_LSB + + (ADXL362_TEMP_BIAS_TEST_CONDITION * 1000); val->val1 = milli_c / 1000; val->val2 = (milli_c % 1000) * 1000; diff --git a/drivers/sensor/adi/adxl362/adxl362.h b/drivers/sensor/adi/adxl362/adxl362.h index 5dea56e107a74e..ac41a2ff2ee983 100644 --- a/drivers/sensor/adi/adxl362/adxl362.h +++ b/drivers/sensor/adi/adxl362/adxl362.h @@ -169,6 +169,7 @@ /* ADXL362 temperature sensor specifications */ #define ADXL362_TEMP_MC_PER_LSB 65 #define ADXL362_TEMP_BIAS_LSB 350 +#define ADXL362_TEMP_BIAS_TEST_CONDITION 25 struct adxl362_config { struct spi_dt_spec bus; From 89c94e43c5e3db8c183812a4d50e3356dbfa3a89 Mon Sep 17 00:00:00 2001 From: Maciej Baczmanski Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0344/1389] kconfig: openthread: Fix PSA Key Ref config for RCP architecture `OPENTHREAD_PLATFORM_KEY_REF` should not be selected for RCP architecture, as keys are handled on host's side and passed to device over Spinel, and therefore they cannot be exported on platform from reference with PSA Crypto API. Signed-off-by: Maciej Baczmanski --- subsys/net/l2/openthread/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/l2/openthread/Kconfig b/subsys/net/l2/openthread/Kconfig index ef71e411b4e1ce..9673aa7702a083 100644 --- a/subsys/net/l2/openthread/Kconfig +++ b/subsys/net/l2/openthread/Kconfig @@ -323,8 +323,8 @@ config OPENTHREAD_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE config OPENTHREAD_CRYPTO_PSA bool "ARM PSA crypto API" depends on MBEDTLS_PSA_CRYPTO_C || BUILD_WITH_TFM - select OPENTHREAD_PLATFORM_KEY_REF - select OPENTHREAD_PLATFORM_KEYS_EXPORTABLE_ENABLE + select OPENTHREAD_PLATFORM_KEY_REF if !OPENTHREAD_COPROCESSOR_RCP + imply OPENTHREAD_PLATFORM_KEYS_EXPORTABLE_ENABLE help Enable crypto backend library implementation based on ARM PSA crypto API instead of the default, using mbedTLS. From 18c17538c5ac92bd58c729dceb68b59b1b0b7a47 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0345/1389] Bluetooth: Controller: BIG/CIG count based upon app configs When building ISO applications on a device that has the host and controller on the same core, the application developer shouldn't have to set controller specific configurations. Signed-off-by: Rubin Gerritsen --- subsys/bluetooth/controller/Kconfig | 5 +++-- tests/bluetooth/controller/ctrl_cis_create/prj.conf | 2 -- tests/bluetooth/controller/ctrl_cis_terminate/prj.conf | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 81bcd7ecc53deb..4a966987bd1bac 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -790,6 +790,7 @@ config BT_CTLR_ADV_ISO_SET int "LE Isochronous Channel advertising sets" depends on BT_CTLR_ADV_ISO range 1 32 + default BT_ISO_MAX_BIG help Maximum supported advertising sets. @@ -821,7 +822,7 @@ config BT_CTLR_SCAN_SYNC_ISO_SET int "LE ISO Broadcast Isochronous Groups Sync Sets" depends on BT_CTLR_SYNC_ISO range 1 64 - default 1 + default BT_ISO_MAX_BIG help Maximum supported broadcast isochronous groups (BIGs) sync sets. @@ -904,7 +905,7 @@ config BT_CTLR_CONN_ISO_GROUPS int "LE Connected Isochronous Groups" depends on BT_CTLR_CONN_ISO range 1 240 - default 1 + default BT_ISO_MAX_CIG help Maximum supported CIGs. diff --git a/tests/bluetooth/controller/ctrl_cis_create/prj.conf b/tests/bluetooth/controller/ctrl_cis_create/prj.conf index dabc6c65cfef46..3074f9f35d1df4 100644 --- a/tests/bluetooth/controller/ctrl_cis_create/prj.conf +++ b/tests/bluetooth/controller/ctrl_cis_create/prj.conf @@ -31,8 +31,6 @@ CONFIG_BT_CTLR_PHY_2M=y CONFIG_BT_CTLR_PHY_CODED=y CONFIG_BT_CTLR_ADV_EXT=y -CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_SYNC_ISO=y CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y diff --git a/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf b/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf index dabc6c65cfef46..3074f9f35d1df4 100644 --- a/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf +++ b/tests/bluetooth/controller/ctrl_cis_terminate/prj.conf @@ -31,8 +31,6 @@ CONFIG_BT_CTLR_PHY_2M=y CONFIG_BT_CTLR_PHY_CODED=y CONFIG_BT_CTLR_ADV_EXT=y -CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_SYNC_ISO=y CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y From f75317de61eb84627b265fd5c9319054ff8b47a8 Mon Sep 17 00:00:00 2001 From: Eran Gal Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0346/1389] drivers: i2c_shell: Add direct_read sub command Adds a direct_read subcommand to the I2C command. Usage: I2C direct_read []. This command reads directly from the I2C device without first writing a register address. Signed-off-by: Eran Gal --- drivers/i2c/i2c_shell.c | 54 +++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/i2c_shell.c b/drivers/i2c/i2c_shell.c index 4bbefcc5734e12..176a0d46c561d0 100644 --- a/drivers/i2c/i2c_shell.c +++ b/drivers/i2c/i2c_shell.c @@ -195,9 +195,6 @@ static int i2c_read_to_buffer(const struct shell *shell_ctx, uint8_t *buf, uint8_t buf_length) { const struct device *dev; - uint8_t reg_addr_buf[MAX_BYTES_FOR_REGISTER_INDEX]; - int reg_addr_bytes; - int reg_addr; int dev_addr; int ret; @@ -209,15 +206,23 @@ static int i2c_read_to_buffer(const struct shell *shell_ctx, } dev_addr = strtol(s_dev_addr, NULL, 16); - reg_addr = strtol(s_reg_addr, NULL, 16); - reg_addr_bytes = get_bytes_count_for_hex(s_reg_addr); - sys_put_be32(reg_addr, reg_addr_buf); + if (s_reg_addr != NULL) { + uint8_t reg_addr_buf[MAX_BYTES_FOR_REGISTER_INDEX]; + int reg_addr_bytes; + int reg_addr; + + reg_addr = strtol(s_reg_addr, NULL, 16); + reg_addr_bytes = get_bytes_count_for_hex(s_reg_addr); + sys_put_be32(reg_addr, reg_addr_buf); + + ret = i2c_write_read(dev, dev_addr, + reg_addr_buf + MAX_BYTES_FOR_REGISTER_INDEX - reg_addr_bytes, + reg_addr_bytes, buf, buf_length); + } else { + ret = i2c_read(dev, buf, buf_length, dev_addr); + } - ret = i2c_write_read(dev, dev_addr, - reg_addr_buf + - MAX_BYTES_FOR_REGISTER_INDEX - reg_addr_bytes, - reg_addr_bytes, buf, buf_length); if (ret < 0) { shell_error(shell_ctx, "Failed to read from device: %s", s_dev_addr); @@ -270,6 +275,30 @@ static int cmd_i2c_read(const struct shell *shell_ctx, size_t argc, char **argv) return ret; } +/* i2c direct_read [] */ +static int cmd_i2c_direct_read(const struct shell *shell_ctx, size_t argc, char **argv) +{ + uint8_t buf[MAX_I2C_BYTES]; + int num_bytes; + int ret; + + if (argc > 3) { + num_bytes = strtol(argv[3], NULL, 16); + if (num_bytes > MAX_I2C_BYTES) { + num_bytes = MAX_I2C_BYTES; + } + } else { + num_bytes = MAX_I2C_BYTES; + } + + ret = i2c_read_to_buffer(shell_ctx, argv[ARGV_DEV], argv[ARGV_ADDR], NULL, buf, num_bytes); + if (ret == 0) { + shell_hexdump(shell_ctx, buf, num_bytes); + } + + return ret; +} + /* i2c speed * For: speed see constants like I2C_SPEED_STANDARD */ @@ -336,6 +365,11 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_i2c_cmds, "Read a byte from an I2C device\n" "Usage: read_byte ", cmd_i2c_read_byte, 4, 0), + SHELL_CMD_ARG(direct_read, &dsub_device_name, + "Read byte stream directly from an I2C device without " + "writing a register address first\n" + "Usage: direct_read []", + cmd_i2c_direct_read, 3, 1), SHELL_CMD_ARG(write, &dsub_device_name, "Write bytes to an I2C device\n" "Usage: write [, ...]", From 7216f5604d2c248184a0d989da9c61a667f16b1c Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0347/1389] Bluetooth: bsim/att/pipeline: add rx tx priority inverted prj Resolves: https://github.com/zephyrproject-rtos/zephyr/issues/71444 Signed-off-by: Aleksander Wasaznik --- tests/bsim/bluetooth/host/att/compile.sh | 2 + .../bluetooth/host/att/pipeline/dut/Kconfig | 14 +++++ .../pipeline/dut/rx_tx_prio_invert.extra.conf | 2 + .../att/pipeline/test_scripts/_compile.sh | 1 + ..._not_pipeline_variant_rx_tx_prio_invert.sh | 50 +++++++++++++++++ ...rate_pipeline_variant_rx_tx_prio_invert.sh | 55 +++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 tests/bsim/bluetooth/host/att/pipeline/dut/Kconfig create mode 100644 tests/bsim/bluetooth/host/att/pipeline/dut/rx_tx_prio_invert.extra.conf create mode 100755 tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_shall_not_pipeline_variant_rx_tx_prio_invert.sh create mode 100755 tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_tolerate_pipeline_variant_rx_tx_prio_invert.sh diff --git a/tests/bsim/bluetooth/host/att/compile.sh b/tests/bsim/bluetooth/host/att/compile.sh index b3da250ba1b027..59d232be3a4ca6 100755 --- a/tests/bsim/bluetooth/host/att/compile.sh +++ b/tests/bsim/bluetooth/host/att/compile.sh @@ -23,6 +23,8 @@ app=tests/bsim/bluetooth/host/att/retry_on_sec_err/server compile app=tests/bsim/bluetooth/host/att/sequential/dut compile app=tests/bsim/bluetooth/host/att/sequential/tester compile app=tests/bsim/bluetooth/host/att/pipeline/dut compile +app=tests/bsim/bluetooth/host/att/pipeline/dut \ + conf_file='prj.conf;rx_tx_prio_invert.extra.conf' compile app=tests/bsim/bluetooth/host/att/pipeline/tester compile app=tests/bsim/bluetooth/host/att/long_read compile app=tests/bsim/bluetooth/host/att/open_close compile diff --git a/tests/bsim/bluetooth/host/att/pipeline/dut/Kconfig b/tests/bsim/bluetooth/host/att/pipeline/dut/Kconfig new file mode 100644 index 00000000000000..71d844b76ee93f --- /dev/null +++ b/tests/bsim/bluetooth/host/att/pipeline/dut/Kconfig @@ -0,0 +1,14 @@ +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# This file adds prompts to allow setting the symbols in a +# configuration file (e.g. 'prj.conf'), as needed for some of +# the test variants. + +config BT_HCI_TX_PRIO + prompt "" + +config BT_RX_PRIO + prompt "" + +source "Kconfig.zephyr" diff --git a/tests/bsim/bluetooth/host/att/pipeline/dut/rx_tx_prio_invert.extra.conf b/tests/bsim/bluetooth/host/att/pipeline/dut/rx_tx_prio_invert.extra.conf new file mode 100644 index 00000000000000..555da337bf587c --- /dev/null +++ b/tests/bsim/bluetooth/host/att/pipeline/dut/rx_tx_prio_invert.extra.conf @@ -0,0 +1,2 @@ +CONFIG_BT_HCI_TX_PRIO=8 +CONFIG_BT_RX_PRIO=7 diff --git a/tests/bsim/bluetooth/host/att/pipeline/test_scripts/_compile.sh b/tests/bsim/bluetooth/host/att/pipeline/test_scripts/_compile.sh index ff0f485b17d58b..06d5d718a9dca9 100755 --- a/tests/bsim/bluetooth/host/att/pipeline/test_scripts/_compile.sh +++ b/tests/bsim/bluetooth/host/att/pipeline/test_scripts/_compile.sh @@ -8,6 +8,7 @@ INCR_BUILD=1 source ${ZEPHYR_BASE}/tests/bsim/compile.source app="$(guess_test_relpath)"/dut compile +app="$(guess_test_relpath)"/dut conf_file='prj.conf;rx_tx_prio_invert.extra.conf' compile app="$(guess_test_relpath)"/tester compile wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_shall_not_pipeline_variant_rx_tx_prio_invert.sh b/tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_shall_not_pipeline_variant_rx_tx_prio_invert.sh new file mode 100755 index 00000000000000..d271c9c04fad3e --- /dev/null +++ b/tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_shall_not_pipeline_variant_rx_tx_prio_invert.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Copyright 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Test purpose: +# +# Basic check that the DUT GATT client does not pipeline ATT +# requests. +# +# Sending a new request on a bearer before the response to the +# previous request has been received ('pipelining') is a +# protocol violation. +# +# Test variant 'rx_tx_prio_invert': +# +# - The priority of the RX and TX threads is inverted compared +# to the default configuration. The result shall be the same. +# +# Test procedure: +# +# - DUT is excercised by calling `gatt_write` in a loop. +# - Tester does not immediately respond but delays the response +# a bit to ensure the LL has time to transport any extra +# requests, exposing a bug. +# - Tester verifies there is no such extra request while it's +# delaying the response. Detecting an extra request proves a +# protocol violation. + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +dut_exe="bs_${BOARD_TS}_tests_bsim_bluetooth_host_att_pipeline_dut_prj_conf" +dut_exe+="_rx_tx_prio_invert_extra_conf" +tester_exe="bs_${BOARD_TS}_tests_bsim_bluetooth_host_att_pipeline_tester_prj_conf" + +simulation_id="att_pipeline_test_shall_not_pipeline_variant_rx_tx_prio_invert" +verbosity_level=2 +sim_length_us=100e6 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_2G4_phy_v1 \ + -v=${verbosity_level} -s="${simulation_id}" -D=2 -sim_length=${sim_length_us} $@ + +Execute "./$tester_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=1 -testid=tester_1 -RealEncryption=1 -rs=100 + +Execute "./$dut_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=0 -testid=dut_1 -RealEncryption=1 + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_tolerate_pipeline_variant_rx_tx_prio_invert.sh b/tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_tolerate_pipeline_variant_rx_tx_prio_invert.sh new file mode 100755 index 00000000000000..bc7928e349f52f --- /dev/null +++ b/tests/bsim/bluetooth/host/att/pipeline/test_scripts/run_test_tolerate_pipeline_variant_rx_tx_prio_invert.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Copyright 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Test purpose: +# +# Check that DUT GATT server gracefully handles a pipelining +# client. +# +# The DUT GATT server must remain available to a well-behaved +# peer while a bad peer tries to spam ATT requests. +# +# Test variant 'rx_tx_prio_invert': +# +# - The priority of the RX and TX threads is inverted compared +# to the default configuration. The result shall be the same. +# +# Test procedure: +# +# - The well-behaved peer performs a discovery procedure +# repeatedly. +# - The bad peer spams ATT requests as fast as possible. +# - The connection with the well-behaved peer shall remain +# responsive. +# - Either: The DUT may disconnect the bad peer ACL after +# receiving a protocol violation occurs. The bad peer shall +# be able to reconnect and continue the bad behavior. +# - Or: The DUT may process and respond to the pipelined +# requests, preserving their ordering. + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +dut_exe="bs_${BOARD_TS}_tests_bsim_bluetooth_host_att_pipeline_dut_prj_conf" +dut_exe+="_rx_tx_prio_invert_extra_conf" +tester_exe="bs_${BOARD_TS}_tests_bsim_bluetooth_host_att_pipeline_tester_prj_conf" + +simulation_id="att_pipeline_test_tolerate_pipeline_variant_rx_tx_prio_invert" +verbosity_level=2 +sim_length_us=100e6 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_2G4_phy_v1 \ + -v=${verbosity_level} -s="${simulation_id}" -D=3 -sim_length=${sim_length_us} $@ + +Execute "./$tester_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=2 -testid=tester -RealEncryption=1 -rs=100 + +Execute "./$dut_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=1 -testid=dut -RealEncryption=1 -rs=2000 + +Execute "./$dut_exe" \ + -v=${verbosity_level} -s="${simulation_id}" -d=0 -testid=dut -RealEncryption=1 + +wait_for_background_jobs From fd1d5bea5992142585926151615a0ee042cdbc75 Mon Sep 17 00:00:00 2001 From: Rafael Laya Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0348/1389] drivers: Fixes Controller Mode for I2C DW Driver 4996a9be262ca81bae717bdd8c2939db2a6876b7 adds Target Support for the Designware I2C Driver But the change missed guarding some places with CONFIG_I2C_TARGET This commit fixes regressions caused by such change Signed-off-by: Rafael Laya --- drivers/i2c/i2c_dw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index 73bb4b6cfe6616..6bb2fc5c64df1f 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -252,7 +252,9 @@ static inline void i2c_dw_data_ask(const struct device *dev) data |= IC_DATA_CMD_STOP; } +#ifdef CONFIG_I2C_TARGET clear_bit_intr_mask_tx_empty(reg_base); +#endif /* CONFIG_I2C_TARGET */ write_cmd_data(data, reg_base); @@ -413,6 +415,7 @@ static void i2c_dw_isr(const struct device *port) i2c_dw_data_read(port); } +#ifdef CONFIG_I2C_TARGET /* Check if the TX FIFO is ready for commands. * TX FIFO also serves as command queue where read requests * are written to TX FIFO. @@ -421,6 +424,7 @@ static void i2c_dw_isr(const struct device *port) == I2C_MSG_READ) { set_bit_intr_mask_tx_empty(reg_base); } +#endif /* CONFIG_I2C_TARGET */ if (intr_stat.bits.tx_empty) { if ((dw->xfr_flags & I2C_MSG_RW_MASK) From 590f05bc491260dcd750eb4b282908c2960c186f Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0349/1389] scripts: Update uf2conv.py from upstream git. Pull in the latest uf2conv.py and newly needed uf2families.json file to address Python warning on Python 3.12 and keep us in sync. Signed-off-by: Peter Johanson --- scripts/build/uf2conv.py | 181 ++++++++++++++---------- scripts/build/uf2families.json | 247 +++++++++++++++++++++++++++++++++ 2 files changed, 358 insertions(+), 70 deletions(-) create mode 100644 scripts/build/uf2families.json diff --git a/scripts/build/uf2conv.py b/scripts/build/uf2conv.py index 5da08efd5b964f..fd70895bc80405 100755 --- a/scripts/build/uf2conv.py +++ b/scripts/build/uf2conv.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Copyright (c) Microsoft Corporation # SPDX-License-Identifier: MIT -# Copied from 7a9e1f4 of https://github.com/microsoft/uf2/blob/master/utils/uf2conv.py +# Copied from 27e322f of https://github.com/microsoft/uf2/blob/master/utils/uf2conv.py # pylint: skip-file import sys import struct @@ -10,40 +10,14 @@ import os import os.path import argparse +import json +from time import sleep UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected UF2_MAGIC_END = 0x0AB16F30 # Ditto -families = { - 'SAMD21': 0x68ed2b88, - 'SAML21': 0x1851780a, - 'SAMD51': 0x55114460, - 'NRF52': 0x1b57745f, - 'STM32F0': 0x647824b6, - 'STM32F1': 0x5ee21072, - 'STM32F2': 0x5d1a0a2e, - 'STM32F3': 0x6b846188, - 'STM32F4': 0x57755a57, - 'STM32F7': 0x53b80f00, - 'STM32G0': 0x300f5633, - 'STM32G4': 0x4c71240a, - 'STM32H7': 0x6db66082, - 'STM32L0': 0x202e3a91, - 'STM32L1': 0x1e1f432d, - 'STM32L4': 0x00ff6919, - 'STM32L5': 0x04240bdf, - 'STM32WB': 0x70d16653, - 'STM32WL': 0x21460ff0, - 'ATMEGA32': 0x16573617, - 'MIMXRT10XX': 0x4FB2D5BD, - 'LPC55': 0x2abc77ec, - 'GD32F350': 0x31D228C6, - 'ESP32S2': 0xbfdd4eee, - 'RP2040': 0xe48bff56 -} - INFO_FILE = "/INFO_UF2.TXT" appstartaddr = 0x2000 @@ -59,14 +33,19 @@ def is_hex(buf): w = buf[0:30].decode("utf-8") except UnicodeDecodeError: return False - if w[0] == ':' and re.match(b"^[:0-9a-fA-F\r\n]+$", buf): + if w[0] == ':' and re.match(rb"^[:0-9a-fA-F\r\n]+$", buf): return True return False def convert_from_uf2(buf): global appstartaddr + global familyid numblocks = len(buf) // 512 curraddr = None + currfamilyid = None + families_found = {} + prev_flag = None + all_flags_same = True outp = [] for blockno in range(numblocks): ptr = blockno * 512 @@ -82,9 +61,13 @@ def convert_from_uf2(buf): if datalen > 476: assert False, "Invalid UF2 data size at " + ptr newaddr = hd[3] - if curraddr == None: - appstartaddr = newaddr + if (hd[2] & 0x2000) and (currfamilyid == None): + currfamilyid = hd[7] + if curraddr == None or ((hd[2] & 0x2000) and hd[7] != currfamilyid): + currfamilyid = hd[7] curraddr = newaddr + if familyid == 0x0 or familyid == hd[7]: + appstartaddr = newaddr padding = newaddr - curraddr if padding < 0: assert False, "Block out of order at " + ptr @@ -94,9 +77,38 @@ def convert_from_uf2(buf): assert False, "Non-word padding size at " + ptr while padding > 0: padding -= 4 - outp += b"\x00\x00\x00\x00" - outp.append(block[32 : 32 + datalen]) + outp.append(b"\x00\x00\x00\x00") + if familyid == 0x0 or ((hd[2] & 0x2000) and familyid == hd[7]): + outp.append(block[32 : 32 + datalen]) curraddr = newaddr + datalen + if hd[2] & 0x2000: + if hd[7] in families_found.keys(): + if families_found[hd[7]] > newaddr: + families_found[hd[7]] = newaddr + else: + families_found[hd[7]] = newaddr + if prev_flag == None: + prev_flag = hd[2] + if prev_flag != hd[2]: + all_flags_same = False + if blockno == (numblocks - 1): + print("--- UF2 File Header Info ---") + families = load_families() + for family_hex in families_found.keys(): + family_short_name = "" + for name, value in families.items(): + if value == family_hex: + family_short_name = name + print("Family ID is {:s}, hex value is 0x{:08x}".format(family_short_name,family_hex)) + print("Target Address is 0x{:08x}".format(families_found[family_hex])) + if all_flags_same: + print("All block flag values consistent, 0x{:04x}".format(hd[2])) + else: + print("Flags were not all the same") + print("----------------------------") + if len(families_found) > 1 and familyid == 0x0: + outp = [] + appstartaddr = 0x0 return b"".join(outp) def convert_to_carray(file_content): @@ -170,11 +182,10 @@ def convert_from_hex_to_uf2(buf): upper = ((rec[4] << 8) | rec[5]) << 16 elif tp == 2: upper = ((rec[4] << 8) | rec[5]) << 4 - assert (upper & 0xffff) == 0 elif tp == 1: break elif tp == 0: - addr = upper | (rec[1] << 8) | rec[2] + addr = upper + ((rec[1] << 8) | rec[2]) if appstartaddr == None: appstartaddr = addr i = 4 @@ -201,19 +212,21 @@ def get_drives(): "get", "DeviceID,", "VolumeName,", "FileSystem,", "DriveType"]) for line in to_str(r).split('\n'): - words = re.split('\s+', line) + words = re.split(r'\s+', line) if len(words) >= 3 and words[1] == "2" and words[2] == "FAT": drives.append(words[0]) else: - rootpath = "/media" + searchpaths = ["/media"] if sys.platform == "darwin": - rootpath = "/Volumes" + searchpaths = ["/Volumes"] elif sys.platform == "linux": - tmp = rootpath + "/" + os.environ["USER"] - if os.path.isdir(tmp): - rootpath = tmp - for d in os.listdir(rootpath): - drives.append(os.path.join(rootpath, d)) + searchpaths += ["/media/" + os.environ["USER"], '/run/media/' + os.environ["USER"]] + + for rootpath in searchpaths: + if os.path.isdir(rootpath): + for d in os.listdir(rootpath): + if os.path.isdir(rootpath): + drives.append(os.path.join(rootpath, d)) def has_info(d): @@ -228,7 +241,7 @@ def has_info(d): def board_id(path): with open(path + INFO_FILE, mode='r') as file: file_content = file.read() - return re.search("Board-ID: ([^\r\n]*)", file_content).group(1) + return re.search(r"Board-ID: ([^\r\n]*)", file_content).group(1) def list_drives(): @@ -242,36 +255,57 @@ def write_file(name, buf): print("Wrote %d bytes to %s" % (len(buf), name)) +def load_families(): + # The expectation is that the `uf2families.json` file is in the same + # directory as this script. Make a path that works using `__file__` + # which contains the full path to this script. + filename = "uf2families.json" + pathname = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename) + with open(pathname) as f: + raw_families = json.load(f) + + families = {} + for family in raw_families: + families[family["short_name"]] = int(family["id"], 0) + + return families + + def main(): global appstartaddr, familyid def error(msg): - print(msg) + print(msg, file=sys.stderr) sys.exit(1) - parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.', - allow_abbrev=False) + parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') parser.add_argument('input', metavar='INPUT', type=str, nargs='?', help='input file (HEX, BIN or UF2)') - parser.add_argument('-b' , '--base', dest='base', type=str, + parser.add_argument('-b', '--base', dest='base', type=str, default="0x2000", help='set base address of application for BIN format (default: 0x2000)') - parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, + parser.add_argument('-f', '--family', dest='family', type=str, + default="0x0", + help='specify familyID - number or name (default: 0x0)') + parser.add_argument('-o', '--output', metavar="FILE", dest='output', type=str, help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') - parser.add_argument('-d' , '--device', dest="device_path", + parser.add_argument('-d', '--device', dest="device_path", help='select a device path to flash') - parser.add_argument('-l' , '--list', action='store_true', + parser.add_argument('-l', '--list', action='store_true', help='list connected devices') - parser.add_argument('-c' , '--convert', action='store_true', + parser.add_argument('-c', '--convert', action='store_true', help='do not flash, just convert') - parser.add_argument('-D' , '--deploy', action='store_true', + parser.add_argument('-D', '--deploy', action='store_true', help='just flash, do not convert') - parser.add_argument('-f' , '--family', dest='family', type=str, - default="0x0", - help='specify familyID - number or name (default: 0x0)') - parser.add_argument('-C' , '--carray', action='store_true', + parser.add_argument('-w', '--wait', action='store_true', + help='wait for device to flash') + parser.add_argument('-C', '--carray', action='store_true', help='convert binary file to a C array, not UF2') + parser.add_argument('-i', '--info', action='store_true', + help='display header information from UF2, do not convert') args = parser.parse_args() appstartaddr = int(args.base, 0) + families = load_families() + if args.family.upper() in families: familyid = families[args.family.upper()] else: @@ -291,9 +325,12 @@ def error(msg): ext = "uf2" if args.deploy: outbuf = inpbuf - elif from_uf2: + elif from_uf2 and not args.info: outbuf = convert_from_uf2(inpbuf) ext = "bin" + elif from_uf2 and args.info: + outbuf = "" + convert_from_uf2(inpbuf) elif is_hex(inpbuf): outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8")) elif args.carray: @@ -301,23 +338,27 @@ def error(msg): ext = "h" else: outbuf = convert_to_uf2(inpbuf) - print("Converting to %s, output size: %d, start address: 0x%x" % - (ext, len(outbuf), appstartaddr)) + if not args.deploy and not args.info: + print("Converted to %s, output size: %d, start address: 0x%x" % + (ext, len(outbuf), appstartaddr)) if args.convert or ext != "uf2": - drives = [] if args.output == None: args.output = "flash." + ext - else: - drives = get_drives() - if args.output: write_file(args.output, outbuf) - else: + if ext == "uf2" and not args.convert and not args.info: + drives = get_drives() if len(drives) == 0: - error("No drive to deploy.") - for d in drives: - print("Flashing %s (%s)" % (d, board_id(d))) - write_file(d + "/NEW.UF2", outbuf) + if args.wait: + print("Waiting for drive to deploy...") + while len(drives) == 0: + sleep(0.1) + drives = get_drives() + elif not args.output: + error("No drive to deploy.") + for d in drives: + print("Flashing %s (%s)" % (d, board_id(d))) + write_file(d + "/NEW.UF2", outbuf) if __name__ == "__main__": diff --git a/scripts/build/uf2families.json b/scripts/build/uf2families.json new file mode 100644 index 00000000000000..14c8e5d043cb65 --- /dev/null +++ b/scripts/build/uf2families.json @@ -0,0 +1,247 @@ +[ + { + "id": "0x16573617", + "short_name": "ATMEGA32", + "description": "Microchip (Atmel) ATmega32" + }, + { + "id": "0x1851780a", + "short_name": "SAML21", + "description": "Microchip (Atmel) SAML21" + }, + { + "id": "0x1b57745f", + "short_name": "NRF52", + "description": "Nordic NRF52" + }, + { + "id": "0x1c5f21b0", + "short_name": "ESP32", + "description": "ESP32" + }, + { + "id": "0x1e1f432d", + "short_name": "STM32L1", + "description": "ST STM32L1xx" + }, + { + "id": "0x202e3a91", + "short_name": "STM32L0", + "description": "ST STM32L0xx" + }, + { + "id": "0x21460ff0", + "short_name": "STM32WL", + "description": "ST STM32WLxx" + }, + { + "id": "0x2abc77ec", + "short_name": "LPC55", + "description": "NXP LPC55xx" + }, + { + "id": "0x300f5633", + "short_name": "STM32G0", + "description": "ST STM32G0xx" + }, + { + "id": "0x31d228c6", + "short_name": "GD32F350", + "description": "GD32F350" + }, + { + "id": "0x04240bdf", + "short_name": "STM32L5", + "description": "ST STM32L5xx" + }, + { + "id": "0x4c71240a", + "short_name": "STM32G4", + "description": "ST STM32G4xx" + }, + { + "id": "0x4fb2d5bd", + "short_name": "MIMXRT10XX", + "description": "NXP i.MX RT10XX" + }, + { + "id": "0x53b80f00", + "short_name": "STM32F7", + "description": "ST STM32F7xx" + }, + { + "id": "0x55114460", + "short_name": "SAMD51", + "description": "Microchip (Atmel) SAMD51" + }, + { + "id": "0x57755a57", + "short_name": "STM32F4", + "description": "ST STM32F4xx" + }, + { + "id": "0x5a18069b", + "short_name": "FX2", + "description": "Cypress FX2" + }, + { + "id": "0x5d1a0a2e", + "short_name": "STM32F2", + "description": "ST STM32F2xx" + }, + { + "id": "0x5ee21072", + "short_name": "STM32F1", + "description": "ST STM32F103" + }, + { + "id": "0x621e937a", + "short_name": "NRF52833", + "description": "Nordic NRF52833" + }, + { + "id": "0x647824b6", + "short_name": "STM32F0", + "description": "ST STM32F0xx" + }, + { + "id": "0x68ed2b88", + "short_name": "SAMD21", + "description": "Microchip (Atmel) SAMD21" + }, + { + "id": "0x6b846188", + "short_name": "STM32F3", + "description": "ST STM32F3xx" + }, + { + "id": "0x6d0922fa", + "short_name": "STM32F407", + "description": "ST STM32F407" + }, + { + "id": "0x6db66082", + "short_name": "STM32H7", + "description": "ST STM32H7xx" + }, + { + "id": "0x70d16653", + "short_name": "STM32WB", + "description": "ST STM32WBxx" + }, + { + "id": "0x7eab61ed", + "short_name": "ESP8266", + "description": "ESP8266" + }, + { + "id": "0x7f83e793", + "short_name": "KL32L2", + "description": "NXP KL32L2x" + }, + { + "id": "0x8fb060fe", + "short_name": "STM32F407VG", + "description": "ST STM32F407VG" + }, + { + "id": "0xada52840", + "short_name": "NRF52840", + "description": "Nordic NRF52840" + }, + { + "id": "0xbfdd4eee", + "short_name": "ESP32S2", + "description": "ESP32-S2" + }, + { + "id": "0xc47e5767", + "short_name": "ESP32S3", + "description": "ESP32-S3" + }, + { + "id": "0xd42ba06c", + "short_name": "ESP32C3", + "description": "ESP32-C3" + }, + { + "id": "0x2b88d29c", + "short_name": "ESP32C2", + "description": "ESP32-C2" + }, + { + "id": "0x332726f6", + "short_name": "ESP32H2", + "description": "ESP32-H2" + }, + { + "id": "0x540ddf62", + "short_name": "ESP32C6", + "description": "ESP32-C6" + }, + { + "id": "0x3d308e94", + "short_name": "ESP32P4", + "description": "ESP32-P4" + }, + { + "id": "0xe48bff56", + "short_name": "RP2040", + "description": "Raspberry Pi RP2040" + }, + { + "id": "0x00ff6919", + "short_name": "STM32L4", + "description": "ST STM32L4xx" + }, + { + "id": "0x9af03e33", + "short_name": "GD32VF103", + "description": "GigaDevice GD32VF103" + }, + { + "id": "0x4f6ace52", + "short_name": "CSK4", + "description": "LISTENAI CSK300x/400x" + }, + { + "id": "0x6e7348a8", + "short_name": "CSK6", + "description": "LISTENAI CSK60xx" + }, + { + "id": "0x11de784a", + "short_name": "M0SENSE", + "description": "M0SENSE BL702" + }, + { + "id": "0x4b684d71", + "short_name": "MaixPlay-U4", + "description": "Sipeed MaixPlay-U4(BL618)" + }, + { + "id": "0x9517422f", + "short_name": "RZA1LU", + "description": "Renesas RZ/A1LU (R7S7210xx)" + }, + { + "id": "0x2dc309c5", + "short_name": "STM32F411xE", + "description": "ST STM32F411xE" + }, + { + "id": "0x06d1097b", + "short_name": "STM32F411xC", + "description": "ST STM32F411xC" + }, + { + "id": "0x72721d4e", + "short_name": "NRF52832xxAA", + "description": "Nordic NRF52832xxAA" + }, + { + "id": "0x6f752678", + "short_name": "NRF52832xxAB", + "description": "Nordic NRF52832xxAB" + } +] From 8ed218e27004a8ceda5eda9315db2d6c090cdb23 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0350/1389] boards: st: nucleo_u575zi_q: add USB OTG_FS Add USB OTG_FS on nucleo_u575zi_q Signed-off-by: Marc Desvaux Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- boards/st/nucleo_u575zi_q/doc/index.rst | 2 ++ boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/boards/st/nucleo_u575zi_q/doc/index.rst b/boards/st/nucleo_u575zi_q/doc/index.rst index 5786fa21b07021..88c4ed94b282dc 100644 --- a/boards/st/nucleo_u575zi_q/doc/index.rst +++ b/boards/st/nucleo_u575zi_q/doc/index.rst @@ -167,6 +167,8 @@ The Zephyr nucleo_u575zi_q board configuration supports the following hardware f +-----------+------------+-------------------------------------+ | WATCHDOG | on-chip | independent watchdog | +-----------+------------+-------------------------------------+ +| USB FS | on-chip | USB Full Speed device | ++-----------+------------+-------------------------------------+ | BKP SRAM | on-chip | Backup SRAM | +-----------+------------+-------------------------------------+ | RNG | on-chip | True Random number generator | diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi index 92e438d03a8ccb..62b466defb4e4a 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi @@ -171,6 +171,12 @@ status = "okay"; }; +zephyr_udc0: &usbotg_fs { + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + &fdcan1 { clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>, <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; From 76fae405bd7fa4e40f22efc1643587ced9b40ef7 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0351/1389] twister: testplan: enable runtime quarantine sometime we need use quarantine at runtime when --test-only add this will help to skip problematic cases in test cycle to reenable the quarantined case you need add --quarantine-list quarantine.yaml --quarantine-verify Signed-off-by: Hake Huang --- scripts/pylib/twister/twisterlib/testplan.py | 23 ++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 85335491af6939..5fd292fd4bc63b 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -571,6 +571,17 @@ def get_platform(self, name): break return selected_platform + def handle_quarantined_tests(self, instance: TestInstance, plat: Platform): + if self.quarantine: + matched_quarantine = self.quarantine.get_matched_quarantine( + instance.testsuite.id, plat.name, plat.arch, plat.simulation + ) + if matched_quarantine and not self.options.quarantine_verify: + instance.add_filter("Quarantine: " + matched_quarantine, Filters.QUARANTINE) + return + if not matched_quarantine and self.options.quarantine_verify: + instance.add_filter("Not under quarantine", Filters.QUARANTINE) + def load_from_file(self, file, filter_platform=[]): with open(file, "r") as json_test_plan: jtp = json.load(json_test_plan) @@ -618,6 +629,8 @@ def load_from_file(self, file, filter_platform=[]): instance.status = status instance.reason = reason + self.handle_quarantined_tests(instance, platform) + for tc in ts.get('testcases', []): identifier = tc['identifier'] tc_status = tc.get('status', None) @@ -903,15 +916,7 @@ def apply_filters(self, **kwargs): break # handle quarantined tests - if self.quarantine: - matched_quarantine = self.quarantine.get_matched_quarantine( - instance.testsuite.id, plat.name, plat.arch, plat.simulation - ) - if matched_quarantine and not self.options.quarantine_verify: - instance.add_filter("Quarantine: " + matched_quarantine, Filters.QUARANTINE) - if not matched_quarantine and self.options.quarantine_verify: - instance.add_filter("Not under quarantine", Filters.QUARANTINE) - + self.handle_quarantined_tests(instance, plat) # platform_key is a list of unique platform attributes that form a unique key a test # will match against to determine if it should be scheduled to run. A key containing a From a82eb34ad231cfb2fc61e07bbb306535e3fb6339 Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0352/1389] dts: bindings: Add SDP-120 connector GPIO ADI Add binding for adi SDP-120 connector and header file with marcos to map signals using signal names. Signed-off-by: Stoyan Bogdanov --- dts/bindings/gpio/adi,sdp-120.yaml | 74 ++++++++++++++++ include/zephyr/dt-bindings/gpio/adi-sdp-120.h | 87 +++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 dts/bindings/gpio/adi,sdp-120.yaml create mode 100644 include/zephyr/dt-bindings/gpio/adi-sdp-120.h diff --git a/dts/bindings/gpio/adi,sdp-120.yaml b/dts/bindings/gpio/adi,sdp-120.yaml new file mode 100644 index 00000000000000..02d1249cdd5aa9 --- /dev/null +++ b/dts/bindings/gpio/adi,sdp-120.yaml @@ -0,0 +1,74 @@ +# Copyright (c) 2024 Analog Devices Inc. +# Copyright (c) 2024 Baylibre, SAS + +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on a Analog devices SDP interface. + + 120-pin SDP interface: + + 1 VIN NC 120 + 2 NC NC 119 + 3 GND GND 118 + 4 GND GND 117 + 5 USB_VBUS VIO 116 + 6 GND GND 115 + 7 PAR_D23 PAR_D22 114 + 8 PAR_D21 PAR_D20 113 + 9 PAR_D19 PAR_D18 112 + 10 PAR_D17 PAR_D16 111 + 11 GND PAR_D15 110 + 12 PAR_D14 GND 109 + 13 PAR_D13 PAR_D12 108 + 14 PAR_D11 PAR_D10 107 + 15 PAR_D9 PAR_D8 106 + 16 PAR_D7 PAR_D6 105 + 17 GND GND 104 + 18 PAR_D5 PAR_D4 103 + 19 PAR_D3 PAR_D2 102 + 20 PAR_D1 PAR_D0 101 + 21 PAR_RD_N PAR_WR_N 100 + 22 PAR_CS_N PAR_INT 99 + 23 GND GND 98 + 24 PAR_A3 PAR_A2 97 + 25 PAR_A1 PAR_A0 96 + 26 PAR_FS3 PAR_FS2 95 + 27 PAR_FS1 PAR_CLK 94 + 28 GND GND 93 + 29 SPORT_TDV0 SPORT_RSCLK 92 + 30 SPORT_TDV1 SPORT_DR0 91 + 31 SPORT_DR1 SPORT_RFS 90 + 32 SPORT_DT1 SPORT_TFS 89 + 33 SPI_D2 SPORT_DT0 88 + 34 SPI_D3 SPORT_TSCLK 87 + 35 SERIAL_INT GND 86 + 36 GND SPI_SEL_A_N 85 + 37 SPI_SEL_B_N SPI_MOSI 84 + 38 SPI_SEL_C_N SPI_MISO 83 + 39 SPI_SEL1/SPI_SS_N SPI_CLK 82 + 40 GND GND 81 + 41 SDA_1 SDA_0 80 + 42 SCL_1 SCL_0 79 + 43 GPIO0 GPIO1 78 + 44 GPIO2 GPIO3 77 + 45 GPIO4 GPIO5 76 + 46 GND GND 75 + 47 GPIO6 GPIO7 74 + 48 TMR_A TMR_B 73 + 49 TMR_C TMR_D 72 + 50 NC CLKOUT 71 + 51 NC NC 70 + 52 GND GND 69 + 53 NC NC 68 + 54 NC NC 67 + 55 NC NC 66 + 56 EEPROM_A0 WAKE_N 65 + 57 RESET_OUT_N SLEEP_N 64 + 58 GND GND 63 + 59 UART_RX UART_TX 62 + 60 RESET_IN_N BMODE1 61 + +compatible: "adi,sdp-120" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/include/zephyr/dt-bindings/gpio/adi-sdp-120.h b/include/zephyr/dt-bindings/gpio/adi-sdp-120.h new file mode 100644 index 00000000000000..6188ce8c004473 --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/adi-sdp-120.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2024 Analog Devices Inc. + * Copyright (c) 2024 Baylibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + * + * @file + * @brief SDP-120 GPIO index definitions + * + * Defines meant to be used in conjunction with the "adi,sdp-120" + * ADI SDP-120 mapping. + * + * Example usage: + * + * @code{.dts} + * &spi1 { + * cs-gpios = <&sdp_120 SDP_120_SPI_SS_N GPIO_ACTIVE_LOW>; + * + * example_device: example-dev@0 { + * compatible = "vnd,spi-device"; + * reg = <0>; + * }; + * }; + * @endcode + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_SDP_120_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_SDP_120_H_ + +/* GPIO */ + +/** + * @brief IO[n] signal on a SDP-120 GPIO nexus node following + */ + +#define SDP_120_IO(n) (n-1) + +/* SPI */ +#define SDP_120_SPI_D2 SDP_120_IO(33) /* SPI_D2 */ +#define SDP_120_SPI_D3 SDP_120_IO(34) /* SPI_D3 */ +#define SDP_120_SERIAL_INT SDP_120_IO(35) /* SERIAL_INT */ +#define SDP_120_SPI_SEL_B_N SDP_120_IO(37) /* SPI_SEL_B_N */ +#define SDP_120_SPI_SEL_C_N SDP_120_IO(38) /* SPI_SEL_C_N */ +#define SDP_120_SPI_SS_N SDP_120_IO(39) /* SPI_SS_N */ + +/* GPIO */ +#define SDP_120_GPIO0 SDP_120_IO(43) /* GPIO0 */ +#define SDP_120_GPIO2 SDP_120_IO(44) /* GPIO2 */ +#define SDP_120_GPIO4 SDP_120_IO(45) /* GPIO4 */ +#define SDP_120_GPIO6 SDP_120_IO(47) /* GPIO6 */ + +/* TMR */ +#define SDP_120_TMR_A SDP_120_IO(48) /* TMR_A */ + +/* USART */ +#define SDP_120_UART_RX SDP_120_IO(59) /* UART2_RX */ +#define SDP_120_UART_TX SDP_120_IO(62) /* UART2_TX */ + +/* TMR */ +#define SDP_120_TMR_D SDP_120_IO(72) /* TMR_D */ +#define SDP_120_TMR_B SDP_120_IO(73) /* TMR_B */ + +/* GPIO */ +#define SDP_120_GPIO7 SDP_120_IO(74) /* GPIO7 */ +#define SDP_120_GPIO5 SDP_120_IO(76) /* GPIO5 */ +#define SDP_120_GPIO3 SDP_120_IO(77) /* GPIO3 */ +#define SDP_120_GPIO1 SDP_120_IO(78) /* GPIO1 */ + +/* I2C */ +#define SDP_120_SCL_0 SDP_120_IO(79) /* SCL_0 */ +#define SDP_120_SDA_0 SDP_120_IO(80) /* SDA_0 */ + +/* SPI */ +#define SDP_120_SPI_CLK SDP_120_IO(82) /* SPI_CLK */ +#define SDP_120_SPI_MISO SDP_120_IO(83) /* SPI_MISO */ +#define SDP_120_SPI_MOSI SDP_120_IO(84) /* SPI_MOSI */ +#define SDP_120_SPI_SEL_A_N SDP_120_IO(85) /* SPI_SEL_A_N */ + +/* SPORT - no driver yet */ +#define SDP_120_SPI_SPORT_TSCLK SDP_120_IO(87) /* SPORT_TSCLK */ +#define SDP_120_SPI_SPORT_DT0 SDP_120_IO(88) /* SPORT_DT0 */ +#define SDP_120_SPI_SPORT_TFS SDP_120_IO(89) /* SPORT_TFS */ +#define SDP_120_SPI_SPORT_RFS SDP_120_IO(90) /* SPORT_RFS */ +#define SDP_120_SPI_SPORT_DR0 SDP_120_IO(91) /* SPORT_DR0 */ +#define SDP_120_SPI_SPORT_RSCLK SDP_120_IO(92) /* SPORT_RSCLK */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_SDP_120_H_ */ From cd8f2120e745049ddbafa7c493a84a62577b90df Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0353/1389] boards: adi_sdp_k1: Add SDP-120 pin connector mapping for SDP-K1 Map all available signals wired to SDP-120 connector. Signed-off-by: Stoyan Bogdanov --- .../adi/sdp_k1/adi_sdp_120pin_connector.dtsi | 118 ++++++++++++++++++ boards/adi/sdp_k1/adi_sdp_k1.dts | 1 + 2 files changed, 119 insertions(+) create mode 100644 boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi diff --git a/boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi b/boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi new file mode 100644 index 00000000000000..a6696d780bfde4 --- /dev/null +++ b/boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024 Analog Devices Inc. + * Copyright (c) 2024 Baylibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + sdp_k1_120_hdr: connector { + compatible = "adi,sdp-120"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = + /* pin map */ /* sdp-120 */ + <32 0 &gpiof 7 0>, /* SPI_D2 */ + <33 0 &gpiod 13 0>, /* SPI_D3 */ + <34 0 &gpioc 11 0>, /* SERIAL_INT */ + <36 0 &gpioc 6 0>, /* SPI_SEL_B_N */ + <37 0 &gpioc 7 0>, /* SPI_SEL_C_N */ + <38 0 &gpiof 6 0>, /* SPI_SEL1/SPI_SS_N */ + + <42 0 &gpioj 0 0>, /* GPIO0 */ + <43 0 &gpioj 3 0>, /* GPIO2 */ + <44 0 &gpioj 5 0>, /* GPIO4 */ + <46 0 &gpioj 13 0>, /* GPIO6 */ + + /* TIMER A */ + <47 0 &gpiob 14 0>, /* TMR_A */ + + <58 0 &gpiod 6 0>, /* UART2_RX */ + <61 0 &gpiod 5 0>, /* UART2_TX */ + + /* TIMER D */ + <71 0 &gpioc 8 0>, /* TMR_D */ + + /* TIMER B */ + <72 0 &gpioe 6 0>, /* TMR_B */ + + <73 0 &gpioj 14 0>, /* GPIO7 */ + <75 0 &gpioj 12 0>, /* GPIO5 */ + <76 0 &gpioj 4 0>, /* GPIO3 */ + <77 0 &gpioj 1 0>, /* GPIO1 */ + + /* I2C3 */ + <78 0 &gpioh 7 0>, /* SCL_0 */ + <79 0 &gpioc 9 0>, /* SDA_0 */ + + /* SPI5 */ + <81 0 &gpioh 6 0>, /* SPI_CLK - spi5_sck_ph6 */ + <82 0 &gpiof 8 0>, /* SPI_MISO - spi5_miso_pf8 */ + <83 0 &gpiof 9 0>, /* SPI_MOSI - spi5_mosi_pf9 */ + <84 0 &gpiob 6 0>, /* SPI_SEL_A_N - could be PB6 or PB9 */ + + /* SPORT - no driver yet */ + <86 0 &gpiog 13 0>, /* SPORT_TSCLK */ + <87 0 &gpiog 14 0>, /* SPORT_DT0 */ + <88 0 &gpioa 8 0>, /* SPORT_TFS */ + <89 0 &gpioe 4 0>, /* SPORT_RFS */ + <90 0 &gpioe 5 0>, /* SPORT_DR0 */ + <91 0 &gpioe 2 0>; /* SPORT_RSCLK */ + }; + + pmod_spi { + compatible = "digilent,pmod"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &sdp_k1_120_hdr SDP_120_SPI_SEL_A_N 0>, // IO1 + <1 0 &sdp_k1_120_hdr SDP_120_SPI_MISO 0>, // IO2 + <2 0 &sdp_k1_120_hdr SDP_120_SPI_MOSI 0>, // IO3 + <3 0 &sdp_k1_120_hdr SDP_120_SPI_CLK 0>, // IO4 + <4 0 &sdp_k1_120_hdr SDP_120_SERIAL_INT 0>, // IO5 + <5 0 &sdp_k1_120_hdr SDP_120_GPIO5 0>, // IO6 + <6 0 &sdp_k1_120_hdr SDP_120_GPIO6 0>, // IO7 + <7 0 &sdp_k1_120_hdr SDP_120_GPIO7 0>; // IO8 + status = "disabled"; + }; + + pmod_usart { + compatible = "digilent,pmod"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &sdp_k1_120_hdr SDP_120_GPIO0 0>, // IO1 + <1 0 &sdp_k1_120_hdr SDP_120_UART_TX 0>, // IO2 + <2 0 &sdp_k1_120_hdr SDP_120_UART_RX 0>, // IO3 + <3 0 &sdp_k1_120_hdr SDP_120_GPIO3 0>, // IO4 + <4 0 &sdp_k1_120_hdr SDP_120_SERIAL_INT 0>, // IO5 + <5 0 &sdp_k1_120_hdr SDP_120_GPIO5 0>, // IO6 + <6 0 &sdp_k1_120_hdr SDP_120_GPIO6 0>, // IO7 + <7 0 &sdp_k1_120_hdr SDP_120_GPIO7 0>; // IO8 + status = "disabled"; + }; + +}; + +/* + * Note from sdp-k1 schematic for overlapping signals + * + * NOTE: SOME OF THE SPI & QUADSPI SIGNALS ON THE SDP + * CONNECTOR ON PAGE 9 ARE ROUTED TO MULTIPLE PINS ON THE + * STM32F469. TAKE CARE NOT TO ENABLE SPI AND QUADSPI ON + * THE SDP CONNECTOR SIMULTANEOUSLY. + */ + +sdp_spi: &spi5 { + pinctrl-0 = <&spi5_sck_ph6 &spi5_miso_pf8 &spi5_mosi_pf9>; + pinctrl-names = "default"; + cs-gpios = <&sdp_k1_120_hdr SDP_120_SPI_SEL_A_N (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + status = "okay"; +}; + +sdp_i2c: &i2c3 { }; + +sdp_serial: &usart2{ }; diff --git a/boards/adi/sdp_k1/adi_sdp_k1.dts b/boards/adi/sdp_k1/adi_sdp_k1.dts index 52c68f90c18976..a1b663867a5b12 100644 --- a/boards/adi/sdp_k1/adi_sdp_k1.dts +++ b/boards/adi/sdp_k1/adi_sdp_k1.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "adi_sdp_120pin_connector.dtsi" / { model = "Analog Devices Inc. SDP-K1 board"; From 2db69f347504bbeebf2ff0bacae82723ec80470e Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0354/1389] ipc: ipc_service: icbmsg backend: workaround endpoint binding deadlock This change works around the issue with the semaphore timeout during the Bluetooth HCI driver initialization when the bt_enable function is called in the context of the System Workqueue thread. This issue only affects platform that use the IPC service and its ICBMsg backend (e.g. the nRF54H20 DK target). The bt_enable function, when called in the System Workqueue context, results in a deadlock, as the waiting semaphore of the Bluetooth HCI driver times out: bt_hci_driver: Endpoint binding failed with -11 During the Bluetooth HCI driver open operation in the context of the bt_enable function, the driver code waits using the semaphore for the endpoint binding process of the IPC service module to finalize. The issue occurs when the waiting occurs in the System Workqueue context. The ICBMsg backend from the IPC service schedules a system work during the endpoint registration, in which it finalizes the binding operation - also in the System Workqueue context. As the Bluetooth HCI driver with its wait operation keeps the System Workqueue context busy, the endpoint binding cannot be completed by the ICBMsg backend before the HCI driver semaphore timeout. Signed-off-by: Kamil Piszczek --- subsys/ipc/ipc_service/backends/ipc_icbmsg.c | 22 +++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c index 02deaa7716124b..37594025313265 100644 --- a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c +++ b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c @@ -110,6 +110,12 @@ LOG_MODULE_REGISTER(ipc_icbmsg, /** Registered endpoints count mask in flags. */ #define FLAG_EPT_COUNT_MASK 0xFFFF +/** Workqueue stack size for bounding processing (this configuration is not optimized). */ +#define EP_BOUND_WORK_Q_STACK_SIZE (512U) + +/** Workqueue priority for bounding processing. */ +#define EP_BOUND_WORK_Q_PRIORITY (CONFIG_SYSTEM_WORKQUEUE_PRIORITY) + enum msg_type { MSG_DATA = 0, /* Data message. */ MSG_RELEASE_DATA, /* Release data buffer message. */ @@ -194,6 +200,9 @@ struct control_message { BUILD_ASSERT(NUM_EPT <= EPT_ADDR_INVALID, "Too many endpoints"); +/* Work queue for bounding processing. */ +static struct k_work_q ep_bound_work_q; + /** * Calculate pointer to block from its index and channel configuration (RX or TX). * No validation is performed. @@ -672,7 +681,7 @@ static int send_bound_message(struct backend_data *dev_data, struct ept_data *ep */ static void schedule_ept_bound_process(struct backend_data *dev_data) { - k_work_submit(&dev_data->ep_bound_work); + k_work_submit_to_queue(&ep_bound_work_q, &dev_data->ep_bound_work); } /** @@ -1117,6 +1126,17 @@ static int backend_init(const struct device *instance) { const struct icbmsg_config *conf = instance->config; struct backend_data *dev_data = instance->data; + static K_THREAD_STACK_DEFINE(ep_bound_work_q_stack, EP_BOUND_WORK_Q_STACK_SIZE); + static bool is_work_q_started; + + if (!is_work_q_started) { + k_work_queue_init(&ep_bound_work_q); + k_work_queue_start(&ep_bound_work_q, ep_bound_work_q_stack, + K_THREAD_STACK_SIZEOF(ep_bound_work_q_stack), + EP_BOUND_WORK_Q_PRIORITY, NULL); + + is_work_q_started = true; + } dev_data->conf = conf; dev_data->is_initiator = (conf->rx.blocks_ptr < conf->tx.blocks_ptr); From 16d16f84113f89b2d3055d492cdfe720f8767d74 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0355/1389] include: linker: common-rom: Remove unused http_resource_desc section HTTP resources are assigned a section for each service, so this iterable section isn't used. Signed-off-by: Pieter De Gendt --- include/zephyr/linker/common-rom/common-rom-net.ld | 1 - 1 file changed, 1 deletion(-) diff --git a/include/zephyr/linker/common-rom/common-rom-net.ld b/include/zephyr/linker/common-rom/common-rom-net.ld index 95aeeb99e89335..5305f9cf873c26 100644 --- a/include/zephyr/linker/common-rom/common-rom-net.ld +++ b/include/zephyr/linker/common-rom/common-rom-net.ld @@ -16,7 +16,6 @@ #if defined(CONFIG_HTTP_SERVER) ITERABLE_SECTION_ROM(http_service_desc, Z_LINK_ITERABLE_SUBALIGN) - ITERABLE_SECTION_ROM(http_resource_desc, Z_LINK_ITERABLE_SUBALIGN) #endif #if defined(CONFIG_COAP_SERVER) From f4bc1591fb910d8e194a49f70b847db8a872b540 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0356/1389] boards: nxp: frdm_mcxn947: Add pyocd runner support The Pyocd support added with the NXP.MCXN947_DFP.17.0.0.pack CMSIS Pack. Signed-off-by: Andrej Butok --- boards/nxp/frdm_mcxn947/board.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/board.cmake b/boards/nxp/frdm_mcxn947/board.cmake index 86cdff853d9b5d..fa5862e5e008fe 100644 --- a/boards/nxp/frdm_mcxn947/board.cmake +++ b/boards/nxp/frdm_mcxn947/board.cmake @@ -23,6 +23,9 @@ else() message(FATAL_ERROR "Support for cpu1 not available yet") endif() +# Pyocd support added with the NXP.MCXN947_DFP.17.0.0.pack CMSIS Pack +board_runner_args(pyocd "--target=mcxn947") include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) From 5f599e5794d659f522fca256f104d1f3819d9c3d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0357/1389] dts: nordic nrf-timer: Expose max frequency as DT property The counter driver needs to know what is the maximum counting frequency of each timer peripheral. Let's add it to its DT. Signed-off-by: Alberto Escolar Piedras --- dts/bindings/timer/nordic,nrf-timer.yaml | 12 +++++++++++- dts/common/nordic/nrf54h20.dtsi | 5 +++++ dts/common/nordic/nrf54l15.dtsi | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dts/bindings/timer/nordic,nrf-timer.yaml b/dts/bindings/timer/nordic,nrf-timer.yaml index 8a961f34f88341..9f8395003a85ce 100644 --- a/dts/bindings/timer/nordic,nrf-timer.yaml +++ b/dts/bindings/timer/nordic,nrf-timer.yaml @@ -24,10 +24,20 @@ properties: interrupts: required: true + max-frequency: + type: int + default: 16000000 + description: | + Maximum timer frequency in Hz. + + The default value is 16MHz which was the maximum frequency for all nRF TIMER peripherals + up to the nRF54 series, and still remains the most typical maximum frequency for nRF54 + TIMERs. + prescaler: type: int required: true - description: Prescaler value determines frequency (base_frequency/2^prescaler) + description: Prescaler value determines frequency (max-frequency/2^prescaler) zli: type: boolean diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 75d112b85e2c80..4a4f78bc166128 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -217,6 +217,7 @@ cc-num = <8>; interrupts = <40 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -227,6 +228,7 @@ cc-num = <8>; interrupts = <41 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -237,6 +239,7 @@ cc-num = <8>; interrupts = <42 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -369,6 +372,7 @@ cc-num = <6>; interrupts = <226 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -379,6 +383,7 @@ cc-num = <6>; interrupts = <227 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index 76dc4903f5552c..a15ead439534bd 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -212,6 +212,7 @@ cc-num = <6>; max-bit-width = <32>; interrupts = <85 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; prescaler = <0>; }; @@ -228,6 +229,7 @@ cc-num = <8>; max-bit-width = <32>; interrupts = <133 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; prescaler = <0>; }; From 8e409d9cdeae1e039b2362b7a4c8eb56e9544caf Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0358/1389] drivers: counter_nrfx_timer.c: Get frequency directly from DT Instead of working it from a macro from the HAL based on the DT address, let's just get the maximum frequency directly from DT. Signed-off-by: Alberto Escolar Piedras --- drivers/counter/counter_nrfx_timer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index 1fe3a98f8d7546..4043d53e718a10 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -15,8 +15,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL); #define DT_DRV_COMPAT nordic_nrf_timer -#define TIMER_CLOCK(timer_instance) NRF_TIMER_BASE_FREQUENCY_GET(timer_instance) - #define CC_TO_ID(cc_num) (cc_num - 2) #define ID_TO_CC(idx) (nrf_timer_cc_channel_t)(idx + 2) @@ -448,7 +446,7 @@ static const struct counter_driver_api counter_nrfx_driver_api = { static MAYBE_CONST_CONFIG struct counter_nrfx_config nrfx_counter_##idx##_config = { \ .info = { \ .max_top_value = (uint32_t)BIT64_MASK(DT_INST_PROP(idx, max_bit_width)),\ - .freq = TIMER_CLOCK((NRF_TIMER_Type *)DT_INST_REG_ADDR(idx)) / \ + .freq = DT_INST_PROP(idx, max_frequency) / \ BIT(DT_INST_PROP(idx, prescaler)), \ .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ .channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \ From cda3839724ac7503cb959330dec0aad05e0a0b2b Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0359/1389] drivers: counter_nrfx_timer.c: Check max-frequency DT property Check that the max-frequency DT property matches the one provided by the nrfx HAL. Signed-off-by: Alberto Escolar Piedras --- drivers/counter/counter_nrfx_timer.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index 4043d53e718a10..bd6af3c5d3c824 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -417,6 +417,14 @@ static const struct counter_driver_api counter_nrfx_driver_api = { irq_handler, DEVICE_DT_INST_GET(idx), 0)) \ ) +#if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX) +#define CHECK_MAX_FREQ(idx) \ + BUILD_ASSERT(DT_INST_PROP(idx, max_frequency) == \ + NRF_TIMER_BASE_FREQUENCY_GET((NRF_TIMER_Type *)DT_INST_REG_ADDR(idx))) +#else +#define CHECK_MAX_FREQ(idx) +#endif + #define COUNTER_NRFX_TIMER_DEVICE(idx) \ BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \ TIMER_PRESCALER_PRESCALER_Msk, \ @@ -455,6 +463,7 @@ static const struct counter_driver_api counter_nrfx_driver_api = { .timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \ LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \ }; \ + CHECK_MAX_FREQ(idx); \ DEVICE_DT_INST_DEFINE(idx, \ counter_##idx##_init, \ NULL, \ From 2b5c4bd0d70065ce0077ce9e3a945161a83eb440 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0360/1389] modules: hal_nordic: nrfx: Add NRFX_RRAMC Add Kconfig option for RRAM controller, NRFX_RRAMC. Signed-off-by: Dominik Ermel --- modules/hal_nordic/nrfx/CMakeLists.txt | 1 + modules/hal_nordic/nrfx/Kconfig | 4 ++++ modules/hal_nordic/nrfx/nrfx_config.h | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index 55911170d968f7..7463cceefa3c4f 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -108,6 +108,7 @@ zephyr_library_sources_ifdef(CONFIG_NRFX_PWM ${SRC_DIR}/nrfx_pwm.c) zephyr_library_sources_ifdef(CONFIG_NRFX_QDEC ${SRC_DIR}/nrfx_qdec.c) zephyr_library_sources_ifdef(CONFIG_NRFX_QSPI ${SRC_DIR}/nrfx_qspi.c) zephyr_library_sources_ifdef(CONFIG_NRFX_RNG ${SRC_DIR}/nrfx_rng.c) +zephyr_library_sources_ifdef(CONFIG_NRFX_RRAMC ${SRC_DIR}/nrfx_rramc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_RTC ${SRC_DIR}/nrfx_rtc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_SAADC ${SRC_DIR}/nrfx_saadc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_SPI ${SRC_DIR}/nrfx_spi.c) diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 32386d54274dc0..07c96c55233ef8 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -265,6 +265,10 @@ config NRFX_RNG bool "RNG driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_RNG)) +config NRFX_RRAMC + bool "RRAMC driver" + depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_RRAM_CONTROLLER)) + config NRFX_RTC bool diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 284147ba0006c4..2b9a02845a7c5c 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -312,6 +312,10 @@ #define NRFX_RNG_CONFIG_LOG_ENABLED 1 #endif +#ifdef CONFIG_NRFX_RRAMC +#define NRFX_RRAMC_ENABLED 1 +#endif + #ifdef CONFIG_NRFX_RTC #define NRFX_RTC_ENABLED 1 #endif From 563f9f0b2829d7985783b6592f5b5e85114af066 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sun, 26 May 2024 22:38:43 +0200 Subject: [PATCH 0361/1389] drivers: flash: rram: Select NRFX_RRAMC Select NRFX_RRAMC for RRAM driver. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf_rram | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index 68efde1ab30269..025b0791010fe9 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -8,6 +8,7 @@ menuconfig SOC_FLASH_NRF_RRAM bool "Nordic Semiconductor flash driver for nRF RRAM" default y depends on DT_HAS_NORDIC_RRAM_CONTROLLER_ENABLED + select NRFX_RRAMC select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_NRF_FORCE_ALT From 7a72946626c6fe458e117e5cd9f7f2a2d5bc49b2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0362/1389] net: lib: http_server: Check HTTP/1.1 Upgrade field Check what kind of upgrading we are doing and return error if we receive upgrade that we do not support. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/server.h | 14 +++- subsys/net/lib/http/http_server_http1.c | 100 +++++++++++++++++++++++- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 35f1dcdc872f15..79a7989519bf87 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -19,6 +19,11 @@ #define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS #define HTTP_SERVER_MAX_CONTENT_TYPE_LEN CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH +/* Maximum header field name / value length. This is only used to detect Upgrade and + * websocket header fields and values in the http1 server so the value is quite short. + */ +#define HTTP_SERVER_MAX_HEADER_LEN 32 + #define HTTP2_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" enum http_resource_type { @@ -142,8 +147,6 @@ struct http_frame { struct http_client_ctx { int fd; - bool preface_sent; - bool has_upgrade_header; unsigned char buffer[HTTP_SERVER_CLIENT_BUFFER_SIZE]; unsigned char *cursor; /**< Cursor indicating currently processed byte. */ size_t data_len; /**< Data left to process in the buffer. */ @@ -157,12 +160,17 @@ struct http_client_ctx { struct http_parser parser; unsigned char url_buffer[CONFIG_HTTP_SERVER_MAX_URL_LENGTH]; unsigned char content_type[CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH]; + unsigned char header_buffer[HTTP_SERVER_MAX_HEADER_LEN]; size_t content_len; enum http_method method; enum http1_parser_state parser_state; int http1_frag_data_len; - bool headers_sent; struct k_work_delayable inactivity_timer; + bool headers_sent : 1; + bool preface_sent : 1; + bool has_upgrade_header : 1; + bool http2_upgrade : 1; + bool websocket_upgrade : 1; }; /* Starts the HTTP2 server */ diff --git a/subsys/net/lib/http/http_server_http1.c b/subsys/net/lib/http/http_server_http1.c index c7dff045d7483c..732b6a1160a8a9 100644 --- a/subsys/net/lib/http/http_server_http1.c +++ b/subsys/net/lib/http/http_server_http1.c @@ -313,12 +313,71 @@ static int on_header_field(struct http_parser *parser, const char *at, struct http_client_ctx *ctx = CONTAINER_OF(parser, struct http_client_ctx, parser); + size_t offset = strlen(ctx->header_buffer); + + if (offset + length > sizeof(ctx->header_buffer) - 1U) { + LOG_DBG("Header %s too long (by %zu bytes)", "field", + offset + length - sizeof(ctx->header_buffer) - 1U); + ctx->header_buffer[0] = '\0'; + } else { + memcpy(ctx->header_buffer + offset, at, length); + offset += length; + ctx->header_buffer[offset] = '\0'; + + if (parser->state == s_header_value_discard_ws) { + /* This means that the header field is fully parsed, + * and we can use it directly. + */ + if (strncasecmp(ctx->header_buffer, "Upgrade", + sizeof("Upgrade") - 1) == 0) { + ctx->has_upgrade_header = true; + } + + ctx->header_buffer[0] = '\0'; + } + } ctx->parser_state = HTTP1_RECEIVING_HEADER_STATE; return 0; } +static int on_header_value(struct http_parser *parser, + const char *at, size_t length) +{ + struct http_client_ctx *ctx = CONTAINER_OF(parser, + struct http_client_ctx, + parser); + size_t offset = strlen(ctx->header_buffer); + + if (offset + length > sizeof(ctx->header_buffer) - 1U) { + LOG_DBG("Header %s too long (by %zu bytes)", "value", + offset + length - sizeof(ctx->header_buffer) - 1U); + ctx->header_buffer[0] = '\0'; + } else { + memcpy(ctx->header_buffer + offset, at, length); + offset += length; + ctx->header_buffer[offset] = '\0'; + + if (parser->state == s_header_almost_done) { + if (ctx->has_upgrade_header) { + if (strncasecmp(ctx->header_buffer, "h2c", + sizeof("h2c") - 1) == 0) { + ctx->http2_upgrade = true; + } else if (strncasecmp(ctx->header_buffer, + "websocket", + sizeof("websocket") - 1) == 0) { + ctx->websocket_upgrade = true; + } + } + + ctx->header_buffer[0] = '\0'; + } + } + + return 0; +} + static int on_headers_complete(struct http_parser *parser) { struct http_client_ctx *ctx = CONTAINER_OF(parser, @@ -383,12 +442,15 @@ int enter_http1_request(struct http_client_ctx *client) http_parser_settings_init(&client->parser_settings); client->parser_settings.on_header_field = on_header_field; + client->parser_settings.on_header_value = on_header_value; client->parser_settings.on_headers_complete = on_headers_complete; client->parser_settings.on_url = on_url; client->parser_settings.on_body = on_body; client->parser_settings.on_message_complete = on_message_complete; client->parser_state = HTTP1_INIT_HEADER_STATE; + memset(client->header_buffer, 0, sizeof(client->header_buffer)); + return 0; } @@ -443,7 +505,43 @@ int handle_http1_request(struct http_client_ctx *client) } if (client->has_upgrade_header) { - return handle_http1_to_http2_upgrade(client); + static const char upgrade_required[] = + "HTTP/1.1 426 Upgrade required\r\n" + "Upgrade: "; + static const char upgrade_msg[] = + "Content-Length: 13\r\n\r\n" + "Wrong upgrade"; + const char *needed_upgrade = "h2c\r\n"; + + if (client->websocket_upgrade) { + goto upgrade_not_found; + } + + if (client->http2_upgrade) { + return handle_http1_to_http2_upgrade(client); + } + +upgrade_not_found: + ret = http_server_sendall(client, upgrade_required, + sizeof(upgrade_required) - 1); + if (ret < 0) { + LOG_DBG("Cannot write to socket (%d)", ret); + return ret; + } + + ret = http_server_sendall(client, needed_upgrade, + strlen(needed_upgrade)); + if (ret < 0) { + LOG_DBG("Cannot write to socket (%d)", ret); + return ret; + } + + ret = http_server_sendall(client, upgrade_msg, + sizeof(upgrade_msg) - 1); + if (ret < 0) { + LOG_DBG("Cannot write to socket (%d)", ret); + return ret; + } } detail = get_resource_detail(client->url_buffer, &path_len); From 5f1a7dc218d61f5d742b2a4547aa348da8abd097 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0363/1389] net: lib: http_server: Upgrade from HTTP/1.1 to websocket Allow connection to be upgraded from HTTP/1.1 to websocket. This commit does nothing yet with the upgraded connection. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/server.h | 3 + subsys/net/lib/http/CMakeLists.txt | 4 + subsys/net/lib/http/headers/server_internal.h | 1 + subsys/net/lib/http/http_server_http1.c | 19 ++++ subsys/net/lib/http/http_server_ws.c | 104 ++++++++++++++++++ subsys/net/lib/websocket/Kconfig | 6 + 6 files changed, 137 insertions(+) create mode 100644 subsys/net/lib/http/http_server_ws.c diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 79a7989519bf87..17b354ca878070 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -130,6 +130,7 @@ enum http1_parser_state { }; #define HTTP_SERVER_INITIAL_WINDOW_SIZE 65536 +#define HTTP_SERVER_WS_MAX_SEC_KEY_LEN 32 struct http_stream_ctx { int stream_id; @@ -166,11 +167,13 @@ struct http_client_ctx { enum http1_parser_state parser_state; int http1_frag_data_len; struct k_work_delayable inactivity_timer; + IF_ENABLED(CONFIG_WEBSOCKET, (uint8_t ws_sec_key[HTTP_SERVER_WS_MAX_SEC_KEY_LEN])); bool headers_sent : 1; bool preface_sent : 1; bool has_upgrade_header : 1; bool http2_upgrade : 1; bool websocket_upgrade : 1; + bool websocket_sec_key_next : 1; }; /* Starts the HTTP2 server */ diff --git a/subsys/net/lib/http/CMakeLists.txt b/subsys/net/lib/http/CMakeLists.txt index 4d4409b2ad731e..b30d12b834eb74 100644 --- a/subsys/net/lib/http/CMakeLists.txt +++ b/subsys/net/lib/http/CMakeLists.txt @@ -16,3 +16,7 @@ zephyr_library_sources_ifdef(CONFIG_HTTP_SERVER http_server_core.c http_server_http2.c http_hpack.c http_huffman.c) +if(CONFIG_HTTP_SERVER AND CONFIG_WEBSOCKET) + zephyr_library_sources(http_server_ws.c) + zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) +endif() diff --git a/subsys/net/lib/http/headers/server_internal.h b/subsys/net/lib/http/headers/server_internal.h index 61e8a36fa538ab..de1c5ca4b9387b 100644 --- a/subsys/net/lib/http/headers/server_internal.h +++ b/subsys/net/lib/http/headers/server_internal.h @@ -28,6 +28,7 @@ int handle_http_frame_headers(struct http_client_ctx *client); int handle_http_frame_data(struct http_client_ctx *client); int handle_http1_request(struct http_client_ctx *client); int handle_http1_to_http2_upgrade(struct http_client_ctx *client); +int handle_http1_to_websocket_upgrade(struct http_client_ctx *client); int enter_http1_request(struct http_client_ctx *client); int enter_http2_request(struct http_client_ctx *client); diff --git a/subsys/net/lib/http/http_server_http1.c b/subsys/net/lib/http/http_server_http1.c index 732b6a1160a8a9..d735736589db8c 100644 --- a/subsys/net/lib/http/http_server_http1.c +++ b/subsys/net/lib/http/http_server_http1.c @@ -331,6 +331,10 @@ static int on_header_field(struct http_parser *parser, const char *at, if (strncasecmp(ctx->header_buffer, "Upgrade", sizeof("Upgrade") - 1) == 0) { ctx->has_upgrade_header = true; + } else if (strncasecmp(ctx->header_buffer, + "Sec-WebSocket-Key", + sizeof("Sec-WebSocket-Key") - 1) == 0) { + ctx->websocket_sec_key_next = true; } ctx->header_buffer[0] = '\0'; @@ -369,6 +373,17 @@ static int on_header_value(struct http_parser *parser, sizeof("websocket") - 1) == 0) { ctx->websocket_upgrade = true; } + + ctx->has_upgrade_header = false; + } + + if (ctx->websocket_sec_key_next) { +#if defined(CONFIG_WEBSOCKET) + strncpy(ctx->ws_sec_key, ctx->header_buffer, + MIN(sizeof(ctx->ws_sec_key), + strlen(ctx->header_buffer))); +#endif + ctx->websocket_sec_key_next = false; } ctx->header_buffer[0] = '\0'; @@ -514,6 +529,10 @@ int handle_http1_request(struct http_client_ctx *client) const char *needed_upgrade = "h2c\r\n"; if (client->websocket_upgrade) { + if (IS_ENABLED(CONFIG_WEBSOCKET)) { + return handle_http1_to_websocket_upgrade(client); + } + goto upgrade_not_found; } diff --git a/subsys/net/lib/http/http_server_ws.c b/subsys/net/lib/http/http_server_ws.c new file mode 100644 index 00000000000000..f618b70e3b0731 --- /dev/null +++ b/subsys/net/lib/http/http_server_ws.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(net_http_server, CONFIG_NET_HTTP_SERVER_LOG_LEVEL); + +#include "headers/server_internal.h" + +#if !defined(ZEPHYR_USER_AGENT) +#define ZEPHYR_USER_AGENT "Zephyr" +#endif + +/* From RFC 6455 chapter 4.2.2 */ +#define WS_MAGIC "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + +/* Handle upgrade from HTTP/1.1 to Websocket, see RFC 6455 + */ +int handle_http1_to_websocket_upgrade(struct http_client_ctx *client) +{ + static const char switching_protocols[] = + "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: "; + char key_accept[32 + sizeof(WS_MAGIC)]; + char accept[20]; + char tmp[64]; + size_t key_len; + size_t olen; + int ret; + + key_len = MIN(sizeof(key_accept) - 1, sizeof(client->ws_sec_key)); + strncpy(key_accept, client->ws_sec_key, key_len); + key_len = strlen(key_accept); + + olen = MIN(sizeof(key_accept) - 1 - key_len, sizeof(WS_MAGIC) - 1); + strncpy(key_accept + key_len, WS_MAGIC, olen); + + mbedtls_sha1(key_accept, olen + key_len, accept); + + ret = base64_encode(tmp, sizeof(tmp) - 1, &olen, accept, sizeof(accept)); + if (ret) { + if (ret == -ENOMEM) { + NET_DBG("[%p] Too short buffer olen %zd", client, olen); + } + + goto error; + } + + ret = http_server_sendall(client, switching_protocols, + sizeof(switching_protocols) - 1); + if (ret < 0) { + NET_DBG("Cannot write to socket (%d)", ret); + goto error; + } + + ret = http_server_sendall(client, tmp, strlen(tmp)); + if (ret < 0) { + NET_DBG("Cannot write to socket (%d)", ret); + goto error; + } + + ret = snprintk(tmp, sizeof(tmp), "\r\nUser-Agent: %s\r\n\r\n", + ZEPHYR_USER_AGENT); + if (ret < 0 || ret >= sizeof(tmp)) { + goto error; + } + + ret = http_server_sendall(client, tmp, strlen(tmp)); + if (ret < 0) { + NET_DBG("Cannot write to socket (%d)", ret); + goto error; + } + + /* Only after the complete HTTP1 payload has been processed, switch + * to Websocket. + */ + if (client->parser_state == HTTP1_MESSAGE_COMPLETE_STATE) { + client->current_detail = NULL; + client->server_state = HTTP_SERVER_PREFACE_STATE; + client->cursor += client->data_len; + client->data_len = 0; + } + + return 0; + +error: + return ret; +} diff --git a/subsys/net/lib/websocket/Kconfig b/subsys/net/lib/websocket/Kconfig index adfcdc169d939e..4a379cca1dd411 100644 --- a/subsys/net/lib/websocket/Kconfig +++ b/subsys/net/lib/websocket/Kconfig @@ -14,6 +14,12 @@ menuconfig WEBSOCKET_CLIENT help Enable Websocket client library. +config WEBSOCKET + bool + default y if WEBSOCKET_CLIENT + help + Helper symbol for generic Websocket support. + if WEBSOCKET_CLIENT config WEBSOCKET_MAX_CONTEXTS From 695b607be3c30c18710218c4c4ddf28f5d3a7944 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0364/1389] net: websocket: Do not use menuconfig Use normal "config" in order to avoid this error from compliance check script: Found pointless 'menuconfig' symbols without children. Use regular 'config' symbols instead. Signed-off-by: Jukka Rissanen --- subsys/net/lib/websocket/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/lib/websocket/Kconfig b/subsys/net/lib/websocket/Kconfig index 4a379cca1dd411..20f6ca6b1fe358 100644 --- a/subsys/net/lib/websocket/Kconfig +++ b/subsys/net/lib/websocket/Kconfig @@ -1,7 +1,7 @@ # Copyright (c) 2019 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -menuconfig WEBSOCKET_CLIENT +config WEBSOCKET_CLIENT bool "Websocket client support [EXPERIMENTAL]" select NET_SOCKETS select HTTP_PARSER From 7705a2eb0f53c3b6b055d139b3b4a54d946ab725 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0365/1389] net: websocket: Fix doc for websocket_recv_msg() function The function websocket_recv_msg() documentation was missing description for the return value. Signed-off-by: Jukka Rissanen --- include/zephyr/net/websocket.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zephyr/net/websocket.h b/include/zephyr/net/websocket.h index 1a0853891a0209..33c300acaf04ef 100644 --- a/include/zephyr/net/websocket.h +++ b/include/zephyr/net/websocket.h @@ -182,6 +182,8 @@ int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len, * the connection. * * @param ws_sock Websocket id returned by websocket_connect(). + * + * @return <0 if error, 0 the connection was closed successfully */ int websocket_disconnect(int ws_sock); From 9ea3ce8ecab05d4134c3e6b209ccd68404624824 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0366/1389] net: websocket: Create websocket_register() for http_server use The http_server needs a way to bind a websocket socket to the upgraded http connection socket. So websocket_register() is used for that. Signed-off-by: Jukka Rissanen --- include/zephyr/net/websocket.h | 14 ++++++++ subsys/net/lib/websocket/websocket.c | 51 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/include/zephyr/net/websocket.h b/include/zephyr/net/websocket.h index 33c300acaf04ef..dc0eaf36d185e1 100644 --- a/include/zephyr/net/websocket.h +++ b/include/zephyr/net/websocket.h @@ -187,6 +187,20 @@ int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len, */ int websocket_disconnect(int ws_sock); +/** + * @brief Register a socket as websocket. This is called by HTTP server + * when a connection is upgraded to a websocket connection. + * + * @param http_sock Underlying socket connection socket. + * @param recv_buf Temporary receive buffer for websocket parsing. This must + * point to a memory area that is valid for the duration of the whole + * websocket session. + * @param recv_buf_len Length of the temporary receive buffer. + * + * @return <0 if error, >=0 the actual websocket to be used by application + */ +int websocket_register(int http_sock, uint8_t *recv_buf, size_t recv_buf_len); + #if defined(CONFIG_WEBSOCKET_CLIENT) void websocket_init(void); #else diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index 8f463285c2504e..e29f2589bb7449 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -1127,6 +1127,57 @@ static ssize_t websocket_recvfrom_ctx(void *obj, void *buf, size_t max_len, return (ssize_t)websocket_recv(ctx, buf, max_len, timeout); } +int websocket_register(int sock, uint8_t *recv_buf, size_t recv_buf_len) +{ + struct websocket_context *ctx; + int ret, fd; + + if (sock < 0) { + return -EINVAL; + } + + ctx = websocket_find(sock); + if (ctx) { + NET_DBG("[%p] Websocket for sock %d already exists!", ctx, sock); + return -EEXIST; + } + + ctx = websocket_get(); + if (!ctx) { + return -ENOENT; + } + + ctx->real_sock = sock; + ctx->recv_buf.buf = recv_buf; + ctx->recv_buf.size = recv_buf_len; + + fd = z_reserve_fd(); + if (fd < 0) { + ret = -ENOSPC; + goto out; + } + + ctx->sock = fd; + z_finalize_fd(fd, ctx, + (const struct fd_op_vtable *)&websocket_fd_op_vtable); + + NET_DBG("[%p] WS connection to peer established (fd %d)", ctx, fd); + + ctx->recv_buf.count = 0; + ctx->parser_state = WEBSOCKET_PARSER_STATE_OPCODE; + + return fd; + +out: + if (fd >= 0) { + (void)zsock_close(fd); + } + + websocket_context_unref(ctx); + + return ret; +} + static const struct socket_op_vtable websocket_fd_op_vtable = { .fd_vtable = { .read = websocket_read_vmeth, From 67794bba53e5fa32a98637aeb03a1a5ea28482e1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0367/1389] net: websocket: Do not print error in closing If the other end closes the connection, it is not exactly an error so downgrade the print to debug level. Signed-off-by: Jukka Rissanen --- subsys/net/lib/websocket/websocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index e29f2589bb7449..83bd976d1cb28d 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -422,7 +422,7 @@ static int websocket_interal_disconnect(struct websocket_context *ctx) ret = websocket_send_msg(ctx->sock, NULL, 0, WEBSOCKET_OPCODE_CLOSE, true, true, SYS_FOREVER_MS); if (ret < 0) { - NET_ERR("[%p] Failed to send close message (err %d).", ctx, ret); + NET_DBG("[%p] Failed to send close message (err %d).", ctx, ret); } websocket_context_unref(ctx); From 91d9502f9effa022e562fb145e55a15631b444b4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0368/1389] net: http_server: Add websocket support After upgrading the HTTP connection to websocket, call the application registered callback to transfer the ownership of the socket to the application. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/server.h | 31 ++++++++++++++++ subsys/net/lib/http/Kconfig | 10 +++++ subsys/net/lib/http/headers/server_internal.h | 3 +- subsys/net/lib/http/http_server_core.c | 37 +++++++++++++++++-- subsys/net/lib/http/http_server_http1.c | 19 +++++++--- subsys/net/lib/http/http_server_http2.c | 4 +- subsys/net/lib/http/http_server_ws.c | 28 +++++++++++--- 7 files changed, 115 insertions(+), 17 deletions(-) diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 17b354ca878070..60cab000fe0e15 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -29,6 +29,7 @@ enum http_resource_type { HTTP_RESOURCE_TYPE_STATIC, HTTP_RESOURCE_TYPE_DYNAMIC, + HTTP_RESOURCE_TYPE_WEBSOCKET, }; struct http_resource_detail { @@ -46,6 +47,8 @@ struct http_resource_detail_static { const void *static_data; size_t static_data_len; }; +/* Make sure that the common is the first in the struct. */ +BUILD_ASSERT(offsetof(struct http_resource_detail_static, common) == 0); struct http_client_ctx; @@ -89,11 +92,39 @@ struct http_resource_detail_dynamic { struct http_client_ctx *holder; void *user_data; }; +BUILD_ASSERT(offsetof(struct http_resource_detail_dynamic, common) == 0); struct http_resource_detail_rest { struct http_resource_detail common; }; +/** + * @typedef http_resource_websocket_cb_t + * @brief Callback used when a Websocket connection is setup. The application + * will need to handle all functionality related to the connection like + * reading and writing websocket data, and closing the connection. + * + * @param ws_socket A socket for the Websocket data. + * @param user_data User specified data. + * + * @return 0 Accepting the connection, HTTP server library will no longer + * handle data to/from the socket and it is application responsibility + * to send and receive data to/from the supplied socket. + * <0 error, close the connection. + */ +typedef int (*http_resource_websocket_cb_t)(int ws_socket, + void *user_data); + +struct http_resource_detail_websocket { + struct http_resource_detail common; + int ws_sock; + http_resource_websocket_cb_t cb; + uint8_t *data_buffer; + size_t data_buffer_len; + void *user_data; +}; +BUILD_ASSERT(offsetof(struct http_resource_detail_websocket, common) == 0); + enum http_stream_state { HTTP_SERVER_STREAM_IDLE, HTTP_SERVER_STREAM_RESERVED_LOCAL, diff --git a/subsys/net/lib/http/Kconfig b/subsys/net/lib/http/Kconfig index b78d8e93e3555d..3df70b84a84a13 100644 --- a/subsys/net/lib/http/Kconfig +++ b/subsys/net/lib/http/Kconfig @@ -106,6 +106,16 @@ config HTTP_SERVER_CLIENT_INACTIVITY_TIMEOUT (i. e. not sending or receiving any data) before the server drops the connection. +config HTTP_SERVER_WEBSOCKET + bool "Allow upgrading to Websocket connection" + select WEBSOCKET_CLIENT + select WEBSOCKET + help + If this is enabled, then the user can allow the HTTP connection to be + upgraded to a Websocket connection. The user can then define a Websocket + handler that is called after upgrading to handle the Websocket network + traffic. + endif # Hidden option to avoid having multiple individual options that are ORed together diff --git a/subsys/net/lib/http/headers/server_internal.h b/subsys/net/lib/http/headers/server_internal.h index de1c5ca4b9387b..557cc26d883331 100644 --- a/subsys/net/lib/http/headers/server_internal.h +++ b/subsys/net/lib/http/headers/server_internal.h @@ -29,13 +29,14 @@ int handle_http_frame_data(struct http_client_ctx *client); int handle_http1_request(struct http_client_ctx *client); int handle_http1_to_http2_upgrade(struct http_client_ctx *client); int handle_http1_to_websocket_upgrade(struct http_client_ctx *client); +void http_server_release_client(struct http_client_ctx *client); int enter_http1_request(struct http_client_ctx *client); int enter_http2_request(struct http_client_ctx *client); int enter_http_done_state(struct http_client_ctx *client); /* Others */ -struct http_resource_detail *get_resource_detail(const char *path, int *len); +struct http_resource_detail *get_resource_detail(const char *path, int *len, bool is_ws); int http_server_sendall(struct http_client_ctx *client, const void *buf, size_t len); void http_client_timer_restart(struct http_client_ctx *client); diff --git a/subsys/net/lib/http/http_server_core.c b/subsys/net/lib/http/http_server_core.c index a7f11b45b8ea0d..e0402259faf428 100644 --- a/subsys/net/lib/http/http_server_core.c +++ b/subsys/net/lib/http/http_server_core.c @@ -292,7 +292,7 @@ static void client_release_resources(struct http_client_ctx *client) } } -static void close_client_connection(struct http_client_ctx *client) +void http_server_release_client(struct http_client_ctx *client) { int i; struct k_work_sync sync; @@ -300,7 +300,6 @@ static void close_client_connection(struct http_client_ctx *client) __ASSERT_NO_MSG(IS_ARRAY_ELEMENT(server_ctx.clients, client)); k_work_cancel_delayable_sync(&client->inactivity_timer, &sync); - zsock_close(client->fd); client_release_resources(client); server_ctx.num_clients--; @@ -314,7 +313,15 @@ static void close_client_connection(struct http_client_ctx *client) memset(client, 0, sizeof(struct http_client_ctx)); client->fd = INVALID_SOCK; +} + +static void close_client_connection(struct http_client_ctx *client) +{ + int fd = client->fd; + http_server_release_client(client); + + (void)zsock_close(fd); } static void client_timeout(struct k_work *work) @@ -625,11 +632,35 @@ static int compare_strings(const char *s1, const char *s2) return 1; /* Strings are not equal */ } +static bool skip_this(struct http_resource_desc *resource, bool is_websocket) +{ + struct http_resource_detail *detail; + + detail = (struct http_resource_detail *)resource->detail; + + if (is_websocket) { + if (detail->type != HTTP_RESOURCE_TYPE_WEBSOCKET) { + return true; + } + } else { + if (detail->type == HTTP_RESOURCE_TYPE_WEBSOCKET) { + return true; + } + } + + return false; +} + struct http_resource_detail *get_resource_detail(const char *path, - int *path_len) + int *path_len, + bool is_websocket) { HTTP_SERVICE_FOREACH(service) { HTTP_SERVICE_FOREACH_RESOURCE(service, resource) { + if (skip_this(resource, is_websocket)) { + continue; + } + if (compare_strings(path, resource->resource) == 0) { NET_DBG("Got match for %s", resource->resource); diff --git a/subsys/net/lib/http/http_server_http1.c b/subsys/net/lib/http/http_server_http1.c index d735736589db8c..799485f537c25c 100644 --- a/subsys/net/lib/http/http_server_http1.c +++ b/subsys/net/lib/http/http_server_http1.c @@ -313,7 +313,7 @@ static int on_header_field(struct http_parser *parser, const char *at, struct http_client_ctx *ctx = CONTAINER_OF(parser, struct http_client_ctx, parser); - size_t offset = strlen(ctx->header_buffer); + size_t offset = strnlen(ctx->header_buffer, sizeof(ctx->header_buffer)); if (offset + length > sizeof(ctx->header_buffer) - 1U) { LOG_DBG("Header %s too long (by %zu bytes)", "field", @@ -352,7 +352,7 @@ static int on_header_value(struct http_parser *parser, struct http_client_ctx *ctx = CONTAINER_OF(parser, struct http_client_ctx, parser); - size_t offset = strlen(ctx->header_buffer); + size_t offset = strnlen(ctx->header_buffer, sizeof(ctx->header_buffer)); if (offset + length > sizeof(ctx->header_buffer) - 1U) { LOG_DBG("Header %s too long (by %zu bytes)", "value", @@ -380,8 +380,7 @@ static int on_header_value(struct http_parser *parser, if (ctx->websocket_sec_key_next) { #if defined(CONFIG_WEBSOCKET) strncpy(ctx->ws_sec_key, ctx->header_buffer, - MIN(sizeof(ctx->ws_sec_key), - strlen(ctx->header_buffer))); + MIN(sizeof(ctx->ws_sec_key), offset)); #endif ctx->websocket_sec_key_next = false; } @@ -529,7 +528,14 @@ int handle_http1_request(struct http_client_ctx *client) const char *needed_upgrade = "h2c\r\n"; if (client->websocket_upgrade) { - if (IS_ENABLED(CONFIG_WEBSOCKET)) { + if (IS_ENABLED(CONFIG_HTTP_SERVER_WEBSOCKET)) { + detail = get_resource_detail(client->url_buffer, + &path_len, true); + if (detail == NULL) { + goto not_found; + } + + client->current_detail = detail; return handle_http1_to_websocket_upgrade(client); } @@ -563,7 +569,7 @@ int handle_http1_request(struct http_client_ctx *client) } } - detail = get_resource_detail(client->url_buffer, &path_len); + detail = get_resource_detail(client->url_buffer, &path_len, false); if (detail != NULL) { detail->path_len = path_len; @@ -583,6 +589,7 @@ int handle_http1_request(struct http_client_ctx *client) } } } else { +not_found: ; /* Add extra semicolon to make clang to compile when using label */ static const char not_found_response[] = "HTTP/1.1 404 Not Found\r\n" "Content-Length: 9\r\n\r\n" diff --git a/subsys/net/lib/http/http_server_http2.c b/subsys/net/lib/http/http_server_http2.c index b26139a79bb266..3948401057f78b 100644 --- a/subsys/net/lib/http/http_server_http2.c +++ b/subsys/net/lib/http/http_server_http2.c @@ -802,7 +802,7 @@ int handle_http1_to_http2_upgrade(struct http_client_ctx *client) client->preface_sent = true; } - detail = get_resource_detail(client->url_buffer, &path_len); + detail = get_resource_detail(client->url_buffer, &path_len, false); if (detail != NULL) { detail->path_len = path_len; @@ -1017,7 +1017,7 @@ int handle_http_frame_headers(struct http_client_ctx *client) return 0; } - detail = get_resource_detail(client->url_buffer, &path_len); + detail = get_resource_detail(client->url_buffer, &path_len, false); if (detail != NULL) { detail->path_len = path_len; diff --git a/subsys/net/lib/http/http_server_ws.c b/subsys/net/lib/http/http_server_ws.c index f618b70e3b0731..593a73526d7af0 100644 --- a/subsys/net/lib/http/http_server_ws.c +++ b/subsys/net/lib/http/http_server_ws.c @@ -16,6 +16,7 @@ #include #include #include +#include LOG_MODULE_DECLARE(net_http_server, CONFIG_NET_HTTP_SERVER_LOG_LEVEL); @@ -37,7 +38,7 @@ int handle_http1_to_websocket_upgrade(struct http_client_ctx *client) "Connection: Upgrade\r\n" "Upgrade: websocket\r\n" "Sec-WebSocket-Accept: "; - char key_accept[32 + sizeof(WS_MAGIC)]; + char key_accept[HTTP_SERVER_WS_MAX_SEC_KEY_LEN + sizeof(WS_MAGIC)]; char accept[20]; char tmp[64]; size_t key_len; @@ -91,10 +92,27 @@ int handle_http1_to_websocket_upgrade(struct http_client_ctx *client) * to Websocket. */ if (client->parser_state == HTTP1_MESSAGE_COMPLETE_STATE) { - client->current_detail = NULL; - client->server_state = HTTP_SERVER_PREFACE_STATE; - client->cursor += client->data_len; - client->data_len = 0; + struct http_resource_detail_websocket *ws_detail; + int ws_sock; + + ws_detail = (struct http_resource_detail_websocket *)client->current_detail; + + ret = ws_sock = websocket_register(client->fd, + ws_detail->data_buffer, + ws_detail->data_buffer_len); + if (ret < 0) { + NET_DBG("Cannot register websocket (%d)", ret); + goto error; + } + + http_server_release_client(client); + + ret = ws_detail->cb(ws_sock, ws_detail->user_data); + if (ret < 0) { + NET_DBG("WS connection failed (%d)", ret); + zsock_close(ws_sock); + goto error; + } } return 0; From bf025d8a3e681295a07d3bca9965981dcbe8cee7 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0369/1389] samples: net: http_server: Add websocket support Add code for creating a websocket support to the http_server. Signed-off-by: Jukka Rissanen --- .../net/sockets/http_server/CMakeLists.txt | 2 + samples/net/sockets/http_server/Kconfig | 12 + samples/net/sockets/http_server/README.rst | 28 +++ samples/net/sockets/http_server/prj.conf | 1 + samples/net/sockets/http_server/src/main.c | 22 ++ samples/net/sockets/http_server/src/ws.c | 215 ++++++++++++++++++ 6 files changed, 280 insertions(+) create mode 100644 samples/net/sockets/http_server/src/ws.c diff --git a/samples/net/sockets/http_server/CMakeLists.txt b/samples/net/sockets/http_server/CMakeLists.txt index 5b27e5ee7ca96f..2a8d03ac9b28ed 100644 --- a/samples/net/sockets/http_server/CMakeLists.txt +++ b/samples/net/sockets/http_server/CMakeLists.txt @@ -32,6 +32,8 @@ generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.i set(source_file_not_found src/not_found_page.html) generate_inc_file_for_target(app ${source_file_not_found} ${gen_dir}/not_found_page.html.gz.inc --gzip) +target_sources_ifdef(CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE app PRIVATE src/ws.c) + target_link_libraries(app PRIVATE zephyr_interface zephyr) zephyr_linker_sources(SECTIONS sections-rom.ld) diff --git a/samples/net/sockets/http_server/Kconfig b/samples/net/sockets/http_server/Kconfig index 90104be01fa19a..ca55f9692e34b8 100644 --- a/samples/net/sockets/http_server/Kconfig +++ b/samples/net/sockets/http_server/Kconfig @@ -38,4 +38,16 @@ config NET_SAMPLE_CERTS_WITH_SC Enable this flag, if you are interested to run this application with signed certificates and keys. +config NET_SAMPLE_WEBSOCKET_SERVICE + bool "Enable websocket service" + default y if HTTP_SERVER_WEBSOCKET + +config NET_SAMPLE_NUM_WEBSOCKET_HANDLERS + int "How many websocket connections to serve at the same time" + depends on NET_SAMPLE_WEBSOCKET_SERVICE + default 1 + help + Each websocket connection is served by a thread which needs + memory. Only increase the value here if really needed. + source "Kconfig.zephyr" diff --git a/samples/net/sockets/http_server/README.rst b/samples/net/sockets/http_server/README.rst index cc4cd1c5482196..739635cf8a1910 100644 --- a/samples/net/sockets/http_server/README.rst +++ b/samples/net/sockets/http_server/README.rst @@ -59,10 +59,38 @@ the requirements. These are the configurable parameters: - ``CONFIG_HTTP_SERVER_MAX_URL_LENGTH``: Specifies the maximum length of an HTTP URL that the server can process. +- ``CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE``: Enables Websocket service endpoint. + This allows a Websocket client to connect to ``/`` endpoint, all the data that + the client sends is echoed back. + To customize these options, we can run ``west build -t menuconfig``, which provides us with an interactive configuration interface. Then we could navigate from the top-level menu to: ``-> Subsystems and OS Services -> Networking -> Network Protocols``. +Websocket Connectivity +---------------------- + +You can use a simple Websocket client application like this to test the Websocket +connectivity. + +.. code-block:: python + + import websocket + + websocket.enableTrace(True) + ws = websocket.WebSocket() + ws.connect("ws://192.0.2.1/") + ws.send("Hello, Server") + print(ws.recv()) + while True: + line = input("> ") + if line == "quit": + break + ws.send(line) + print(ws.recv()) + ws.close() + + Performance Analysis -------------------- diff --git a/samples/net/sockets/http_server/prj.conf b/samples/net/sockets/http_server/prj.conf index 9e56f3332e7f2b..3d13a55cbf29b4 100644 --- a/samples/net/sockets/http_server/prj.conf +++ b/samples/net/sockets/http_server/prj.conf @@ -30,6 +30,7 @@ CONFIG_JSON_LIBRARY=y CONFIG_HTTP_PARSER_URL=y CONFIG_HTTP_PARSER=y CONFIG_HTTP_SERVER=y +CONFIG_HTTP_SERVER_WEBSOCKET=y # Network buffers CONFIG_NET_PKT_RX_COUNT=16 diff --git a/samples/net/sockets/http_server/src/main.c b/samples/net/sockets/http_server/src/main.c index dac4499029d4db..be564ac4a541e5 100644 --- a/samples/net/sockets/http_server/src/main.c +++ b/samples/net/sockets/http_server/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Emna Rekik + * Copyright (c) 2024, Nordic Semiconductor * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,6 +89,27 @@ struct http_resource_detail_dynamic dyn_resource_detail = { HTTP_RESOURCE_DEFINE(dyn_resource, test_http_service, "/dynamic", &dyn_resource_detail); +#if defined(CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE) +extern int ws_setup(int ws_socket, void *user_data); + +static uint8_t ws_recv_buffer[1024]; + +struct http_resource_detail_websocket ws_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_WEBSOCKET, + + /* We need HTTP/1.1 Get method for upgrading */ + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + }, + .cb = ws_setup, + .data_buffer = ws_recv_buffer, + .data_buffer_len = sizeof(ws_recv_buffer), + .user_data = NULL, /* Fill this for any user specific data */ +}; + +HTTP_RESOURCE_DEFINE(ws_resource, test_http_service, "/", &ws_resource_detail); + +#endif /* CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE */ #endif /* CONFIG_NET_SAMPLE_HTTP_SERVICE */ #if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) diff --git a/samples/net/sockets/http_server/src/ws.c b/samples/net/sockets/http_server/src/ws.c new file mode 100644 index 00000000000000..08cdfd1ee29f7c --- /dev/null +++ b/samples/net/sockets/http_server/src/ws.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2024, Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(net_http_server_sample, LOG_LEVEL_DBG); + +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) || defined(CONFIG_COVERAGE_GCOV) +#define STACK_SIZE 4096 +#else +#define STACK_SIZE 2048 +#endif + +#if defined(CONFIG_NET_TC_THREAD_COOPERATIVE) +#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1) +#else +#define THREAD_PRIORITY K_PRIO_PREEMPT(8) +#endif + +#if defined(CONFIG_USERSPACE) +#include +extern struct k_mem_partition app_partition; +extern struct k_mem_domain app_domain; +#define APP_BMEM K_APP_BMEM(app_partition) +#define APP_DMEM K_APP_DMEM(app_partition) +#else +#define APP_BMEM +#define APP_DMEM +#endif + +#define MAX_CLIENT_QUEUE CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS +#define RECV_BUFFER_SIZE 1280 + +K_THREAD_STACK_ARRAY_DEFINE(ws_handler_stack, + CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS, + STACK_SIZE); +static struct k_thread ws_handler_thread[CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS]; +static APP_BMEM bool ws_handler_in_use[CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS]; + +static struct data { + int sock; + uint32_t counter; + uint32_t bytes_received; + struct pollfd fds[1]; + char recv_buffer[RECV_BUFFER_SIZE]; +} config[CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS] = { + [0 ... (CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS - 1)] = { + .sock = -1, + .fds[0].fd = -1, + } +}; + +static int get_free_slot(struct data *cfg) +{ + for (int i = 0; i < CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS; i++) { + if (cfg[i].sock < 0) { + return i; + } + } + + return -1; +} + +static ssize_t sendall(int sock, const void *buf, size_t len) +{ + while (len) { + ssize_t out_len = send(sock, buf, len, 0); + + if (out_len < 0) { + return out_len; + } + buf = (const char *)buf + out_len; + len -= out_len; + } + + return 0; +} + +static void ws_handler(void *ptr1, void *ptr2, void *ptr3) +{ + int slot = POINTER_TO_INT(ptr1); + struct data *cfg = ptr2; + bool *in_use = ptr3; + int offset = 0; + int received; + int client; + int ret; + + client = cfg->sock; + + cfg->fds[0].fd = client; + cfg->fds[0].events = POLLIN; + + /* In this example, we start to receive data from the websocket + * and send it back to the client. Note that we could either use + * the BSD socket interface if we do not care about Websocket + * specific packets, or we could use the websocket_{send/recv}_msg() + * function to send websocket specific data. + */ + while (true) { + if (poll(cfg->fds, 1, -1) < 0) { + LOG_ERR("Error in poll:%d", errno); + continue; + } + + if (cfg->fds[0].fd < 0) { + continue; + } + + if (cfg->fds[0].revents & ZSOCK_POLLHUP) { + LOG_DBG("Client #%d has disconnected", client); + break; + } + + received = recv(client, + cfg->recv_buffer + offset, + sizeof(cfg->recv_buffer) - offset, + 0); + + if (received == 0) { + /* Connection closed */ + LOG_INF("[%d] Connection closed", slot); + break; + } else if (received < 0) { + /* Socket error */ + LOG_ERR("[%d] Connection error %d", slot, errno); + break; + } + + cfg->bytes_received += received; + offset += received; + +#if !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + /* To prevent fragmentation of the response, reply only if + * buffer is full or there is no more data to read + */ + if (offset == sizeof(cfg->recv_buffer) || + (recv(client, cfg->recv_buffer + offset, + sizeof(cfg->recv_buffer) - offset, + MSG_PEEK | MSG_DONTWAIT) < 0 && + (errno == EAGAIN || errno == EWOULDBLOCK))) { +#endif + ret = sendall(client, cfg->recv_buffer, offset); + if (ret < 0) { + LOG_ERR("[%d] Failed to send data, closing socket", + slot); + break; + } + + LOG_DBG("[%d] Received and replied with %d bytes", + slot, offset); + + if (++cfg->counter % 1000 == 0U) { + LOG_INF("[%d] Sent %u packets", slot, cfg->counter); + } + + offset = 0; +#if !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + } +#endif + } + + *in_use = false; + + (void)close(client); + + cfg->sock = -1; +} + +int ws_setup(int ws_socket, void *user_data) +{ + int slot; + + slot = get_free_slot(config); + if (slot < 0) { + LOG_ERR("Cannot accept more connections"); + /* The caller will close the connection in this case */ + return -ENOENT; + } + + config[slot].sock = ws_socket; + + LOG_INF("[%d] Accepted a Websocket connection", slot); + + k_thread_create(&ws_handler_thread[slot], + ws_handler_stack[slot], + K_THREAD_STACK_SIZEOF(ws_handler_stack[slot]), + ws_handler, + INT_TO_POINTER(slot), &config[slot], &ws_handler_in_use[slot], + THREAD_PRIORITY, + IS_ENABLED(CONFIG_USERSPACE) ? K_USER | + K_INHERIT_PERMS : 0, + K_NO_WAIT); + + if (IS_ENABLED(CONFIG_THREAD_NAME)) { +#define MAX_NAME_LEN sizeof("ws[xx]") + char name[MAX_NAME_LEN]; + + snprintk(name, sizeof(name), "ws[%d]", slot); + k_thread_name_set(&ws_handler_thread[slot], name); + } + + return 0; +} From 85affcd3d6b8932954bcaa9abda2b7f6c2bbe681 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0370/1389] net: websocket: Add socket statistics collection Add socket obj_core support to websocket so that the socket information can be viewed by "net sockets" command. Signed-off-by: Jukka Rissanen --- subsys/net/lib/websocket/websocket.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index 83bd976d1cb28d..9890571ff29ab7 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -393,6 +393,8 @@ int websocket_connect(int sock, struct websocket_request *wreq, /* Init parser FSM */ ctx->parser_state = WEBSOCKET_PARSER_STATE_OPCODE; + (void)sock_obj_core_alloc_find(ctx->real_sock, fd, SOCK_STREAM); + return fd; out: @@ -425,6 +427,8 @@ static int websocket_interal_disconnect(struct websocket_context *ctx) NET_DBG("[%p] Failed to send close message (err %d).", ctx, ret); } + (void)sock_obj_core_dealloc(ctx->sock); + websocket_context_unref(ctx); return ret; @@ -1050,6 +1054,8 @@ static int websocket_send(struct websocket_context *ctx, const uint8_t *buf, NET_DBG("[%p] Sent %d bytes", ctx, ret); + sock_obj_core_update_send_stats(ctx->sock, ret); + return ret; } @@ -1078,6 +1084,8 @@ static int websocket_recv(struct websocket_context *ctx, uint8_t *buf, NET_DBG("[%p] Received %d bytes", ctx, ret); + sock_obj_core_update_recv_stats(ctx->sock, ret); + return ret; } @@ -1166,6 +1174,8 @@ int websocket_register(int sock, uint8_t *recv_buf, size_t recv_buf_len) ctx->recv_buf.count = 0; ctx->parser_state = WEBSOCKET_PARSER_STATE_OPCODE; + (void)sock_obj_core_alloc_find(ctx->real_sock, fd, SOCK_STREAM); + return fd; out: From 25ac42839f09ebe35988c9d7df177ef1f240e1dc Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0371/1389] net: shell: Pretty print websocket output Fixing the websocket command output to align the fields and printing interface index instead of a pointer value. Signed-off-by: Jukka Rissanen --- subsys/net/lib/shell/websocket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/net/lib/shell/websocket.c b/subsys/net/lib/shell/websocket.c index 56e705199e3466..7e760024f7e13d 100644 --- a/subsys/net/lib/shell/websocket.c +++ b/subsys/net/lib/shell/websocket.c @@ -37,16 +37,16 @@ static void websocket_context_cb(struct websocket_context *context, } if ((*count) == 0) { - PR(" websocket/net_ctx\tIface " - "Local \tRemote\n"); + PR(" websocket/net_ctx \tIface\t" + "%-16s\t%-16s\n", "Local", "Remote"); } get_addresses(net_ctx, addr_local, sizeof(addr_local), addr_remote, sizeof(addr_remote)); - PR("[%2d] %p/%p\t%p %16s\t%16s\n", + PR("[%2d] %p/%p\t%d\t%-16s\t%-16s\n", (*count) + 1, context, net_ctx, - net_context_get_iface(net_ctx), + net_if_get_by_iface(net_context_get_iface(net_ctx)), addr_local, addr_remote); (*count)++; From 80b3a92fcf5c3438d789e51daf6e6588fd2ae6da Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0372/1389] Bluetooth: controller: Implement macros for vendor assert information Implement LL_ASSERT_INFO1 and LL_ASSERT_INFO2 for triggering assertions with parameter information provided for vendor core dump. Adds Kconfig CONFIG_BT_CTLR_ASSERT_VENDOR by which the new LL asserts map to BT_ASSERT_VND macros, which shall be implemented in the debug_vendor_hal.h of the platform. If not enabled, LL_ASSERT_INFO will map to existing BT_ASSERT_MSG with parameters printed. Add use of LL_ASSERT_INFO2 where ull_ticker_stop_with_mark() result may assert. Signed-off-by: Morten Priess --- subsys/bluetooth/controller/Kconfig.ll_sw_split | 10 ++++++++++ subsys/bluetooth/controller/hal/debug.h | 12 ++++++++++++ subsys/bluetooth/controller/ll_sw/ull_adv_aux.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_adv_sync.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_conn.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_conn_iso.c | 3 +-- subsys/bluetooth/controller/ll_sw/ull_scan.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_sync.c | 2 +- subsys/bluetooth/controller/ll_sw/ull_sync_iso.c | 4 ++-- 9 files changed, 30 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 9613dc8ebb262f..7828dfdf65abd7 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -671,6 +671,16 @@ config BT_CTLR_ASSERT_OVERHEAD_START otherwise leading to remote supervision timeout and possible missing local disconnect events. +config BT_CTLR_ASSERT_VENDOR + bool "Vendor Defined Assertion Information Handler" + help + This option enables a vendor specific sink for the controller assertion + mechanism, where parameter information is provided. This must be defined in + vendor debug HAL interface as \"BT_ASSERT_VND(cond, param1, param2)\", and + will be invoked whenever the controller code encounters an unrecoverable error + with parameter information. Implementation shall include the equivalent of + BT_ASSERT_DIE for halting the kernel. + config BT_CTLR_CENTRAL_SPACING int "Central Connection Spacing" depends on BT_CTLR_SCHED_ADVANCED diff --git a/subsys/bluetooth/controller/hal/debug.h b/subsys/bluetooth/controller/hal/debug.h index 9f2fc3d0c95c0b..653aa304b070b0 100644 --- a/subsys/bluetooth/controller/hal/debug.h +++ b/subsys/bluetooth/controller/hal/debug.h @@ -27,6 +27,18 @@ void bt_ctlr_assert_handle(char *file, uint32_t line); BT_ASSERT_MSG(cond, fmt, ##__VA_ARGS__) #endif +#if defined(CONFIG_BT_CTLR_ASSERT_VENDOR) +#define LL_ASSERT_INFO1(cond, param) \ + BT_ASSERT_VND(cond, param, 0) +#define LL_ASSERT_INFO2(cond, param1, param2) \ + BT_ASSERT_VND(cond, param1, param2) +#else +#define LL_ASSERT_INFO1(cond, param) \ + LL_ASSERT_MSG(cond, "param: %u", param) +#define LL_ASSERT_INFO2(cond, param1, param2) \ + LL_ASSERT_MSG(cond, "param1: %u param2: %u", param1, param2) +#endif /* CONFIG_BT_CTLR_ASSERT_VENDOR */ + #if defined(CONFIG_BT_CTLR_ASSERT_OVERHEAD_START) #define LL_ASSERT_OVERHEAD(overhead) \ LL_ASSERT_MSG(false, "%s: Actual EVENT_OVERHEAD_START_US = %u", \ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index b1a3798c1a1919..094ba62f85305f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -2647,7 +2647,7 @@ int ull_adv_aux_stop(struct ll_adv_aux_set *aux) err = ull_ticker_stop_with_mark(TICKER_ID_ADV_AUX_BASE + aux_handle, aux, &aux->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, aux_handle, err); if (err) { return err; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c index f61b5b6b0fbae7..c8f12876620f15 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c @@ -2022,7 +2022,7 @@ static uint8_t sync_stop(struct ll_adv_sync_set *sync) err = ull_ticker_stop_with_mark(TICKER_ID_ADV_SYNC_BASE + sync_handle, sync, &sync->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, sync_handle, err); if (err) { return BT_HCI_ERR_CMD_DISALLOWED; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index ef3950805b3449..7383478d1763be 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1730,7 +1730,7 @@ static inline void disable(uint16_t handle) err = ull_ticker_stop_with_mark(TICKER_ID_CONN_BASE + handle, conn, &conn->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, handle, err); conn->lll.handle = LLL_HANDLE_INVALID; conn->lll.link_tx_free = NULL; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index 4d390576763885..25ca59bc44f681 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -1568,8 +1568,7 @@ static void disable(uint16_t handle) err = ull_ticker_stop_with_mark(TICKER_ID_CONN_ISO_BASE + handle, cig, &cig->lll); - - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, handle, err); cig->lll.handle = LLL_HANDLE_INVALID; cig->lll.resume_cis = LLL_HANDLE_INVALID; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index a8498e3682cc14..36763a7c0f7f5e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -653,7 +653,7 @@ uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan) err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_BASE + handle, scan, &scan->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, handle, err); if (err) { return BT_HCI_ERR_CMD_DISALLOWED; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index cecaefef333daa..0917e594edfb8b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -412,7 +412,7 @@ uint8_t ll_sync_terminate(uint16_t handle) /* Stop periodic sync ticker timeouts */ err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_SYNC_BASE + handle, sync, &sync->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, handle, err); if (err) { return BT_HCI_ERR_CMD_DISALLOWED; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index bd312a5cf4b586..f6c68436b5eb09 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -270,7 +270,7 @@ uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx) err = ull_ticker_stop_with_mark((TICKER_ID_SCAN_SYNC_ISO_BASE + big_handle), sync_iso, &sync_iso->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, big_handle, err); if (err) { return BT_HCI_ERR_CMD_DISALLOWED; } @@ -823,7 +823,7 @@ static void disable(uint8_t sync_idx) err = ull_ticker_stop_with_mark(TICKER_ID_SCAN_SYNC_ISO_BASE + sync_idx, sync_iso, &sync_iso->lll); - LL_ASSERT(err == 0 || err == -EALREADY); + LL_ASSERT_INFO2(err == 0 || err == -EALREADY, sync_idx, err); } static int init_reset(void) From 4055356024b26ba7cd5a4fe897920a1b2eee20a1 Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0373/1389] drivers: mfd: add new driver "mfd_adp5585" Add mfd_adp5585 and gpio_adp5585 driver. This driver enables ADP5585 as an GPIO expander. This chip is used as an GPIO expander on i.MX93 EVK. GPIO pinctrl, read/write and interrupt is supported. Note that ADP5585 has 2 GPIO banks with 5 pins each. The driver combines two group into a 16-bit port. Index 0~4 correspond to R0~R4 lines, index 8~12 correspond to C0~C4 lines. Index 5~7 is reserved unavailable. Signed-off-by: Chekhov Ma --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.adp5585 | 18 + drivers/gpio/gpio_adp5585.c | 469 ++++++++++++++++++++++++ drivers/mfd/CMakeLists.txt | 1 + drivers/mfd/Kconfig | 1 + drivers/mfd/Kconfig.adp5585 | 17 + drivers/mfd/mfd_adp5585.c | 145 ++++++++ dts/arm64/nxp/nxp_mimx93_a55.dtsi | 1 + dts/bindings/gpio/adi,adp5585-gpio.yaml | 30 ++ dts/bindings/mfd/adi,adp5585.yaml | 19 + include/zephyr/drivers/mfd/adp5585.h | 126 +++++++ 12 files changed, 829 insertions(+) create mode 100644 drivers/gpio/Kconfig.adp5585 create mode 100644 drivers/gpio/gpio_adp5585.c create mode 100644 drivers/mfd/Kconfig.adp5585 create mode 100644 drivers/mfd/mfd_adp5585.c create mode 100644 dts/bindings/gpio/adi,adp5585-gpio.yaml create mode 100644 dts/bindings/mfd/adi,adp5585.yaml create mode 100644 include/zephyr/drivers/mfd/adp5585.h diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 655de8340d79e3..787a10d7dd5d41 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library() # zephyr-keep-sorted-start zephyr_library_sources_ifdef(CONFIG_GPIO_AD559X gpio_ad559x.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_ADP5585 gpio_adp5585.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ADS114S0X gpio_ads114s0x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_PIO gpio_altera_pio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_AMBIQ gpio_ambiq.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 45d0129841e30c..9ce2b7f5859f96 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -95,6 +95,7 @@ config GPIO_ENABLE_DISABLE_INTERRUPT # zephyr-keep-sorted-start source "drivers/gpio/Kconfig.ad559x" +source "drivers/gpio/Kconfig.adp5585" source "drivers/gpio/Kconfig.ads114s0x" source "drivers/gpio/Kconfig.altera" source "drivers/gpio/Kconfig.ambiq" diff --git a/drivers/gpio/Kconfig.adp5585 b/drivers/gpio/Kconfig.adp5585 new file mode 100644 index 00000000000000..d531f858f1d27f --- /dev/null +++ b/drivers/gpio/Kconfig.adp5585 @@ -0,0 +1,18 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_ADP5585 + bool "ADP5585_GPIO I2C GPIO chip" + default y + depends on DT_HAS_ADI_ADP5585_GPIO_ENABLED + select MFD + select I2C + help + Enable the ADP5585 GPIO driver. + +config GPIO_ADP5585_INIT_PRIORITY + int "Init priority" + default 70 + depends on GPIO_ADP5585 + help + Device driver initialization priority. diff --git a/drivers/gpio/gpio_adp5585.c b/drivers/gpio/gpio_adp5585.c new file mode 100644 index 00000000000000..0a1da5e63f4aac --- /dev/null +++ b/drivers/gpio/gpio_adp5585.c @@ -0,0 +1,469 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define DT_DRV_COMPAT adi_adp5585_gpio + +LOG_MODULE_REGISTER(adp5585_gpio, CONFIG_GPIO_LOG_LEVEL); + +#define ADP5585_BANK(offs) (offs >> 3) +#define ADP5585_BIT(offs) (offs & GENMASK(2, 0)) + +enum adp5585_gpio_pin_direction { + adp5585_pin_input = 0U, + adp5585_pin_output, +}; + +enum adp5585_gpio_pin_drive_mode { + adp5585_pin_drive_pp = 0U, + adp5585_pin_drive_od, +}; + +enum adp5585_gpio_pull_config { + adp5585_pull_up_300k = 0U, + adp5585_pull_dn_300k, + adp5585_pull_up_100k, /* not used */ + adp5585_pull_disable, +}; + +enum adp5585_gpio_int_en { + adp5585_int_disable = 0U, + adp5585_int_enable, +}; + +enum adp5585_gpio_int_level { + adp5585_int_active_low = 0U, + adp5585_int_active_high, +}; + +/** Configuration data */ +struct adp5585_gpio_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + const struct device *mfd_dev; + const struct gpio_dt_spec gpio_int; +}; + +/** Runtime driver data */ +struct adp5585_gpio_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + uint16_t output; + + sys_slist_t callbacks; +}; + +static int gpio_adp5585_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + int ret = 0; + uint8_t reg_value; + + /* ADP5585 has non-contiguous gpio pin layouts, account for this */ + if ((pin & cfg->common.port_pin_mask) == 0) { + LOG_ERR("pin %d is invalid for this device", pin); + return -ENOTSUP; + } + + uint8_t bank = ADP5585_BANK(pin); + uint8_t bank_pin = ADP5585_BIT(pin); + + /* Can't do I2C bus operations from an ISR */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + /* Simultaneous PU & PD mode not supported */ + if (((flags & GPIO_PULL_UP) != 0) && ((flags & GPIO_PULL_DOWN) != 0)) { + return -ENOTSUP; + } + + /* Simultaneous input & output mode not supported */ + if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { + return -ENOTSUP; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + if ((flags & GPIO_SINGLE_ENDED) != 0) { + reg_value = adp5585_pin_drive_od << bank_pin; + } else { + reg_value = adp5585_pin_drive_pp << bank_pin; + } + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, ADP5585_GPO_OUT_MODE_A + bank, + BIT(bank_pin), reg_value); + if (ret != 0) { + goto out; + } + + uint8_t regaddr = ADP5585_RPULL_CONFIG_A + (bank << 1); + uint8_t shift = bank_pin << 1; + + if (bank_pin > 3U) { + regaddr += 1U; + shift = (bank_pin - 3U) << 1; + } + if ((flags & GPIO_PULL_UP) != 0) { + reg_value = adp5585_pull_up_300k << shift; + } else if ((flags & GPIO_PULL_DOWN) != 0) { + reg_value = adp5585_pull_dn_300k << shift; + } else { + reg_value = adp5585_pull_disable << shift; + } + + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, regaddr, + 0b11U << shift, reg_value); + if (ret != 0) { + goto out; + } + + /* Ensure either Output or Input is specified */ + if ((flags & GPIO_OUTPUT) != 0) { + + /* Set Low or High if specified */ + if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { + data->output &= ~BIT(pin); + } else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + data->output |= BIT(pin); + } + if (bank == 0) { + /* reg_value for ADP5585_GPO_OUT_MODE */ + reg_value = (uint8_t)data->output; + } else { + /* reg_value for ADP5585_GPO_OUT_MODE */ + reg_value = (uint8_t)(data->output >> 8); + } + ret = i2c_reg_write_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPO_OUT_MODE_A + bank, + reg_value); + if (ret != 0) { + goto out; + } + /* reg_value for ADP5585_GPIO_DIRECTION */ + reg_value = adp5585_pin_output << bank_pin; + } else if ((flags & GPIO_INPUT) != 0) { + /* reg_value for ADP5585_GPIO_DIRECTION */ + reg_value = adp5585_pin_output << bank_pin; + } + + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPIO_DIRECTION_A + bank, + BIT(bank_pin), reg_value); + +out: + k_sem_give(&parent_data->lock); + if (ret != 0) { + LOG_ERR("pin configure error: %d", ret); + } + return ret; +} + +static int gpio_adp5585_port_read(const struct device *dev, gpio_port_value_t *value) +{ + const struct adp5585_gpio_config *cfg = dev->config; + /* struct adp5585_gpio_data *data = dev->data; */ + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + uint16_t input_data = 0; + int ret = 0; + + /* Can't do I2C bus operations from an ISR */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + /** Read Input Register */ + + uint8_t gpi_status_reg; + uint8_t gpi_status_buf[2]; + + ret = i2c_write_read_dt(&parent_cfg->i2c_bus, &gpi_status_reg, 1U, + gpi_status_buf, 2U); + if (ret) { + goto out; + } + input_data = sys_le16_to_cpu(*((uint16_t *)gpi_status_buf)); + *value = input_data; + +out: + k_sem_give(&parent_data->lock); + LOG_DBG("read %x got %d", input_data, ret); + return ret; +} + +static int gpio_adp5585_port_write(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value, gpio_port_value_t toggle) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + uint16_t orig_out; + uint16_t out; + uint8_t reg_value; + int ret; + + /* Can't do I2C bus operations from an ISR */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + orig_out = data->output; + out = ((orig_out & ~mask) | (value & mask)) ^ toggle; + + reg_value = (uint8_t)out; + uint8_t gpo_data_out_buf[] = { ADP5585_GPO_DATA_OUT_A, + (uint8_t)out, (uint8_t)(out >> 8) }; + + ret = i2c_write_dt(&parent_cfg->i2c_bus, gpo_data_out_buf, sizeof(gpo_data_out_buf)); + if (ret) { + goto out; + } + + data->output = out; + +out: + k_sem_give(&parent_data->lock); + LOG_DBG("write %x msk %08x val %08x => %x: %d", orig_out, mask, value, out, ret); + return ret; +} + +static int gpio_adp5585_port_set_masked(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + return gpio_adp5585_port_write(dev, mask, value, 0); +} + +static int gpio_adp5585_port_set_bits(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_adp5585_port_write(dev, pins, pins, 0); +} + +static int gpio_adp5585_port_clear_bits(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_adp5585_port_write(dev, pins, 0, 0); +} + +static int gpio_adp5585_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_adp5585_port_write(dev, 0, 0, pins); +} + +static int gpio_adp5585_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct adp5585_gpio_config *cfg = dev->config; + /* struct adp5585_gpio_data *data = dev->data; */ + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + int ret = 0; + + if (parent_cfg->nint_gpio.port == NULL) { + return -ENOTSUP; + } + + /* ADP5585 has non-contiguous gpio pin layouts, account for this */ + if ((pin & cfg->common.port_pin_mask) == 0) { + LOG_ERR("pin %d is invalid for this device", pin); + return -ENOTSUP; + } + + /* This device supports only level-triggered interrupts. */ + /* This device does NOT support either-level interrupt. */ + if (mode == GPIO_INT_MODE_EDGE || trig == GPIO_INT_TRIG_BOTH) { + return -ENOTSUP; + } + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + uint8_t bank = ADP5585_BANK(pin); + uint8_t bank_pin = ADP5585_BIT(pin); + + k_sem_take(&parent_data->lock, K_FOREVER); + + if (mode == GPIO_INT_MODE_DISABLED) { + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPI_INTERRUPT_EN_A + bank, BIT(bank_pin), + (adp5585_int_disable << bank_pin)); + } else if ((trig & GPIO_INT_TRIG_BOTH) != 0) { + if (trig == GPIO_INT_TRIG_LOW) { + ret = i2c_reg_update_byte_dt( + &parent_cfg->i2c_bus, ADP5585_GPI_INT_LEVEL_A + bank, + BIT(bank_pin), (adp5585_int_active_low << bank_pin)); + } else { + ret = i2c_reg_update_byte_dt( + &parent_cfg->i2c_bus, ADP5585_GPI_INT_LEVEL_A + bank, + BIT(bank_pin), (adp5585_int_active_high << bank_pin)); + } + + /* make sure GPI_n_EVENT_EN is disabled, otherwise it will generate FIFO event */ + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPI_EVENT_EN_A + bank, BIT(bank_pin), 0U); + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPI_INTERRUPT_EN_A + bank, + BIT(bank_pin), (adp5585_int_enable << bank_pin)); + } + + k_sem_give(&parent_data->lock); + return ret; +} + +static int gpio_adp5585_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct adp5585_gpio_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +void gpio_adp5585_irq_handler(const struct device *dev) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + uint16_t reg_int_status; + int ret = 0; + + k_sem_take(&parent_data->lock, K_FOREVER); + + /* Read Input Register */ + ret = i2c_burst_read_dt(&parent_cfg->i2c_bus, ADP5585_GPI_INT_STAT_A, + (uint8_t *)®_int_status, 2U); + if (ret != 0) { + LOG_WRN("%s failed to read interrupt status %d", dev->name, ret); + goto out; + } + +out: + k_sem_give(&parent_data->lock); + + if (ret == 0 && reg_int_status != 0) { + gpio_fire_callbacks(&data->callbacks, dev, reg_int_status); + } +} + +/** + * @brief Initialization function of ADP5585_GPIO + * + * This sets initial input/ output configuration and output states. + * The interrupt is configured if this is enabled. + * + * @param dev Device struct + * @return 0 if successful, failed otherwise. + */ +static int gpio_adp5585_init(const struct device *dev) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + int ret = 0; + + if (!device_is_ready(cfg->mfd_dev)) { + LOG_ERR("%s: parent dev not ready", dev->name); + ret = -ENODEV; + goto out; + } + + if (!device_is_ready(parent_cfg->i2c_bus.bus)) { + LOG_ERR("I2C bus device not found"); + ret = -EIO; + goto out; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + /** Read output register */ + uint8_t gpo_data_out_buf[] = { ADP5585_GPO_DATA_OUT_A, + 0x00, 0x00 }; + + ret = i2c_write_read_dt(&parent_cfg->i2c_bus, gpo_data_out_buf, 1U, + gpo_data_out_buf + 1, 2U); + if (ret) { + goto out; + } + data->output = sys_le16_to_cpu(*((uint16_t *)(gpo_data_out_buf + 1))); + + /** Set RPULL to high-z by default */ + uint8_t rpull_config_buf[] = { ADP5585_RPULL_CONFIG_A, + 0xffU, 0x03U, 0xffU, 0x03U }; + + ret = i2c_write_dt(&parent_cfg->i2c_bus, rpull_config_buf, sizeof(rpull_config_buf)); + if (ret) { + goto out; + } + + parent_data->child.gpio_dev = dev; + + /** Enable GPI interrupt */ + if ((ret == 0) && gpio_is_ready_dt(&parent_cfg->nint_gpio)) { + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, ADP5585_INT_EN, (1U << 1), + (1U << 1)); + } + +out: + k_sem_give(&parent_data->lock); + if (ret) { + LOG_ERR("%s init failed: %d", dev->name, ret); + } else { + LOG_INF("%s init ok", dev->name); + } + return ret; +} + +static const struct gpio_driver_api api_table = { + .pin_configure = gpio_adp5585_config, + .port_get_raw = gpio_adp5585_port_read, + .port_set_masked_raw = gpio_adp5585_port_set_masked, + .port_set_bits_raw = gpio_adp5585_port_set_bits, + .port_clear_bits_raw = gpio_adp5585_port_clear_bits, + .port_toggle_bits = gpio_adp5585_port_toggle_bits, + .pin_interrupt_configure = gpio_adp5585_pin_interrupt_configure, + .manage_callback = gpio_adp5585_manage_callback, +}; + +#define GPIO_ADP5585_INIT(inst) \ + static const struct adp5585_gpio_config adp5585_gpio_cfg_##inst = { \ + .common = { \ + .port_pin_mask = GPIO_DT_INST_PORT_PIN_MASK_NGPIOS_EXC( \ + inst, DT_INST_PROP(inst, ngpios)) \ + }, \ + .mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + static struct adp5585_gpio_data adp5585_gpio_drvdata_##inst; \ + DEVICE_DT_INST_DEFINE(inst, gpio_adp5585_init, NULL, \ + &adp5585_gpio_drvdata_##inst, \ + &adp5585_gpio_cfg_##inst, POST_KERNEL, \ + CONFIG_GPIO_ADP5585_INIT_PRIORITY, &api_table); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_ADP5585_INIT) diff --git a/drivers/mfd/CMakeLists.txt b/drivers/mfd/CMakeLists.txt index bcd9b190e15633..fa6ab5ddceda01 100644 --- a/drivers/mfd/CMakeLists.txt +++ b/drivers/mfd/CMakeLists.txt @@ -3,6 +3,7 @@ zephyr_library() +zephyr_library_sources_ifdef(CONFIG_MFD_ADP5585 mfd_adp5585.c) zephyr_library_sources_ifdef(CONFIG_MFD_MAX20335 mfd_max20335.c) zephyr_library_sources_ifdef(CONFIG_MFD_NCT38XX mfd_nct38xx.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b487c3556b00ed..c384249daed3e1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -19,6 +19,7 @@ config MFD_INIT_PRIORITY Multi-function devices initialization priority. source "drivers/mfd/Kconfig.ad559x" +source "drivers/mfd/Kconfig.adp5585" source "drivers/mfd/Kconfig.axp192" source "drivers/mfd/Kconfig.bd8lb600fs" source "drivers/mfd/Kconfig.max20335" diff --git a/drivers/mfd/Kconfig.adp5585 b/drivers/mfd/Kconfig.adp5585 new file mode 100644 index 00000000000000..e08f119a72cbc2 --- /dev/null +++ b/drivers/mfd/Kconfig.adp5585 @@ -0,0 +1,17 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +menuconfig MFD_ADP5585 + bool "Analog ADP5585 I2C configurable GPIO/PWM/KeyScan chip" + default y + depends on DT_HAS_ADI_ADP5585_ENABLED + depends on I2C + help + Enable driver for Analog ADP5585. + +config MFD_ADP5585_INIT_PRIORITY + int "Init priority" + default 65 + depends on MFD_ADP5585 + help + Device driver initialization priority. diff --git a/drivers/mfd/mfd_adp5585.c b/drivers/mfd/mfd_adp5585.c new file mode 100644 index 00000000000000..d57b82035dca44 --- /dev/null +++ b/drivers/mfd/mfd_adp5585.c @@ -0,0 +1,145 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adp5585 + +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(adp5585, CONFIG_GPIO_LOG_LEVEL); + +static int mfd_adp5585_software_reset(const struct device *dev) +{ + const struct mfd_adp5585_config *config = dev->config; + int ret = 0; + + /** Set CONFIG to gpio by default */ + uint8_t pin_config_buf[] = { ADP5585_PIN_CONFIG_A, 0x00U, 0x00U }; + + ret = i2c_write_dt(&config->i2c_bus, pin_config_buf, sizeof(pin_config_buf)); + if (ret) { + goto out; + } + +out: + if (ret) { + LOG_ERR("%s: software reset failed: %d", dev->name, ret); + } + return ret; +} + +static void mfd_adp5585_int_gpio_handler(const struct device *dev, struct gpio_callback *gpio_cb, + uint32_t pins) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pins); + + struct mfd_adp5585_data *data = CONTAINER_OF(gpio_cb, struct mfd_adp5585_data, int_gpio_cb); + + k_work_submit(&data->work); +} + +static void mfd_adp5585_work_handler(struct k_work *work) +{ + struct mfd_adp5585_data *data = CONTAINER_OF(work, struct mfd_adp5585_data, work); + const struct mfd_adp5585_config *config = data->dev->config; + uint8_t reg_int_status; + int ret = 0; + + k_sem_take(&data->lock, K_FOREVER); + /* Read Interrput Flag */ + if (ret == 0) { + ret = i2c_reg_read_byte_dt(&config->i2c_bus, ADP5585_INT_STATUS, ®_int_status); + } + /* Clear Interrput Flag */ + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->i2c_bus, ADP5585_INT_STATUS, reg_int_status); + } + + k_sem_give(&data->lock); + +#ifdef CONFIG_GPIO_ADP5585 + if ((reg_int_status & ADP5585_INT_GPI) && device_is_ready(data->child.gpio_dev)) { + (void)gpio_adp5585_irq_handler(data->child.gpio_dev); + } +#endif /* CONFIG_GPIO_ADP5585 */ +} + +static int mfd_adp5585_init(const struct device *dev) +{ + const struct mfd_adp5585_config *config = dev->config; + struct mfd_adp5585_data *data = dev->data; + int ret; + + if (!i2c_is_ready_dt(&config->i2c_bus)) { + return -ENODEV; + } + + /* reset gpio can be left float */ + if (gpio_is_ready_dt(&config->reset_gpio)) { + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + if (ret) { + LOG_ERR("%s: configure reset pin failed: %d", dev->name, ret); + return ret; + } + } else { + LOG_WRN("%s: reset pin not configured", dev->name); + } + + ret = mfd_adp5585_software_reset(dev); + if (ret) { + return ret; + } + + if (gpio_is_ready_dt(&config->nint_gpio)) { + ret = gpio_pin_configure_dt(&config->nint_gpio, GPIO_INPUT); + if (ret < 0) { + return ret; + } + ret = gpio_pin_interrupt_configure_dt(&config->nint_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (ret != 0) { + LOG_ERR("%s: failed to configure INT interrupt: %d", dev->name, ret); + return ret; + } + + gpio_init_callback(&data->int_gpio_cb, mfd_adp5585_int_gpio_handler, + BIT(config->nint_gpio.pin)); + ret = gpio_add_callback_dt(&config->nint_gpio, &data->int_gpio_cb); + if (ret != 0) { + LOG_ERR("%s: failed to add INT callback: %d", dev->name, ret); + return ret; + } + } else { + LOG_WRN("%s: nint pin not configured", dev->name); + } + + LOG_DBG("%s: init ok\r\n", dev->name); + + return 0; +} + +#define MFD_ADP5585_DEFINE(inst) \ + static const struct mfd_adp5585_config mfd_adp5585_config_##inst = { \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ + .nint_gpio = GPIO_DT_SPEC_INST_GET_OR(n, nint_gpios, {0}), \ + .i2c_bus = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + static struct mfd_adp5585_data mfd_adp5585_data_##inst = { \ + .work = Z_WORK_INITIALIZER(mfd_adp5585_work_handler), \ + .lock = Z_SEM_INITIALIZER(mfd_adp5585_data_##inst.lock, 1, 1), \ + .dev = DEVICE_DT_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_adp5585_init, NULL, &mfd_adp5585_data_##inst, \ + &mfd_adp5585_config_##inst, POST_KERNEL, \ + CONFIG_MFD_ADP5585_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_ADP5585_DEFINE); diff --git a/dts/arm64/nxp/nxp_mimx93_a55.dtsi b/dts/arm64/nxp/nxp_mimx93_a55.dtsi index 0192e62a3502b9..defcb2dc32687c 100644 --- a/dts/arm64/nxp/nxp_mimx93_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx93_a55.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include / { diff --git a/dts/bindings/gpio/adi,adp5585-gpio.yaml b/dts/bindings/gpio/adi,adp5585-gpio.yaml new file mode 100644 index 00000000000000..bb27d2facb61e7 --- /dev/null +++ b/dts/bindings/gpio/adi,adp5585-gpio.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: ADP5585 GPIO Controller + +compatible: "adi,adp5585-gpio" + +include: gpio-controller.yaml + +properties: + "#gpio-cells": + const: 2 + + ngpios: + const: 13 + description: | + Number of GPIOs available on port expander. + + gpio-reserved-ranges: + required: true + const: [5, 3] + description: | + Ranges of GPIOs reserved unavailable on port expander. + The ADP5585 has 10 GPIO lines divided in 2 groups. GPIO number + 5, 6, 7 is reserved. That's to say, GPIO R0~R4 occupy line + number 0~4, GPIO C0~C4 occupy line number 8~12. + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/mfd/adi,adp5585.yaml b/dts/bindings/mfd/adi,adp5585.yaml new file mode 100644 index 00000000000000..9d2456b6a83b50 --- /dev/null +++ b/dts/bindings/mfd/adi,adp5585.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Analog ADP5585 GPIO/keypad/PWM chip + +compatible: "adi,adp5585" + +include: i2c-device.yaml + +properties: + reset-gpios: + type: phandle-array + description: RESET pin + + nint-gpios: + type: phandle-array + description: | + Connection for the NINT signal. This signal is active-low when + produced by adp5585 GPIO node. diff --git a/include/zephyr/drivers/mfd/adp5585.h b/include/zephyr/drivers/mfd/adp5585.h new file mode 100644 index 00000000000000..abac20bcd51b16 --- /dev/null +++ b/include/zephyr/drivers/mfd/adp5585.h @@ -0,0 +1,126 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_ADP5585_H_ +#define ZEPHYR_INCLUDE_DRIVERS_MFD_ADP5585_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#define ADP5585_ID 0x00 +#define ADP5585_INT_STATUS 0x01 +#define ADP5585_STATUS 0x02 +#define ADP5585_FIFO_1 0x03 +#define ADP5585_FIFO_2 0x04 +#define ADP5585_FIFO_3 0x05 +#define ADP5585_FIFO_4 0x06 +#define ADP5585_FIFO_5 0x07 +#define ADP5585_FIFO_6 0x08 +#define ADP5585_FIFO_7 0x09 +#define ADP5585_FIFO_8 0x0A +#define ADP5585_FIFO_9 0x0B +#define ADP5585_FIFO_10 0x0C +#define ADP5585_FIFO_11 0x0D +#define ADP5585_FIFO_12 0x0E +#define ADP5585_FIFO_13 0x0F +#define ADP5585_FIFO_14 0x10 +#define ADP5585_FIFO_15 0x11 +#define ADP5585_FIFO_16 0x12 +#define ADP5585_GPI_INT_STAT_A 0x13 +#define ADP5585_GPI_INT_STAT_B 0x14 +#define ADP5585_GPI_STATUS_A 0x15 +#define ADP5585_GPI_STATUS_B 0x16 +#define ADP5585_RPULL_CONFIG_A 0x17 +#define ADP5585_RPULL_CONFIG_B 0x18 +#define ADP5585_RPULL_CONFIG_C 0x19 +#define ADP5585_RPULL_CONFIG_D 0x1A +#define ADP5585_GPI_INT_LEVEL_A 0x1B +#define ADP5585_GPI_INT_LEVEL_B 0x1C +#define ADP5585_GPI_EVENT_EN_A 0x1D +#define ADP5585_GPI_EVENT_EN_B 0x1E +#define ADP5585_GPI_INTERRUPT_EN_A 0x1F +#define ADP5585_GPI_INTERRUPT_EN_B 0x20 +#define ADP5585_DEBOUNCE_DIS_A 0x21 +#define ADP5585_DEBOUNCE_DIS_B 0x22 +#define ADP5585_GPO_DATA_OUT_A 0x23 +#define ADP5585_GPO_DATA_OUT_B 0x24 +#define ADP5585_GPO_OUT_MODE_A 0x25 +#define ADP5585_GPO_OUT_MODE_B 0x26 +#define ADP5585_GPIO_DIRECTION_A 0x27 +#define ADP5585_GPIO_DIRECTION_B 0x28 +#define ADP5585_RESET1_EVENT_A 0x29 +#define ADP5585_RESET1_EVENT_B 0x2A +#define ADP5585_RESET1_EVENT_C 0x2B +#define ADP5585_RESET2_EVENT_A 0x2C +#define ADP5585_RESET2_EVENT_B 0x2D +#define ADP5585_RESET_CFG 0x2E +#define ADP5585_PWM_OFFT_LOW 0x2F +#define ADP5585_PWM_OFFT_HIGH 0x30 +#define ADP5585_PWM_ONT_LOW 0x31 +#define ADP5585_PWM_ONT_HIGH 0x32 +#define ADP5585_PWM_CFG 0x33 +#define ADP5585_LOGIC_CFG 0x34 +#define ADP5585_LOGIC_FF_CFG 0x35 +#define ADP5585_LOGIC_INT_EVENT_EN 0x36 +#define ADP5585_POLL_PTIME_CFG 0x37 +#define ADP5585_PIN_CONFIG_A 0x38 +#define ADP5585_PIN_CONFIG_B 0x39 +#define ADP5585_PIN_CONFIG_C 0x3A +#define ADP5585_GENERAL_CFG 0x3B +#define ADP5585_INT_EN 0x3C + +/* ID Register */ +#define ADP5585_DEVICE_ID_MASK 0xF +#define ADP5585_MAN_ID_MASK 0xF +#define ADP5585_MAN_ID_SHIFT 4 +#define ADP5585_MAN_ID 0x02 + +#define ADP5585_PWM_CFG_EN 0x1 +#define ADP5585_PWM_CFG_MODE 0x2 +#define ADP5585_PIN_CONFIG_R3_PWM 0x8 +#define ADP5585_PIN_CONFIG_R3_MASK 0xC +#define ADP5585_GENERAL_CFG_OSC_EN 0x80 + +/* INT_EN and INT_STATUS Register */ +#define ADP5585_INT_EVENT (1U << 0) +#define ADP5585_INT_GPI (1U << 1) +#define ADP5585_INT_OVERFLOW (1U << 2) +#define ADP5585_INT_LOGIC (1U << 4) + +#define ADP5585_REG_MASK 0xFF + +struct mfd_adp5585_config { + struct gpio_dt_spec reset_gpio; + struct gpio_dt_spec nint_gpio; + struct i2c_dt_spec i2c_bus; +}; + +struct mfd_adp5585_data { + struct k_work work; + struct k_sem lock; + const struct device *dev; + struct { +#ifdef CONFIG_GPIO_ADP5585 + const struct device *gpio_dev; +#endif /* CONFIG_GPIO_ADP5585 */ + } child; + struct gpio_callback int_gpio_cb; +}; + +/** + * @brief Forward declaration of child device interrupt + * handler + */ +#ifdef CONFIG_GPIO_ADP5585 +void gpio_adp5585_irq_handler(const struct device *dev); +#endif /* CONFIG_GPIO_ADP5585 */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_AD5952_H_ */ From 21f8df18e4181c55374102036fc596a1369420e3 Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0374/1389] board: mimx93_evk_a55: enable mfd_adp5585 and adp5585_gpio driver. Enable ADP5585 as GPIO expander on i.MX93 EVK. - Add dts node for ADP5585 under lpi2c2. - Add gpio-hog for EXP_SEL signal. - Disable lpi2c2 and adp5585 node by default Signed-off-by: Chekhov Ma --- .../nxp/imx93_evk/imx93_evk_mimx9352_a55.dts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts index 6cd176d0ce358e..40faba8411719d 100644 --- a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts +++ b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts @@ -83,18 +83,44 @@ }; -&lpi2c1{ +&lpi2c1 { status = "disabled"; clock-frequency = ; pinctrl-0 = <&i2c1_default>; pinctrl-names = "default"; }; -&lpi2c2{ +&lpi2c2 { status = "disabled"; clock-frequency = ; pinctrl-0 = <&i2c2_default>; pinctrl-names = "default"; + + mfd0:adp5585@34 { + compatible = "adi,adp5585"; + reg = <0x34>; + status = "disabled"; + + gpio_exp0: adp5585_gpio { + compatible = "adi,adp5585-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <13>; + gpio-reserved-ranges = <5 3>; + /* + * This device has non-contiguous gpio range: + * GPIO Pin R0~R4 are gpio0~4 + * GPIO Pin C0~C4 are gpio8~12 + */ + + gpiohog_exp_sel: exp-sel-hog { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + line-name = "exp_sel"; + output-low; + }; + }; + }; }; &lpspi3 { From 344d9857df77ab6687f860a803daea47f0ed788d Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0375/1389] net: arp: Add support for gratuitous ARP transmission Add support for gratuitous ARP transmission by Zephyr network stack. This allows to prematurely fill the peer ARP table, so there's no need to send an explicit request when peer needs to send an actual packet. The gratuitous ARP is send when the network interface is brought up (joins the network) or a new IP address is added. The gratuitous ARP request is also sent periodically, with a configurable interval time. The gratuitous ARP should also be sent whenever MAC address of the interface is changed, but as Zephyr only allows to do this when interface is down, this is already covered by the first case (interface brought up). Signed-off-by: Robert Lubos --- subsys/net/l2/ethernet/Kconfig | 13 +++ subsys/net/l2/ethernet/arp.c | 157 +++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/subsys/net/l2/ethernet/Kconfig b/subsys/net/l2/ethernet/Kconfig index 17588b17fd1f38..e6fd07e47e28f6 100644 --- a/subsys/net/l2/ethernet/Kconfig +++ b/subsys/net/l2/ethernet/Kconfig @@ -73,6 +73,19 @@ config NET_ARP_GRATUITOUS ff:ff:ff:ff:ff:ff. Ordinarily, no reply packet will occur. A gratuitous ARP reply is a reply to which no request has been made. +config NET_ARP_GRATUITOUS_TRANSMISSION + bool "Transmit gratuitous ARP requests" + depends on NET_ARP_GRATUITOUS + depends on NET_MGMT_EVENT + depends on NET_MGMT_EVENT_INFO + help + Transmit gratuitous ARP requests, as defined in RFC 5227. + +config NET_ARP_GRATUITOUS_INTERVAL + int "Time interval (in seconds) between sending gratuitous ARP requests" + depends on NET_ARP_GRATUITOUS_TRANSMISSION + default 60 + if NET_ARP module = NET_ARP module-dep = NET_LOG diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index 7c0a2ba74f2566..85eafd0eedb334 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(net_arp, CONFIG_NET_ARP_LOG_LEVEL); #include #include #include +#include #include "arp.h" #include "net_private.h" @@ -34,6 +35,12 @@ static struct k_work_delayable arp_request_timer; static struct k_mutex arp_mutex; +#if defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) +static struct net_mgmt_event_callback iface_event_cb; +static struct net_mgmt_event_callback ipv4_event_cb; +static struct k_work_delayable arp_gratuitous_work; +#endif /* defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) */ + static void arp_entry_cleanup(struct arp_entry *entry, bool pending) { NET_DBG("entry %p", entry); @@ -466,6 +473,141 @@ static void arp_gratuitous(struct net_if *iface, } } +#if defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) +static void arp_gratuitous_send(struct net_if *iface, + struct in_addr *ipaddr) +{ + struct net_arp_hdr *hdr; + struct net_pkt *pkt; + + pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_arp_hdr), + AF_UNSPEC, 0, NET_BUF_TIMEOUT); + if (!pkt) { + return; + } + + net_buf_add(pkt->buffer, sizeof(struct net_arp_hdr)); + net_pkt_set_vlan_tag(pkt, net_eth_get_vlan_tag(iface)); + + hdr = NET_ARP_HDR(pkt); + + hdr->hwtype = htons(NET_ARP_HTYPE_ETH); + hdr->protocol = htons(NET_ETH_PTYPE_IP); + hdr->hwlen = sizeof(struct net_eth_addr); + hdr->protolen = sizeof(struct in_addr); + hdr->opcode = htons(NET_ARP_REQUEST); + + memcpy(&hdr->dst_hwaddr.addr, net_eth_broadcast_addr(), + sizeof(struct net_eth_addr)); + memcpy(&hdr->src_hwaddr.addr, net_if_get_link_addr(iface)->addr, + sizeof(struct net_eth_addr)); + + net_ipv4_addr_copy_raw(hdr->dst_ipaddr, (uint8_t *)ipaddr); + net_ipv4_addr_copy_raw(hdr->src_ipaddr, (uint8_t *)ipaddr); + + net_pkt_lladdr_src(pkt)->addr = net_if_get_link_addr(iface)->addr; + net_pkt_lladdr_src(pkt)->len = sizeof(struct net_eth_addr); + + net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)net_eth_broadcast_addr(); + net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr); + + NET_DBG("Sending gratuitous ARP pkt %p", pkt); + + if (net_if_send_data(iface, pkt) == NET_DROP) { + net_pkt_unref(pkt); + } +} + +static void notify_all_ipv4_addr(struct net_if *iface) +{ + struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4; + int i; + + if (!ipv4) { + return; + } + + for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { + if (ipv4->unicast[i].ipv4.is_used && + ipv4->unicast[i].ipv4.address.family == AF_INET && + ipv4->unicast[i].ipv4.addr_state == NET_ADDR_PREFERRED) { + arp_gratuitous_send(iface, + &ipv4->unicast[i].ipv4.address.in_addr); + } + } +} + +static void iface_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + ARG_UNUSED(cb); + + if (!(net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET) || + net_eth_is_vlan_interface(iface))) { + return; + } + + if (mgmt_event != NET_EVENT_IF_UP) { + return; + } + + notify_all_ipv4_addr(iface); +} + +static void ipv4_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + struct in_addr *ipaddr; + + if (!(net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET) || + net_eth_is_vlan_interface(iface))) { + return; + } + + if (!net_if_is_up(iface)) { + return; + } + + if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { + return; + } + + if (cb->info_length != sizeof(struct in_addr)) { + return; + } + + ipaddr = (struct in_addr *)cb->info; + + arp_gratuitous_send(iface, ipaddr); +} + +static void iface_cb(struct net_if *iface, void *user_data) +{ + ARG_UNUSED(user_data); + + if (!(net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET) || + net_eth_is_vlan_interface(iface))) { + return; + } + + if (!net_if_is_up(iface)) { + return; + } + + notify_all_ipv4_addr(iface); +} + +static void arp_gratuitous_work_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + net_if_foreach(iface_cb, NULL); + + k_work_reschedule(&arp_gratuitous_work, + K_SECONDS(CONFIG_NET_ARP_GRATUITOUS_INTERVAL)); +} +#endif /* defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) */ + void net_arp_update(struct net_if *iface, struct in_addr *src, struct net_eth_addr *hwaddr, @@ -837,4 +979,19 @@ void net_arp_init(void) k_mutex_init(&arp_mutex); arp_cache_initialized = true; + +#if defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) + net_mgmt_init_event_callback(&iface_event_cb, iface_event_handler, + NET_EVENT_IF_UP); + net_mgmt_init_event_callback(&ipv4_event_cb, ipv4_event_handler, + NET_EVENT_IPV4_ADDR_ADD); + + net_mgmt_add_event_callback(&iface_event_cb); + net_mgmt_add_event_callback(&ipv4_event_cb); + + k_work_init_delayable(&arp_gratuitous_work, + arp_gratuitous_work_handler); + k_work_reschedule(&arp_gratuitous_work, + K_SECONDS(CONFIG_NET_ARP_GRATUITOUS_INTERVAL)); +#endif /* defined(CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION) */ } From 06e9ee30ee306f2fa872dc0f07b6f70fe3d32345 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0376/1389] tests: net: all: Make sure gratuitous ARP transmission is enabled Add you config to the build-all net tests, to make sure everything build properly. Signed-off-by: Robert Lubos --- tests/net/all/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/net/all/prj.conf b/tests/net/all/prj.conf index 1ab45c3ef6dbd1..90d38919cdad83 100644 --- a/tests/net/all/prj.conf +++ b/tests/net/all/prj.conf @@ -221,6 +221,7 @@ CONFIG_NET_ARP=y CONFIG_NET_ARP_TABLE_SIZE=3 CONFIG_NET_ARP_LOG_LEVEL_DBG=y CONFIG_NET_ARP_GRATUITOUS=y +CONFIG_NET_ARP_GRATUITOUS_TRANSMISSION=y # Logging CONFIG_NET_LOG=y From 81a7cc2fd845828b4dd837dece71d8510db458c7 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0377/1389] mbedtls: add Kconfig option for PSA_WANT_ALG_SHA_256 Create a new Kconfig named CONFIG_PSA_WANT_ALG_SHA_256 which allows to enable PSA_WANT_ALG_SHA_256. This allows to use PSA functions to compute SHA256 hashes. When PSA is provided by TFM this allows also to remove legacy mbedtls_sha256() support and therefore reduce footprint for the NS side. Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig | 1 + modules/mbedtls/Kconfig.psa | 14 ++++++++++++++ modules/mbedtls/configs/config-tls-generic.h | 9 ++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 modules/mbedtls/Kconfig.psa diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index daaee438a38c77..dab5ef4215d995 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -13,6 +13,7 @@ config MBEDTLS_PROMPTLESS mbed TLS menu prompt and instead handle the selection of MBEDTLS from dependent sub-configurations and thus prevent stuck symbol behavior. +rsource "Kconfig.psa" menuconfig MBEDTLS bool "mbed TLS Support" if !MBEDTLS_PROMPTLESS diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa new file mode 100644 index 00000000000000..35200a9d2f4f2a --- /dev/null +++ b/modules/mbedtls/Kconfig.psa @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config MBEDTLS_PSA_CRYPTO_CLIENT + bool + default y + depends on BUILD_WITH_TFM || MBEDTLS_PSA_CRYPTO_C + +if MBEDTLS_PSA_CRYPTO_CLIENT + +config PSA_WANT_ALG_SHA_256 + bool "SHA-256 hash algorithm through PSA" + +endif # MBEDTLS_PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 18be5b4119ebb1..d33b2de0e4b1af 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -496,8 +496,15 @@ #endif #if defined(CONFIG_BUILD_WITH_TFM) -#define MBEDTLS_PSA_CRYPTO_CLIENT #undef MBEDTLS_PSA_CRYPTO_C #endif /* CONFIG_BUILD_WITH_TFM */ +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) +#define MBEDTLS_PSA_CRYPTO_CLIENT +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_256) +#define PSA_WANT_ALG_SHA_256 1 +#endif + #endif /* MBEDTLS_CONFIG_H */ From fca0b6dcdecb419415342426f6dea586a0b7a67a Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0378/1389] net: tls_credentials: use PSA to compute SHA256 when BUILD_WITH_TFM When using the TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE there is BUILD_WITH_TFM enabled which means that we can take advantage of TFM (thorugh PSA interface) to compute the SHA256 hash. This removes the need for the built-in implementation of mbedtls_sha256() on the non-secure image (unless it's used somewhere else, of course) and therefore it helps in reducing the memory footprint. Signed-off-by: Valerio Setti --- subsys/net/lib/tls_credentials/Kconfig | 1 + .../tls_credentials/tls_credentials_digest_raw.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/subsys/net/lib/tls_credentials/Kconfig b/subsys/net/lib/tls_credentials/Kconfig index 58ec0949d474f8..760a3ce6757b2a 100644 --- a/subsys/net/lib/tls_credentials/Kconfig +++ b/subsys/net/lib/tls_credentials/Kconfig @@ -28,6 +28,7 @@ config TLS_CREDENTIALS_BACKEND_VOLATILE config TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE bool "TLS credentials management protected storage backend" depends on BUILD_WITH_TFM + select PSA_WANT_ALG_SHA_256 help TLS credentials management backend using the Protected Storage API to store credentials with integrity check against physical diff --git a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c index 2013c5d52fb787..c85b35452b8092 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c +++ b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c @@ -55,19 +55,24 @@ int credential_digest_raw(struct tls_credential *credential, void *dest, size_t return err; } -#elif defined(MBEDTLS_SHA256_C) && defined(CONFIG_BASE64) +#elif defined(CONFIG_PSA_WANT_ALG_SHA_256) && defined(CONFIG_BASE64) -#include -#include +#include int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len) { int err = 0; size_t written = 0; uint8_t digest_buf[32]; + size_t digest_len; + psa_status_t status; - /* Compute digest. The '0' indicates to mbedtls to use SHA256 instead of 224. */ - mbedtls_sha256(credential->buf, credential->len, digest_buf, 0); + /* Compute digest. */ + status = psa_hash_compute(PSA_ALG_SHA_256, credential->buf, credential->len, + digest_buf, sizeof(digest_buf), &digest_len); + if (status != PSA_SUCCESS) { + return -EIO; + } /* Attempt to encode digest to destination. * Will return -ENOMEM if there is not enough space in the destination buffer. From ca4985ddeb1b009d482ec8f3597ab040656e5044 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:44 +0200 Subject: [PATCH 0379/1389] test: tls_credentials: relax requirements for test execution Remove dependency on netif for net.tls_credentials.trusted_tfm in order to have the test fully built and executed in at least 1 platform (i.e. mps2/an521/cpu0/ns) Signed-off-by: Valerio Setti --- tests/net/lib/tls_credentials/testcase.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/lib/tls_credentials/testcase.yaml b/tests/net/lib/tls_credentials/testcase.yaml index 042a59405a8e19..77e3ac8f28398e 100644 --- a/tests/net/lib/tls_credentials/testcase.yaml +++ b/tests/net/lib/tls_credentials/testcase.yaml @@ -10,5 +10,5 @@ tests: tags: - net - tls - - trusted - depends_on: netif + - tfm + - trusted-firmware-m From 9763c533e3f74647b473ef43c0ac974a9d2b386d Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0380/1389] tls_credentials: remove TinyCrypt implementation of digest_raw Moving toward the adoption of PSA crypto APIs, TinyCrypt is going to be deprecated so we can remove it in favor of newer APIs. Moreover tls_credentials is mostly meant to store data in the protected storage meaning that there is a TFM implementation providing this service. The same TFM can of course be used to compute sha256 hashing thus saving memory footprint on the NS side by removing TC. Signed-off-by: Valerio Setti --- .../tls_credentials_digest_raw.c | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c index c85b35452b8092..95c41984de2f5d 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c +++ b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c @@ -16,46 +16,7 @@ #include "tls_internal.h" #include "tls_credentials_digest_raw.h" -/* Grab mbedTLS headers if they are available so that we can check whether SHA256 is supported */ - -#if defined(CONFIG_MBEDTLS) -#if !defined(CONFIG_MBEDTLS_CFG_FILE) -#include "mbedtls/config.h" -#else -#include CONFIG_MBEDTLS_CFG_FILE -#endif /* CONFIG_MBEDTLS_CFG_FILE */ -#endif /* CONFIG_MBEDTLS */ - -#if defined(CONFIG_TINYCRYPT_SHA256) && defined(CONFIG_BASE64) - -#include -#include - -int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len) -{ - int err = 0; - size_t written = 0; - struct tc_sha256_state_struct sha_state; - uint8_t digest_buf[TC_SHA256_DIGEST_SIZE]; - - /* Compute digest. */ - (void)tc_sha256_init(&sha_state); - (void)tc_sha256_update(&sha_state, credential->buf, credential->len); - (void)tc_sha256_final(digest_buf, &sha_state); - - /* Attempt to encode digest to destination. - * Will return -ENOMEM if there is not enough space in the destination buffer. - */ - err = base64_encode(dest, *len, &written, digest_buf, sizeof(digest_buf)); - *len = err ? 0 : written; - - /* Clean up. */ - memset(&sha_state, 0, sizeof(sha_state)); - memset(digest_buf, 0, sizeof(digest_buf)); - return err; -} - -#elif defined(CONFIG_PSA_WANT_ALG_SHA_256) && defined(CONFIG_BASE64) +#if defined(CONFIG_PSA_WANT_ALG_SHA_256) && defined(CONFIG_BASE64) #include From 9e0bc526f00ba039e1a45144ed31cfdef3bb7b3e Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0381/1389] net: tcp: use CS random generators to generate ISN Use only cryptographically secure random number generators for ISN. Signed-off-by: Valerio Setti --- subsys/net/ip/tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 8e5f7abf652223..3fedc2563504fa 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -2291,7 +2291,7 @@ static uint32_t tcpv6_init_isn(struct in6_addr *saddr, static bool once; if (!once) { - sys_rand_get(unique_key, sizeof(unique_key)); + sys_csrand_get(unique_key, sizeof(unique_key)); once = true; } @@ -2326,7 +2326,7 @@ static uint32_t tcpv4_init_isn(struct in_addr *saddr, static bool once; if (!once) { - sys_rand_get(unique_key, sizeof(unique_key)); + sys_csrand_get(unique_key, sizeof(unique_key)); once = true; } From eeebec68b8a5c09fd56e84d6846f3ce597155669 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0382/1389] mbedtls: add option to use CSPRNG as random source for PSA_CRYPTO_C Add a choice to select between legacy modules (i.e. ENTROPY + CTR_DRBG/HMAC_DRBG) and CSPRNG as random generators for PSA_CRYPTO_C. Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.tls-generic | 24 ++++++++++++++++++-- modules/mbedtls/configs/config-tls-generic.h | 4 ++++ modules/mbedtls/zephyr_init.c | 23 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index d75abd64be2f00..b55111a5599c73 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -460,10 +460,30 @@ config MBEDTLS_SSL_EXTENDED_MASTER_SECRET which ensures that master secrets are different for every connection and every session. +choice MBEDTLS_PSA_CRYPTO_RND_SOURCE + prompt "Select random source for built-in PSA crypto" + default MBEDTLS_PSA_CRYPTO_LEGACY_RNG + +config MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + bool "Use a cryptographically secure driver as random source" + depends on CSPRNG_ENABLED + help + Use cryptographically secure random generator to provide random data + instead of legacy MbedTLS modules (ENTROPY + CTR_DRBG/HMAC_DRBG). + +config MBEDTLS_PSA_CRYPTO_LEGACY_RNG + bool "Use legacy modules to generate random data" + select MBEDTLS_ENTROPY_ENABLED + select MBEDTLS_CTR_DRBG_ENABLED if !MBEDTLS_HMAC_DRBG_ENABLED + help + Use legacy MbedTLS modules (ENTROPY + CTR_DRBG/HMAC_DRBG) as random + source generators. + +endchoice + config MBEDTLS_PSA_CRYPTO_C bool "Platform Security Architecture cryptography API" - depends on MBEDTLS_ENTROPY_ENABLED - depends on MBEDTLS_CTR_DRBG_ENABLED || MBEDTLS_HMAC_DRBG_ENABLED + depends on MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG || MBEDTLS_PSA_CRYPTO_LEGACY_RNG default y if UOSCORE || UEDHOC config MBEDTLS_LMS diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index d33b2de0e4b1af..6febce2c60db01 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -468,6 +468,10 @@ #define MBEDTLS_SSL_EXTENDED_MASTER_SECRET #endif +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG +#endif + #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_C #define MBEDTLS_USE_PSA_CRYPTO diff --git a/modules/mbedtls/zephyr_init.c b/modules/mbedtls/zephyr_init.c index 28a6a40fdc5451..78602e497e3899 100644 --- a/modules/mbedtls/zephyr_init.c +++ b/modules/mbedtls/zephyr_init.c @@ -115,3 +115,26 @@ mbedtls_ms_time_t mbedtls_ms_time(void) { return (mbedtls_ms_time_t)k_uptime_get(); } + +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/* MBEDTLS_PSA_CRYPTO_C requires a random generator to work and this can + * be achieved through either legacy MbedTLS modules + * (ENTROPY + CTR_DRBG/HMAC_DRBG) or provided externally by enabling the + * CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. In the latter case the following + * callback functions needs to be defined. + */ +psa_status_t mbedtls_psa_external_get_random( + mbedtls_psa_external_random_context_t *context, + uint8_t *output, size_t output_size, size_t *output_length) +{ + (void) context; + + if (sys_csrand_get(output, output_size) != 0) { + return PSA_ERROR_GENERIC_ERROR; + } + + *output_length = output_size; + + return PSA_SUCCESS; +} +#endif From 68ca0dab2513d3b4437bcf58f2aef6f8e285964b Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0383/1389] net: tcp: use PSA for SHA256 when BUILD_WITH_TFM When BUILD_WITH_TFM is enabled we can dispatch hash computation to TFM. This allows to remove the built-in support of SHA256 from the non-secure side (if it's not used for any other purpose, of course). Signed-off-by: Valerio Setti --- subsys/net/ip/Kconfig.tcp | 4 +--- subsys/net/ip/tcp.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/subsys/net/ip/Kconfig.tcp b/subsys/net/ip/Kconfig.tcp index e7d45f46c7a6c0..9df87e31b60997 100644 --- a/subsys/net/ip/Kconfig.tcp +++ b/subsys/net/ip/Kconfig.tcp @@ -229,9 +229,7 @@ config NET_TCP_ISN_RFC6528 bool "Use ISN algorithm from RFC 6528" default y depends on NET_TCP - select MBEDTLS - select MBEDTLS_MD - select MBEDTLS_MAC_MD5_ENABLED + depends on PSA_WANT_ALG_SHA_256 help Implement Initial Sequence Number calculation as described in RFC 6528 chapter 3. https://tools.ietf.org/html/rfc6528 diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 3fedc2563504fa..0c747449f85ec7 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL); #include #if defined(CONFIG_NET_TCP_ISN_RFC6528) -#include +#include #endif #include #include @@ -2298,7 +2298,10 @@ static uint32_t tcpv6_init_isn(struct in6_addr *saddr, memcpy(buf.key, unique_key, sizeof(buf.key)); #if defined(CONFIG_NET_TCP_ISN_RFC6528) - mbedtls_md5((const unsigned char *)&buf, sizeof(buf), hash); + size_t hash_len; + + psa_hash_compute(PSA_ALG_SHA_256, (const unsigned char *)&buf, sizeof(buf), + hash, sizeof(hash), &hash_len); #endif return seq_scale(UNALIGNED_GET((uint32_t *)&hash[0])); @@ -2333,7 +2336,10 @@ static uint32_t tcpv4_init_isn(struct in_addr *saddr, memcpy(buf.key, unique_key, sizeof(unique_key)); #if defined(CONFIG_NET_TCP_ISN_RFC6528) - mbedtls_md5((const unsigned char *)&buf, sizeof(buf), hash); + size_t hash_len; + + psa_hash_compute(PSA_ALG_SHA_256, (const unsigned char *)&buf, sizeof(buf), + hash, sizeof(hash), &hash_len); #endif return seq_scale(UNALIGNED_GET((uint32_t *)&hash[0])); From f717b5c894d040ddc7c7c8bfa45cd4978efb293b Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0384/1389] tests: mbedtls: add missing CONFIGS CONFIG_MINIMAL_LIBC was required for: - CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS - CONFIG_MINIMAL_LIBC_RAND while CONFIG_ENTROPY_GENERATOR and CONFIG_MBEDTLS_ZEPHYR_ENTROPY are required for CRYPTO_C. Signed-off-by: Valerio Setti --- tests/crypto/mbedtls/prj.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/crypto/mbedtls/prj.conf b/tests/crypto/mbedtls/prj.conf index 9b6af503e038e9..dd5e629e16a400 100644 --- a/tests/crypto/mbedtls/prj.conf +++ b/tests/crypto/mbedtls/prj.conf @@ -4,5 +4,9 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_TEST=y CONFIG_ZTEST=y CONFIG_TEST_USERSPACE=y +CONFIG_MINIMAL_LIBC=y CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y CONFIG_MINIMAL_LIBC_RAND=y +CONFIG_ENTROPY_GENERATOR=y +CONFIG_MBEDTLS_ZEPHYR_ENTROPY=y +CONFIG_TEST_RANDOM_GENERATOR=y From a9788ae5f48f47520db2ccd13550fbf631ba020f Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0385/1389] mbedtls: do not include PSA ITS when using PICOLIBC PICOLIBC misses the dirent.h header which is required to emulate ITS (internal trusted storage) in PSA APIs. Signed-off-by: Valerio Setti --- modules/mbedtls/configs/config-tls-generic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 6febce2c60db01..383ab44f18b040 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -476,7 +476,7 @@ #define MBEDTLS_PSA_CRYPTO_C #define MBEDTLS_USE_PSA_CRYPTO -#if defined(CONFIG_ARCH_POSIX) +#if defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_PICOLIBC) #define MBEDTLS_PSA_KEY_SLOT_COUNT 64 #define MBEDTLS_PSA_CRYPTO_STORAGE_C #define MBEDTLS_PSA_ITS_FILE_C From 10dd12b962048b8bddf2802964177596d4be5420 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0386/1389] mbedtls: add specific Kconfig option for MBEDTLS_USE_PSA_CRYPTO MBEDTLS_PSA_CRYPTO_C and MBEDTLS_USE_PSA_CRYPTO are 2 different things and the former should not automatically enable the latter. The reson is that the user might want the MbedTLS PSA crypto toolbox to be built, but at the same time he/she does not want TLS/DTLS (and other intermediate modules such as PK, MD and Cipher) to use PSA APIs. For this reason this commit introduces a new Kconfig option named CONFIG_MBEDTLS_USE_PSA_CRYPTO to enable the corresponding build symbol. By default USE_PSA_CRYPTO is disabled. It is only explicilty enabled in tests/samples that were previously setting CRYPTO_C (since in those cases USE_PSA was set). Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.tls-generic | 6 ++++++ modules/mbedtls/configs/config-tls-generic.h | 3 +++ samples/tfm_integration/psa_crypto/prj.conf | 1 + subsys/bluetooth/mesh/Kconfig | 1 + 4 files changed, 11 insertions(+) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index b55111a5599c73..5087213bb27ecf 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -486,6 +486,12 @@ config MBEDTLS_PSA_CRYPTO_C depends on MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG || MBEDTLS_PSA_CRYPTO_LEGACY_RNG default y if UOSCORE || UEDHOC +config MBEDTLS_USE_PSA_CRYPTO + bool "Use PSA APIs instead of legacy MbedTLS when possible" + help + Use PSA APIs instead of legacy MbedTLS functions in TLS/DTLS and other + "intermediate" modules such as PK, MD and Cipher. + config MBEDTLS_LMS bool "Support LMS signature schemes" depends on MBEDTLS_PSA_CRYPTO_C diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 383ab44f18b040..92ab1f66edb76c 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -474,7 +474,10 @@ #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_C + +#if defined(CONFIG_MBEDTLS_USE_PSA_CRYPTO) #define MBEDTLS_USE_PSA_CRYPTO +#endif #if defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_PICOLIBC) #define MBEDTLS_PSA_KEY_SLOT_COUNT 64 diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index a7ac8db8f2e149..f308a5aefaf5b7 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -29,6 +29,7 @@ CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_MBEDTLS_USE_PSA_CRYPTO=y CONFIG_MBEDTLS_ENTROPY_ENABLED=y CONFIG_MBEDTLS_ECP_C=y CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 88fccf0961cf55..74e377569b3386 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1349,6 +1349,7 @@ config BT_MESH_USES_MBEDTLS_PSA select MBEDTLS select MBEDTLS_ZEPHYR_ENTROPY select MBEDTLS_PSA_CRYPTO_C + select MBEDTLS_USE_PSA_CRYPTO select MBEDTLS_MAC_CMAC_ENABLED select MBEDTLS_CIPHER_AES_ENABLED select MBEDTLS_AES_ROM_TABLES From edda5d5045bd1a1fe58e8d78667561d7d909cc0a Mon Sep 17 00:00:00 2001 From: David Schneider Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0387/1389] libc/picolibc: Support Picolibc for toolchains without bundled Picolibc Allow Picolibc to get build from module, if the toolchain does not include a bundled picolibc. This should always be possible, except for native applications and if libcpp is required. Signed-off-by: David Schneider --- lib/libc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index dc65b683118df5..1dcc3dc729ac31 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -43,7 +43,6 @@ config NEWLIB_LIBC_SUPPORTED config PICOLIBC_SUPPORTED bool depends on !NATIVE_APPLICATION - depends on ("$(TOOLCHAIN_HAS_PICOLIBC)" = "y") || (NATIVE_LIBRARY) depends on !REQUIRES_FULL_LIBCPP || ("$(TOOLCHAIN_HAS_PICOLIBC)" = "y") default y select FULL_LIBC_SUPPORTED From aacdac5e5fa6ee506221b00174c9fb66c7ec9295 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0388/1389] 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 --- arch/arc/core/mpu/arc_core_mpu.c | 2 +- arch/arc/core/mpu/arc_mpu_common_internal.h | 2 +- arch/arc/core/mpu/arc_mpu_v4_internal.h | 2 +- arch/arm/core/mpu/arm_core_mpu.c | 2 +- arch/arm/core/mpu/arm_core_mpu_dev.h | 2 +- arch/arm/core/mpu/arm_mpu.c | 2 +- arch/arm/core/mpu/arm_mpu_v7_internal.h | 2 +- arch/arm/core/mpu/arm_mpu_v8_internal.h | 4 ++-- arch/arm/core/mpu/nxp_mpu.c | 2 +- arch/arm64/core/userspace.S | 2 +- arch/riscv/core/pmp.c | 2 +- arch/x86/core/x86_mmu.c | 8 ++++---- arch/xtensa/core/mpu.c | 2 +- arch/xtensa/core/ptables.c | 2 +- include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h | 2 +- include/zephyr/arch/arch_interface.h | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arc/core/mpu/arc_core_mpu.c b/arch/arc/core/mpu/arc_core_mpu.c index 0ffcdc875b4e37..2d739d7a233ed2 100644 --- a/arch/arc/core/mpu/arc_core_mpu.c +++ b/arch/arc/core/mpu/arc_core_mpu.c @@ -34,7 +34,7 @@ int arch_mem_domain_max_partitions_get(void) /* * Validate the given buffer is user accessible or not */ -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { return arc_core_mpu_buffer_validate(addr, size, write); } diff --git a/arch/arc/core/mpu/arc_mpu_common_internal.h b/arch/arc/core/mpu/arc_mpu_common_internal.h index 736a9742af96b2..a9ff5518b2fd33 100644 --- a/arch/arc/core/mpu/arc_mpu_common_internal.h +++ b/arch/arc/core/mpu/arc_mpu_common_internal.h @@ -207,7 +207,7 @@ int arc_core_mpu_get_max_domain_partition_regions(void) /** * @brief validate the given buffer is user accessible or not */ -int arc_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arc_core_mpu_buffer_validate(const void *addr, size_t size, int write) { /* * For ARC MPU, smaller region number takes priority. diff --git a/arch/arc/core/mpu/arc_mpu_v4_internal.h b/arch/arc/core/mpu/arc_mpu_v4_internal.h index e7e91fed93fd32..3bf6fca6c43b8c 100644 --- a/arch/arc/core/mpu/arc_mpu_v4_internal.h +++ b/arch/arc/core/mpu/arc_mpu_v4_internal.h @@ -779,7 +779,7 @@ int arc_core_mpu_get_max_domain_partition_regions(void) /** * @brief validate the given buffer is user accessible or not */ -int arc_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arc_core_mpu_buffer_validate(const void *addr, size_t size, int write) { int r_index; int key = arch_irq_lock(); diff --git a/arch/arm/core/mpu/arm_core_mpu.c b/arch/arm/core/mpu/arm_core_mpu.c index 2fb0f141125b05..dde98c0b07fa86 100644 --- a/arch/arm/core/mpu/arm_core_mpu.c +++ b/arch/arm/core/mpu/arm_core_mpu.c @@ -338,7 +338,7 @@ int arch_mem_domain_max_partitions_get(void) return ARM_CORE_MPU_MAX_DOMAIN_PARTITIONS_GET(available_regions); } -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { return arm_core_mpu_buffer_validate(addr, size, write); } diff --git a/arch/arm/core/mpu/arm_core_mpu_dev.h b/arch/arm/core/mpu/arm_core_mpu_dev.h index fd56131d7dc1bf..254d6d9dda341a 100644 --- a/arch/arm/core/mpu/arm_core_mpu_dev.h +++ b/arch/arm/core/mpu/arm_core_mpu_dev.h @@ -261,7 +261,7 @@ int arm_core_mpu_get_max_available_dyn_regions(void); * spans multiple enabled MPU regions (even if these regions all * permit user access). */ -int arm_core_mpu_buffer_validate(void *addr, size_t size, int write); +int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write); #endif /* CONFIG_ARM_MPU */ diff --git a/arch/arm/core/mpu/arm_mpu.c b/arch/arm/core/mpu/arm_mpu.c index cd4c8ccd7a07f5..52ad585b79c13c 100644 --- a/arch/arm/core/mpu/arm_mpu.c +++ b/arch/arm/core/mpu/arm_mpu.c @@ -341,7 +341,7 @@ int arm_core_mpu_get_max_available_dyn_regions(void) * * Presumes the background mapping is NOT user accessible. */ -int arm_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write) { return mpu_buffer_validate(addr, size, write); } diff --git a/arch/arm/core/mpu/arm_mpu_v7_internal.h b/arch/arm/core/mpu/arm_mpu_v7_internal.h index 1fe3417901ee99..9641ab250003c8 100644 --- a/arch/arm/core/mpu/arm_mpu_v7_internal.h +++ b/arch/arm/core/mpu/arm_mpu_v7_internal.h @@ -169,7 +169,7 @@ static inline int is_user_accessible_region(uint32_t r_index, int write) * This internal function validates whether a given memory buffer * is user accessible or not. */ -static inline int mpu_buffer_validate(void *addr, size_t size, int write) +static inline int mpu_buffer_validate(const void *addr, size_t size, int write) { int32_t r_index; int rc = -EPERM; diff --git a/arch/arm/core/mpu/arm_mpu_v8_internal.h b/arch/arm/core/mpu/arm_mpu_v8_internal.h index 751786d5a4c990..66a00a452a7ada 100644 --- a/arch/arm/core/mpu/arm_mpu_v8_internal.h +++ b/arch/arm/core/mpu/arm_mpu_v8_internal.h @@ -408,7 +408,7 @@ static inline int is_user_accessible_region(uint32_t rnr, int write) * This internal function validates whether a given memory buffer * is user accessible or not. */ -static inline int mpu_buffer_validate(void *addr, size_t size, int write) +static inline int mpu_buffer_validate(const void *addr, size_t size, int write) { int32_t rnr; int rc = -EPERM; @@ -455,7 +455,7 @@ static inline int mpu_buffer_validate(void *addr, size_t size, int write) * in case the fast address range check fails. * */ -static inline int mpu_buffer_validate(void *addr, size_t size, int write) +static inline int mpu_buffer_validate(const void *addr, size_t size, int write) { uint32_t _addr = (uint32_t)addr; uint32_t _size = (uint32_t)size; diff --git a/arch/arm/core/mpu/nxp_mpu.c b/arch/arm/core/mpu/nxp_mpu.c index 39d7cde6f8f52c..b0fe24c6bf617a 100644 --- a/arch/arm/core/mpu/nxp_mpu.c +++ b/arch/arm/core/mpu/nxp_mpu.c @@ -602,7 +602,7 @@ static inline int is_user_accessible_region(uint32_t r_index, int write) /** * @brief validate the given buffer is user accessible or not */ -int arm_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write) { uint8_t r_index; diff --git a/arch/arm64/core/userspace.S b/arch/arm64/core/userspace.S index 618aa6b2c20b1c..968d2a436bc55e 100644 --- a/arch/arm64/core/userspace.S +++ b/arch/arm64/core/userspace.S @@ -51,7 +51,7 @@ strlen_done: ret /* - * int arch_buffer_validate(void *addr, size_t size, int write) + * int arch_buffer_validate(const void *addr, size_t size, int write) */ GTEXT(arch_buffer_validate) diff --git a/arch/riscv/core/pmp.c b/arch/riscv/core/pmp.c index 3807b3b103b2cd..50b5dd58f5d72a 100644 --- a/arch/riscv/core/pmp.c +++ b/arch/riscv/core/pmp.c @@ -667,7 +667,7 @@ int arch_mem_domain_thread_remove(struct k_thread *thread) ((inner_start) >= (outer_start) && (inner_size) <= (outer_size) && \ ((inner_start) - (outer_start)) <= ((outer_size) - (inner_size))) -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { uintptr_t start = (uintptr_t)addr; int ret = -1; diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index 5540cebce7061b..8591e0a8ba4454 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -848,7 +848,7 @@ static inline pentry_t pte_finalize_value(pentry_t val, bool user_table, __pinned_func static inline pentry_t atomic_pte_get(const pentry_t *target) { - return (pentry_t)atomic_ptr_get((atomic_ptr_t *)target); + return (pentry_t)atomic_ptr_get((const atomic_ptr_t *)target); } __pinned_func @@ -1301,7 +1301,7 @@ void arch_mem_unmap(void *addr, size_t size) { int ret; - ret = range_map_unlocked((void *)addr, 0, size, 0, 0, + ret = range_map_unlocked(addr, 0, size, 0, 0, OPTION_FLUSH | OPTION_CLEAR); __ASSERT_NO_MSG(ret == 0); ARG_UNUSED(ret); @@ -1387,7 +1387,7 @@ void z_x86_set_stack_guard(k_thread_stack_t *stack) __pinned_func static bool page_validate(pentry_t *ptables, uint8_t *addr, bool write) { - pentry_t *table = (pentry_t *)ptables; + pentry_t *table = ptables; for (int level = 0; level < NUM_LEVELS; level++) { pentry_t entry = get_entry(table, addr, level); @@ -1432,7 +1432,7 @@ static inline void bcb_fence(void) } __pinned_func -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { pentry_t *ptables = z_x86_thread_page_tables_get(_current); uint8_t *virt; diff --git a/arch/xtensa/core/mpu.c b/arch/xtensa/core/mpu.c index 29e336297717fe..76036b32c705f5 100644 --- a/arch/xtensa/core/mpu.c +++ b/arch/xtensa/core/mpu.c @@ -969,7 +969,7 @@ int arch_mem_domain_thread_remove(struct k_thread *thread) return ret; } -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { uintptr_t aligned_addr; size_t aligned_size, addr_offset; diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index dc33d6fd5f050a..d4da8366cf22f1 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -1044,7 +1044,7 @@ static bool page_validate(uint32_t *ptables, uint32_t page, uint8_t ring, bool w return true; } -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { int ret = 0; uint8_t *virt; diff --git a/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h b/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h index ad36a22eb771ec..8e3e02a67ced1e 100644 --- a/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h +++ b/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h @@ -88,7 +88,7 @@ void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain); void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain, uint32_t partition_id); int arc_core_mpu_get_max_domain_partition_regions(void); -int arc_core_mpu_buffer_validate(void *addr, size_t size, int write); +int arc_core_mpu_buffer_validate(const void *addr, size_t size, int write); #endif diff --git a/include/zephyr/arch/arch_interface.h b/include/zephyr/arch/arch_interface.h index d7ff2f2cad2dbc..04aef8157558b6 100644 --- a/include/zephyr/arch/arch_interface.h +++ b/include/zephyr/arch/arch_interface.h @@ -783,7 +783,7 @@ int arch_mem_domain_partition_add(struct k_mem_domain *domain, * * @return nonzero if the permissions don't match. */ -int arch_buffer_validate(void *addr, size_t size, int write); +int arch_buffer_validate(const void *addr, size_t size, int write); /** * Get the optimal virtual region alignment to optimize the MMU table layout From 79e309e0664b37b36e468b168aee7ad4005cae79 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0389/1389] llext: add a multi-file test case Add a case, testing building an llext from multiple files, calling functions and accessing data across files. Signed-off-by: Guennadi Liakhovetski --- tests/subsys/llext/simple/CMakeLists.txt | 10 +++++++ .../subsys/llext/simple/src/multi_file_ext1.c | 30 +++++++++++++++++++ .../subsys/llext/simple/src/multi_file_ext2.c | 15 ++++++++++ .../llext/simple/src/test_llext_simple.c | 7 +++++ 4 files changed, 62 insertions(+) create mode 100644 tests/subsys/llext/simple/src/multi_file_ext1.c create mode 100644 tests/subsys/llext/simple/src/multi_file_ext2.c diff --git a/tests/subsys/llext/simple/CMakeLists.txt b/tests/subsys/llext/simple/CMakeLists.txt index 92ddab5258e8de..2a677470f66669 100644 --- a/tests/subsys/llext/simple/CMakeLists.txt +++ b/tests/subsys/llext/simple/CMakeLists.txt @@ -35,6 +35,16 @@ foreach(ext_name ${ext_names}) generate_inc_file_for_target(app ${ext_bin} ${ext_inc}) endforeach() +if(NOT CONFIG_LLEXT_TYPE_ELF_OBJECT) + add_llext_target(multi_file_ext + OUTPUT ${ZEPHYR_BINARY_DIR}/multi_file.llext + SOURCES ${PROJECT_SOURCE_DIR}/src/multi_file_ext1.c ${PROJECT_SOURCE_DIR}/src/multi_file_ext2.c + ) + generate_inc_file_for_target(app ${ZEPHYR_BINARY_DIR}/multi_file.llext + ${ZEPHYR_BINARY_DIR}/include/generated/multi_file.inc + ) +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) diff --git a/tests/subsys/llext/simple/src/multi_file_ext1.c b/tests/subsys/llext/simple/src/multi_file_ext1.c new file mode 100644 index 00000000000000..018c11af6faa06 --- /dev/null +++ b/tests/subsys/llext/simple/src/multi_file_ext1.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This code demonstrates multi-file object and function linking support. + */ + +#include +#include +#include + +/* Test non-static global object relocation */ +int number = 0x42; +extern int ext_number; +int ext_sum_fn(int arg); + +void test_entry(void) +{ + printk("initial: local %d plus external %d equals %d\n", + number, ext_number, ext_sum_fn(ext_number)); + number ^= ext_number; + ext_number ^= number; + number ^= ext_number; + printk("updated: local %d plus external %d equals %d\n", + number, ext_number, ext_sum_fn(ext_number)); +} +LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/multi_file_ext2.c b/tests/subsys/llext/simple/src/multi_file_ext2.c new file mode 100644 index 00000000000000..e9ed12997bc770 --- /dev/null +++ b/tests/subsys/llext/simple/src/multi_file_ext2.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* File 2 of the multi-file linking test */ + +extern int number; +int ext_number = 0x18; + +int ext_sum_fn(int arg) +{ + return arg + number; +} diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 2833caa2ad031f..f5e608d891285c 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -230,6 +230,13 @@ static LLEXT_CONST uint8_t threads_kernel_objects_ext[] __aligned(4) = { LLEXT_LOAD_UNLOAD(threads_kernel_objects, true, threads_objects_perm_setup) #endif +#ifndef CONFIG_LLEXT_TYPE_ELF_OBJECT +static LLEXT_CONST uint8_t multi_file_ext[] __aligned(4) = { + #include "multi_file.inc" +}; +LLEXT_LOAD_UNLOAD(multi_file, true, NULL) +#endif + /* * Ensure that EXPORT_SYMBOL does indeed provide a symbol and a valid address From 101aa30cd397275ab1a76221cdf6cd18c69d038f Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0390/1389] drivers: bluetooth: hci: Fix int conversion warning Fix int conversion warning (-Wint-conversion), which is caused by parallel PRs. Signed-off-by: Ali Hozhabri --- drivers/bluetooth/hci/hci_spi_st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/hci/hci_spi_st.c b/drivers/bluetooth/hci/hci_spi_st.c index 8da9936888eef0..d45dbb592a1e8a 100644 --- a/drivers/bluetooth/hci/hci_spi_st.c +++ b/drivers/bluetooth/hci/hci_spi_st.c @@ -435,12 +435,12 @@ static int bt_spi_rx_buf_construct(uint8_t *msg, struct net_buf **bufp, uint16_t len = sizeof(iso_hdr) + bt_iso_hdr_len(sys_le16_to_cpu(iso_hdr.len)); } else { LOG_ERR("No available ISO buffers!"); - return NULL; + return -ENOMEM; } if (len > net_buf_tailroom(buf)) { LOG_ERR("ISO too long: %d", len); net_buf_unref(buf); - return NULL; + return -ENOMEM; } net_buf_add_mem(buf, &msg[1], len); break; From 34801d82a8cf429a93e2bdbe7184c675b2c17067 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0391/1389] drivers: counter: stm32_rtc: fix clk disable for WBAX clock_control_on() was called instead of clock_control_off(). Signed-off-by: Abderrahmane Jarmouni --- drivers/counter/counter_ll_stm32_rtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/counter/counter_ll_stm32_rtc.c b/drivers/counter/counter_ll_stm32_rtc.c index 128586a4a0a43c..cab26b1eeeab82 100644 --- a/drivers/counter/counter_ll_stm32_rtc.c +++ b/drivers/counter/counter_ll_stm32_rtc.c @@ -191,7 +191,7 @@ static int rtc_stm32_start(const struct device *dev) /* Enable RTC bus clock */ if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { - LOG_ERR("clock op failed\n"); + LOG_ERR("RTC clock enabling failed\n"); return -EIO; } #else @@ -212,9 +212,9 @@ static int rtc_stm32_stop(const struct device *dev) const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); const struct rtc_stm32_config *cfg = dev->config; - /* Enable RTC bus clock */ - if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { - LOG_ERR("clock op failed\n"); + /* Disable RTC bus clock */ + if (clock_control_off(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { + LOG_ERR("RTC clock disabling failed\n"); return -EIO; } #else From a07a65a20b834d928dbaaee50c9a49732f55e5f9 Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0392/1389] drivers: regulator: shell: print all 6-digits of micro values Previously only the upper/first 3 digits of a micro value would be printed, dropping the last 3 digits. This could cause misleading output for cmds like vlist. Signed-off-by: Mike J. Chen --- drivers/regulator/regulator_shell.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/regulator/regulator_shell.c b/drivers/regulator/regulator_shell.c index f9d61431cc9668..508a029790faa3 100644 --- a/drivers/regulator/regulator_shell.c +++ b/drivers/regulator/regulator_shell.c @@ -74,8 +74,7 @@ static int strtomicro(char *inp, char units, int32_t *val) static void microtoshell(const struct shell *sh, char unit, int32_t val) { if (val > 100000) { - shell_print(sh, "%d.%03d %c", val / 1000000, - (val % 1000000) / 1000, unit); + shell_print(sh, "%d.%06d %c", val / 1000000, val % 1000000, unit); } else if (val > 1000) { shell_print(sh, "%d.%03d m%c", val / 1000, val % 1000, unit); } else { From 21ef2902197d494ab7b7f63e44c20b9de5ba2c0d Mon Sep 17 00:00:00 2001 From: Sateesh Kotapati Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0393/1389] boards: silabs: Added support for Counter and Watchdog Added the support for counter and watchdog in efr32xg24_dk2601b board. Signed-off-by: Sateesh Kotapati --- boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts | 5 +++++ boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml | 2 ++ west.yml | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts index 3617191ed5b2cf..ffa883da6f9e60 100644 --- a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts +++ b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts @@ -27,6 +27,7 @@ led2 = &blue_led; sw0 = &button0; sw1 = &button1; + watchdog0 = &wdog0; }; leds { @@ -172,3 +173,7 @@ &adc0 { status = "okay"; }; + +&stimer0 { + status = "okay"; +}; diff --git a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml index 2b803cca1abb02..522d945ce5afcb 100644 --- a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml +++ b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml @@ -8,8 +8,10 @@ toolchain: - zephyr - gnuarmemb supported: + - counter - gpio - uart + - watchdog testing: ignore_tags: - net diff --git a/west.yml b/west.yml index 3df717bf0e5ff8..94d555e9f169cb 100644 --- a/west.yml +++ b/west.yml @@ -219,7 +219,7 @@ manifest: groups: - hal - name: hal_silabs - revision: 442d0fb1d02cc4b2bb159fbff378029998b89049 + revision: 0c39ee28be31c59a98ed490c3811f68caa1fcbd3 path: modules/hal/silabs groups: - hal From dc0dba926ab88c2e3693e278e15af80f5f12ae01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0394/1389] drivers: wdt: nrf: Add WDT instances that exist in nrf54h20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add WDT instances no. 010, 011, 131, 132. Signed-off-by: Sebastian Głąb --- .../nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + .../nrf54h20dk_nrf54h20_cpurad.yaml | 1 + drivers/watchdog/Kconfig.nrfx | 4 +++ drivers/watchdog/wdt_nrfx.c | 16 +++++++++++ dts/arm/nordic/nrf54h20_cpuapp.dtsi | 2 ++ dts/arm/nordic/nrf54h20_cpurad.dtsi | 2 ++ dts/common/nordic/nrf54h20.dtsi | 28 +++++++++++++++++++ modules/hal_nordic/nrfx/Kconfig | 10 +++++++ modules/hal_nordic/nrfx/nrfx_config.h | 6 ++++ soc/nordic/common/Kconfig.peripherals | 6 ++++ soc/nordic/validate_base_addresses.c | 4 +++ 11 files changed, 80 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 6ecde2cfdb1033..107aa0be67f41a 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -14,3 +14,4 @@ flash: 512 supported: - gpio - pwm + - watchdog diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml index b199f65385f3fb..32375faf481cf2 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml @@ -14,3 +14,4 @@ flash: 256 supported: - gpio - pwm + - watchdog diff --git a/drivers/watchdog/Kconfig.nrfx b/drivers/watchdog/Kconfig.nrfx index 2967fe8648901e..61f42d8ff3167a 100644 --- a/drivers/watchdog/Kconfig.nrfx +++ b/drivers/watchdog/Kconfig.nrfx @@ -11,7 +11,11 @@ config WDT_NRFX select NRFX_WDT1 if HAS_HW_NRF_WDT1 select NRFX_WDT30 if HAS_HW_NRF_WDT30 select NRFX_WDT31 if HAS_HW_NRF_WDT31 + select NRFX_WDT010 if HAS_HW_NRF_WDT010 + select NRFX_WDT011 if HAS_HW_NRF_WDT011 select NRFX_WDT130 if HAS_HW_NRF_WDT130 + select NRFX_WDT131 if HAS_HW_NRF_WDT131 + select NRFX_WDT132 if HAS_HW_NRF_WDT132 help Enable support for nrfx WDT driver for nRF MCU series. diff --git a/drivers/watchdog/wdt_nrfx.c b/drivers/watchdog/wdt_nrfx.c index 57b4dba828c7fb..706c2621bbb630 100644 --- a/drivers/watchdog/wdt_nrfx.c +++ b/drivers/watchdog/wdt_nrfx.c @@ -220,6 +220,22 @@ WDT_NRFX_WDT_DEVICE(30); WDT_NRFX_WDT_DEVICE(31); #endif +#ifdef CONFIG_HAS_HW_NRF_WDT010 +WDT_NRFX_WDT_DEVICE(010); +#endif + +#ifdef CONFIG_HAS_HW_NRF_WDT011 +WDT_NRFX_WDT_DEVICE(011); +#endif + #ifdef CONFIG_HAS_HW_NRF_WDT130 WDT_NRFX_WDT_DEVICE(130); #endif + +#ifdef CONFIG_HAS_HW_NRF_WDT131 +WDT_NRFX_WDT_DEVICE(131); +#endif + +#ifdef CONFIG_HAS_HW_NRF_WDT132 +WDT_NRFX_WDT_DEVICE(132); +#endif diff --git a/dts/arm/nordic/nrf54h20_cpuapp.dtsi b/dts/arm/nordic/nrf54h20_cpuapp.dtsi index 9d011019f4afe1..1cfa3dddb553a6 100644 --- a/dts/arm/nordic/nrf54h20_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54h20_cpuapp.dtsi @@ -11,6 +11,8 @@ systick: &cpuapp_systick {}; nvic: &cpuapp_nvic {}; cpuppr_vevif: &cpuppr_vevif_remote {}; cpusys_vevif: &cpusys_vevif_remote {}; +wdt010: &cpuapp_wdt010 {}; +wdt011: &cpuapp_wdt011 {}; /delete-node/ &cpuppr; /delete-node/ &cpurad; diff --git a/dts/arm/nordic/nrf54h20_cpurad.dtsi b/dts/arm/nordic/nrf54h20_cpurad.dtsi index 2a62845dc89177..e4a7469dac5530 100644 --- a/dts/arm/nordic/nrf54h20_cpurad.dtsi +++ b/dts/arm/nordic/nrf54h20_cpurad.dtsi @@ -11,6 +11,8 @@ systick: &cpurad_systick {}; nvic: &cpurad_nvic {}; cpuppr_vevif: &cpuppr_vevif_remote {}; cpusys_vevif: &cpusys_vevif_remote {}; +wdt010: &cpurad_wdt010 {}; +wdt011: &cpurad_wdt011 {}; /delete-node/ &cpuapp; /delete-node/ &cpuapp_peripherals; diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 4a4f78bc166128..5671ac699a4cce 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -168,6 +168,20 @@ interrupts = <64 NRF_DEFAULT_IRQ_PRIORITY>, <65 NRF_DEFAULT_IRQ_PRIORITY>; }; + + cpuapp_wdt010: watchdog@14000 { + compatible = "nordic,nrf-wdt"; + reg = <0x14000 0x1000>; + status = "disabled"; + interrupts = <20 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + cpuapp_wdt011: watchdog@15000 { + compatible = "nordic,nrf-wdt"; + reg = <0x15000 0x1000>; + status = "disabled"; + interrupts = <21 NRF_DEFAULT_IRQ_PRIORITY>; + }; }; cpurad_peripherals: peripheral@53000000 { @@ -188,6 +202,20 @@ nordic,ficr-names = "vsup", "coarse", "fine"; }; + cpurad_wdt010: watchdog@13000 { + compatible = "nordic,nrf-wdt"; + reg = <0x13000 0x1000>; + status = "disabled"; + interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + cpurad_wdt011: watchdog@14000 { + compatible = "nordic,nrf-wdt"; + reg = <0x14000 0x1000>; + status = "disabled"; + interrupts = <20 NRF_DEFAULT_IRQ_PRIORITY>; + }; + dppic020: dppic@22000 { compatible = "nordic,nrf-dppic-local"; reg = <0x22000 0x1000>; diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 07c96c55233ef8..549abb138fbecc 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -984,6 +984,16 @@ config NRFX_WDT31 depends on $(dt_nodelabel_has_compat,wdt31,$(DT_COMPAT_NORDIC_NRF_WDT)) select NRFX_WDT +config NRFX_WDT010 + bool "WDT010 driver instance" + depends on $(dt_nodelabel_has_compat,wdt010,$(DT_COMPAT_NORDIC_NRF_WDT)) + select NRFX_WDT + +config NRFX_WDT011 + bool "WDT011 driver instance" + depends on $(dt_nodelabel_has_compat,wdt011,$(DT_COMPAT_NORDIC_NRF_WDT)) + select NRFX_WDT + config NRFX_WDT130 bool "WDT130 driver instance" depends on $(dt_nodelabel_has_compat,wdt130,$(DT_COMPAT_NORDIC_NRF_WDT)) diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 2b9a02845a7c5c..a54866252a5ccd 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -828,6 +828,12 @@ #ifdef CONFIG_NRFX_WDT31 #define NRFX_WDT31_ENABLED 1 #endif +#ifdef CONFIG_NRFX_WDT010 +#define NRFX_WDT010_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_WDT011 +#define NRFX_WDT011_ENABLED 1 +#endif #ifdef CONFIG_NRFX_WDT130 #define NRFX_WDT130_ENABLED 1 #endif diff --git a/soc/nordic/common/Kconfig.peripherals b/soc/nordic/common/Kconfig.peripherals index db6c51568f42ab..a6d730804b824d 100644 --- a/soc/nordic/common/Kconfig.peripherals +++ b/soc/nordic/common/Kconfig.peripherals @@ -642,6 +642,12 @@ config HAS_HW_NRF_WDT30 config HAS_HW_NRF_WDT31 def_bool $(dt_nodelabel_enabled_with_compat,wdt31,$(DT_COMPAT_NORDIC_NRF_WDT)) +config HAS_HW_NRF_WDT010 + def_bool $(dt_nodelabel_enabled_with_compat,wdt010,$(DT_COMPAT_NORDIC_NRF_WDT)) + +config HAS_HW_NRF_WDT011 + def_bool $(dt_nodelabel_enabled_with_compat,wdt011,$(DT_COMPAT_NORDIC_NRF_WDT)) + config HAS_HW_NRF_WDT130 def_bool $(dt_nodelabel_enabled_with_compat,wdt130,$(DT_COMPAT_NORDIC_NRF_WDT)) diff --git a/soc/nordic/validate_base_addresses.c b/soc/nordic/validate_base_addresses.c index f9db3f4db14587..9dfd1e409c89e7 100644 --- a/soc/nordic/validate_base_addresses.c +++ b/soc/nordic/validate_base_addresses.c @@ -321,6 +321,10 @@ CHECK_DT_REG(wdt0, NRF_WDT0); CHECK_DT_REG(wdt1, NRF_WDT1); CHECK_DT_REG(wdt30, NRF_WDT30); CHECK_DT_REG(wdt31, NRF_WDT31); +CHECK_DT_REG(cpuapp_wdt010, NRF_APPLICATION_WDT010); +CHECK_DT_REG(cpuapp_wdt011, NRF_APPLICATION_WDT011); +CHECK_DT_REG(cpurad_wdt010, NRF_RADIOCORE_WDT010); +CHECK_DT_REG(cpurad_wdt011, NRF_RADIOCORE_WDT011); CHECK_DT_REG(wdt131, NRF_WDT131); CHECK_DT_REG(wdt132, NRF_WDT132); From 7803051813424b4ddab511611cd6c243ba379892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0395/1389] tests: drivers: watchdog: wdt_error_cases: Run test on nRF54H20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overaly files for Application and Radio cores. Configure test according to watchdog features available on nRF54H20. Signed-off-by: Sebastian Głąb --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 21 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 21 +++++++++++++++++++ .../watchdog/wdt_error_cases/src/main.c | 2 +- .../watchdog/wdt_error_cases/testcase.yaml | 2 ++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..d540137dadb483 --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt010 { + status = "okay"; +}; + +&wdt011 { + status = "disabled"; +}; + +&wdt131 { + status = "disabled"; +}; + +&wdt132 { + status = "disabled"; +}; diff --git a/tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000000..7793fed2b8e969 --- /dev/null +++ b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt010 { + status = "disabled"; +}; + +&wdt011 { + status = "okay"; +}; + +&wdt131 { + status = "disabled"; +}; + +&wdt132 { + status = "disabled"; +}; diff --git a/tests/drivers/watchdog/wdt_error_cases/src/main.c b/tests/drivers/watchdog/wdt_error_cases/src/main.c index fc453ba3b321c4..65569ad30a4319 100644 --- a/tests/drivers/watchdog/wdt_error_cases/src/main.c +++ b/tests/drivers/watchdog/wdt_error_cases/src/main.c @@ -42,7 +42,7 @@ #define DEFAULT_WINDOW_MIN (0U) /* Align tests to the specific target: */ -#if defined(CONFIG_SOC_NRF54L15) +#if defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54H20) #define WDT_TEST_FLAGS \ (WDT_DISABLE_SUPPORTED | WDT_FLAG_RESET_SOC_SUPPORTED | \ WDT_FLAG_ONLY_ONE_TIMEOUT_VALUE_SUPPORTED | WDT_OPT_PAUSE_IN_SLEEP_SUPPORTED | \ diff --git a/tests/drivers/watchdog/wdt_error_cases/testcase.yaml b/tests/drivers/watchdog/wdt_error_cases/testcase.yaml index c408d2f8f1d2cc..4fdbfaa1a4c2d7 100644 --- a/tests/drivers/watchdog/wdt_error_cases/testcase.yaml +++ b/tests/drivers/watchdog/wdt_error_cases/testcase.yaml @@ -9,5 +9,7 @@ tests: drivers.watchdog.wdt_error_cases: platform_allow: - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad integration_platforms: - nrf54l15pdk/nrf54l15/cpuapp From b00c1d917d07f0770ffc1d550ddbab0534f220a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0396/1389] boards: nordic: nrf54h20dk: Enable SPI driver tests in Twister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SPI to list of supported periperals by nrf54h20 Application and Radio core. This is needed to run following tests in Twister https://github.com/zephyrproject-rtos/zephyr/pull/71677 Signed-off-by: Sebastian Głąb --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 107aa0be67f41a..198f4db403b38a 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -14,4 +14,5 @@ flash: 512 supported: - gpio - pwm + - spi - watchdog diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml index 32375faf481cf2..68d169331ef831 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml @@ -14,4 +14,5 @@ flash: 256 supported: - gpio - pwm + - spi - watchdog From aee7eff0b17612b3cfacffab751ecc24b885c815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:45 +0200 Subject: [PATCH 0397/1389] modules: hal_nordic: request nRF5340 network CPU in 802.15.4 init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The network CPU must be requested explicitly by the 802.15.4 driver for the sharing mechanism to work correctly. Signed-off-by: Jędrzej Ciupis --- .../platform/nrf_802154_spinel_backend_ipc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c b/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c index b2629eef67b767..6df811f6badb6a 100644 --- a/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c +++ b/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c @@ -15,6 +15,10 @@ #include "../../spinel_base/spinel.h" #include "../../src/include/nrf_802154_spinel.h" +#if defined(CONFIG_SOC_NRF5340_CPUAPP) +#include +#endif + #define LOG_LEVEL LOG_LEVEL_INFO #define LOG_MODULE_NAME spinel_ipc_backend LOG_MODULE_REGISTER(LOG_MODULE_NAME); @@ -50,6 +54,10 @@ nrf_802154_ser_err_t nrf_802154_backend_init(void) DEVICE_DT_GET(DT_CHOSEN(nordic_802154_spinel_ipc)); int err; +#if defined(CONFIG_SOC_NRF5340_CPUAPP) + nrf53_cpunet_enable(true); +#endif + err = ipc_service_open_instance(ipc_instance); if (err < 0 && err != -EALREADY) { LOG_ERR("Failed to open IPC instance: %d", err); From 8dd64d6b8a678cc9e082305e0182c10ace63ac1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0398/1389] boards: control the network CPU directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Board initialization code should not use the network CPU management. It acts as a permanent request for the network CPU, which causes its users to be unable to turn it off. Instead, let the board initialization code control the network CPU directly. It sets initial state of the network core but does not have any impact on sharing the network CPU as a resource between its users. Signed-off-by: Jędrzej Ciupis --- .../lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c | 4 ++-- .../nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c | 4 ++-- boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c | 4 ++-- boards/nordic/thingy53/board.c | 4 ++-- boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c | 4 ++-- .../mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c | 4 ++-- .../mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c b/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c index c4f39467314347..49c0e5a1c730e0 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c +++ b/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c @@ -10,7 +10,7 @@ #include #include -#include +#include LOG_MODULE_REGISTER(bl5340_dvk_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -50,7 +50,7 @@ static int remoteproc_mgr_boot(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c index 3d08a5dd4cd6f8..f9082e6ca4006d 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include LOG_MODULE_REGISTER(nrf5340_audio_dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -71,7 +71,7 @@ static int remoteproc_mgr_boot(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c b/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c index 3b85d55dfd071c..dadba8c0f54a87 100644 --- a/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c +++ b/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c @@ -9,7 +9,7 @@ #include #include -#include +#include LOG_MODULE_REGISTER(nrf5340dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -49,7 +49,7 @@ static int remoteproc_mgr_boot(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/nordic/thingy53/board.c b/boards/nordic/thingy53/board.c index 491808f236a22c..67059bd4ee895f 100644 --- a/boards/nordic/thingy53/board.c +++ b/boards/nordic/thingy53/board.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include LOG_MODULE_REGISTER(thingy53_board_init); @@ -52,7 +52,7 @@ static void enable_cpunet(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c b/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c index cd8281cb2bf25a..bf0626ce30b2ec 100644 --- a/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c +++ b/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c @@ -9,7 +9,7 @@ #include #include -#include +#include #if defined(CONFIG_BOARD_PAN1783_EVB_NRF5340_CPUAPP) LOG_MODULE_REGISTER(pan1783_evb_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -42,7 +42,7 @@ static int remoteproc_mgr_boot(void) remoteproc_mgr_config(); /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c index 64e335869fb596..9596b3453be205 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c @@ -10,7 +10,7 @@ #include #include -#include +#include LOG_MODULE_REGISTER(raytac_mdbt53_db_40_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -50,7 +50,7 @@ static int remoteproc_mgr_boot(const struct device *dev) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c b/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c index ec4567274c40d1..31b8bf5a75e5a0 100644 --- a/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c +++ b/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c @@ -49,7 +49,7 @@ static int remoteproc_mgr_boot(const struct device *dev) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ From d6d5b8a13869d8227c43c70ec95aa29ea76eb4c1 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0399/1389] arch: x86: avoided increments/decrements with side effects - moved ++/-- before or after the value use Signed-off-by: frei tycho --- arch/x86/zefi/printf.h | 16 +++++++++++----- arch/x86/zefi/zefi.c | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/x86/zefi/printf.h b/arch/x86/zefi/printf.h index f90a54ec3fb315..a3960064029b50 100644 --- a/arch/x86/zefi/printf.h +++ b/arch/x86/zefi/printf.h @@ -45,14 +45,18 @@ static void prdec(struct _pfr *r, long v) char digs[11 * sizeof(long)/4]; int i = sizeof(digs) - 1; - digs[i--] = 0; + digs[i] = 0; + --i; while (v || i == 9) { - digs[i--] = '0' + (v % 10); + digs[i] = '0' + (v % 10); + --i; v /= 10; } - while (digs[++i] != '\0') { + ++i; + while (digs[i] != '\0') { pc(r, digs[i]); + ++i; } } @@ -101,8 +105,10 @@ static int vpf(struct _pfr *r, const char *f, va_list ap) case 's': { char *s = va_arg(ap, char *); - while (*s != '\0') - pc(r, *s++); + while (*s != '\0') { + pc(r, *s); + ++s; + } break; } case 'p': diff --git a/arch/x86/zefi/zefi.c b/arch/x86/zefi/zefi.c index 015a6ff50a26e7..56d0701e79bb05 100644 --- a/arch/x86/zefi/zefi.c +++ b/arch/x86/zefi/zefi.c @@ -56,7 +56,8 @@ static void efi_putchar(int c) efi_putchar('\r'); } - efibuf[n++] = c; + efibuf[n] = c; + ++n; if (c == '\n' || n == PUTCHAR_BUFSZ) { efibuf[n] = 0U; From 797fdbaa995d4ef6847ee21f20a7bbd820900093 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0400/1389] drivers: gnss: Add emulated GNSS device driver The emulated GNSS driver behaves like a GNSS, implementing device pm and the GNSS APIs, using only kernel features ( zephyr work queue and uptime) making it buildable on all zephyr targets. The purpose of this device driver is to tailor and validate the gnss api test suite. Signed-off-by: Bjarki Arge Andreasen --- drivers/gnss/CMakeLists.txt | 1 + drivers/gnss/Kconfig | 1 + drivers/gnss/Kconfig.emul | 10 + drivers/gnss/gnss_emul.c | 510 ++++++++++++++++++++++++ dts/bindings/gnss/zephyr,gnss-emul.yaml | 6 + 5 files changed, 528 insertions(+) create mode 100644 drivers/gnss/Kconfig.emul create mode 100644 drivers/gnss/gnss_emul.c create mode 100644 dts/bindings/gnss/zephyr,gnss-emul.yaml diff --git a/drivers/gnss/CMakeLists.txt b/drivers/gnss/CMakeLists.txt index 77631bcb9710ad..05192ca5400ebf 100644 --- a/drivers/gnss/CMakeLists.txt +++ b/drivers/gnss/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_library_sources(gnss_publish.c) zephyr_library_sources_ifdef(CONFIG_GNSS_DUMP gnss_dump.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_EMUL gnss_emul.c) zephyr_library_sources_ifdef(CONFIG_GNSS_PARSE gnss_parse.c) zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA0183 gnss_nmea0183.c) zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA0183_MATCH gnss_nmea0183_match.c) diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig index 98602d4194997f..94aaf7a02ba84b 100644 --- a/drivers/gnss/Kconfig +++ b/drivers/gnss/Kconfig @@ -70,6 +70,7 @@ module = GNSS module-str = gnss source "subsys/logging/Kconfig.template.log_config" +rsource "Kconfig.emul" rsource "Kconfig.generic" rsource "Kconfig.quectel_lcx6g" rsource "Kconfig.u_blox_m10" diff --git a/drivers/gnss/Kconfig.emul b/drivers/gnss/Kconfig.emul new file mode 100644 index 00000000000000..9ae9a406472844 --- /dev/null +++ b/drivers/gnss/Kconfig.emul @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +config GNSS_EMUL + bool "Emulated GNSS driver" + default y + depends on DT_HAS_ZEPHYR_GNSS_EMUL_ENABLED + select TIMEOUT_64BIT + help + Enable emulated GNSS driver. diff --git a/drivers/gnss/gnss_emul.c b/drivers/gnss/gnss_emul.c new file mode 100644 index 00000000000000..553736f0ba7217 --- /dev/null +++ b/drivers/gnss/gnss_emul.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L /* Required for gmtime_r */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(gnss_emul, CONFIG_GNSS_LOG_LEVEL); + +#define DT_DRV_COMPAT zephyr_gnss_emul + +#define GNSS_EMUL_DEFAULT_FIX_INTERVAL_MS 1000 +#define GNSS_EMUL_MIN_FIX_INTERVAL_MS 100 +#define GNSS_EMUL_FIX_ACQUIRE_TIME_MS 5000 +#define GNSS_EMUL_DEFAULT_NAV_MODE GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS +#define GNSS_EMUL_SUPPORTED_SYSTEMS_MASK 0xFF +#define GNSS_EMUL_SUPPORTED_SYSTEMS_COUNT 8 +#define GNSS_EMUL_DEFAULT_ENABLED_SYSTEMS_MASK GNSS_EMUL_SUPPORTED_SYSTEMS_MASK + +struct gnss_emul_data { + const struct device *dev; + struct k_work_delayable data_dwork; + struct k_sem lock; + int64_t resume_timestamp_ms; + int64_t fix_timestamp_ms; + uint32_t fix_interval_ms; + enum gnss_navigation_mode nav_mode; + gnss_systems_t enabled_systems; + struct gnss_data data; + +#ifdef CONFIG_GNSS_SATELLITES + struct gnss_satellite satellites[GNSS_EMUL_SUPPORTED_SYSTEMS_COUNT]; + uint8_t satellites_len; +#endif +}; + +static void gnss_emul_lock_sem(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + (void)k_sem_take(&data->lock, K_FOREVER); +} + +static void gnss_emul_unlock_sem(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + k_sem_give(&data->lock); +} + +static void gnss_emul_update_fix_timestamp(const struct device *dev, bool resuming) +{ + struct gnss_emul_data *data = dev->data; + int64_t uptime_ms; + + uptime_ms = k_uptime_get(); + data->fix_timestamp_ms = ((uptime_ms / data->fix_interval_ms) + 1) * data->fix_interval_ms; + + if (resuming) { + data->resume_timestamp_ms = data->fix_timestamp_ms; + } +} + +static bool gnss_emul_fix_is_acquired(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + int64_t time_since_resume; + + time_since_resume = data->fix_timestamp_ms - data->resume_timestamp_ms; + return time_since_resume >= GNSS_EMUL_FIX_ACQUIRE_TIME_MS; +} + +#ifdef CONFIG_PM_DEVICE +static void gnss_emul_clear_fix_timestamp(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->fix_timestamp_ms = 0; +} +#endif + +static void gnss_emul_schedule_work(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + k_work_schedule(&data->data_dwork, K_TIMEOUT_ABS_MS(data->fix_timestamp_ms)); +} + +static bool gnss_emul_cancel_work(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + struct k_work_sync sync; + + return k_work_cancel_delayable_sync(&data->data_dwork, &sync); +} + +static bool gnss_emul_is_resumed(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + return data->fix_timestamp_ms > 0; +} + +static void gnss_emul_lock(const struct device *dev) +{ + gnss_emul_lock_sem(dev); + gnss_emul_cancel_work(dev); +} + +static void gnss_emul_unlock(const struct device *dev) +{ + if (gnss_emul_is_resumed(dev)) { + gnss_emul_schedule_work(dev); + } + + gnss_emul_unlock_sem(dev); +} + +static int gnss_emul_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + struct gnss_emul_data *data = dev->data; + + if (fix_interval_ms < GNSS_EMUL_MIN_FIX_INTERVAL_MS) { + return -EINVAL; + } + + data->fix_interval_ms = fix_interval_ms; + return 0; +} + +static int gnss_emul_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + struct gnss_emul_data *data = dev->data; + + *fix_interval_ms = data->fix_interval_ms; + return 0; +} + +static int gnss_emul_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + struct gnss_emul_data *data = dev->data; + + if (mode > GNSS_NAVIGATION_MODE_HIGH_DYNAMICS) { + return -EINVAL; + } + + data->nav_mode = mode; + return 0; +} + +static int gnss_emul_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + struct gnss_emul_data *data = dev->data; + + *mode = data->nav_mode; + return 0; +} + +static int gnss_emul_set_enabled_systems(const struct device *dev, gnss_systems_t systems) +{ + struct gnss_emul_data *data = dev->data; + + if (systems > GNSS_EMUL_SUPPORTED_SYSTEMS_MASK) { + return -EINVAL; + } + + data->enabled_systems = systems; + return 0; +} + +static int gnss_emul_get_enabled_systems(const struct device *dev, gnss_systems_t *systems) +{ + struct gnss_emul_data *data = dev->data; + + *systems = data->enabled_systems; + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static void gnss_emul_resume(const struct device *dev) +{ + gnss_emul_update_fix_timestamp(dev, true); +} + +static void gnss_emul_suspend(const struct device *dev) +{ + gnss_emul_clear_fix_timestamp(dev); +} + +static int gnss_emul_pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret = 0; + + gnss_emul_lock(dev); + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + gnss_emul_suspend(dev); + break; + + case PM_DEVICE_ACTION_RESUME: + gnss_emul_resume(dev); + break; + + default: + ret = -ENOTSUP; + break; + } + + gnss_emul_unlock(dev); + return ret; +} +#endif + +static int gnss_emul_api_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_set_fix_rate(dev, fix_interval_ms); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_get_fix_rate(dev, fix_interval_ms); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_set_navigation_mode(dev, mode); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_get_navigation_mode(dev, mode); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_set_enabled_systems(const struct device *dev, gnss_systems_t systems) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_set_enabled_systems(dev, systems); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_enabled_systems(const struct device *dev, gnss_systems_t *systems) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_get_enabled_systems(dev, systems); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_supported_systems(const struct device *dev, gnss_systems_t *systems) +{ + *systems = GNSS_EMUL_SUPPORTED_SYSTEMS_MASK; + return 0; +} + +static struct gnss_driver_api api = { + .set_fix_rate = gnss_emul_api_set_fix_rate, + .get_fix_rate = gnss_emul_api_get_fix_rate, + .set_navigation_mode = gnss_emul_api_set_navigation_mode, + .get_navigation_mode = gnss_emul_api_get_navigation_mode, + .set_enabled_systems = gnss_emul_api_set_enabled_systems, + .get_enabled_systems = gnss_emul_api_get_enabled_systems, + .get_supported_systems = gnss_emul_api_get_supported_systems, +}; + +static void gnss_emul_clear_data(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + memset(&data->data, 0, sizeof(data->data)); +} + +static void gnss_emul_set_fix(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->data.info.satellites_cnt = 8; + data->data.info.hdop = 100; + data->data.info.fix_status = GNSS_FIX_STATUS_GNSS_FIX; + data->data.info.fix_quality = GNSS_FIX_QUALITY_GNSS_SPS; +} + +static void gnss_emul_set_utc(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + time_t timestamp; + struct tm datetime; + uint16_t millisecond; + + timestamp = (time_t)(data->fix_timestamp_ms / 1000); + gmtime_r(×tamp, &datetime); + + millisecond = (uint16_t)(data->fix_timestamp_ms % 1000) + + (uint16_t)(datetime.tm_sec * 1000); + + data->data.utc.hour = datetime.tm_hour; + data->data.utc.millisecond = millisecond; + data->data.utc.minute = datetime.tm_min; + data->data.utc.month = datetime.tm_mon + 1; + data->data.utc.century_year = datetime.tm_year % 100; +} + +static void gnss_emul_set_nav_data(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->data.nav_data.latitude = 10000000000; + data->data.nav_data.longitude = -10000000000; + data->data.nav_data.bearing = 3000; + data->data.nav_data.speed = 0; + data->data.nav_data.altitude = 20000; +} + +#ifdef CONFIG_GNSS_SATELLITES +static void gnss_emul_clear_satellites(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->satellites_len = 0; +} + +static bool gnss_emul_system_enabled(const struct device *dev, uint8_t system_bit) +{ + struct gnss_emul_data *data = dev->data; + + return BIT(system_bit) & data->enabled_systems; +} + +static void gnss_emul_add_satellite(const struct device *dev, uint8_t system_bit) +{ + struct gnss_emul_data *data = dev->data; + + /* Unique values synthesized from GNSS system */ + data->satellites[data->satellites_len].prn = system_bit; + data->satellites[data->satellites_len].snr = system_bit + 20; + data->satellites[data->satellites_len].elevation = system_bit + 40; + data->satellites[data->satellites_len].azimuth = system_bit + 60; + data->satellites[data->satellites_len].system = BIT(system_bit); + data->satellites[data->satellites_len].is_tracked = true; + data->satellites_len++; +} + +static void gnss_emul_set_satellites(const struct device *dev) +{ + gnss_emul_clear_satellites(dev); + + for (uint8_t i = 0; i < GNSS_EMUL_SUPPORTED_SYSTEMS_COUNT; i++) { + if (!gnss_emul_system_enabled(dev, i)) { + continue; + } + + gnss_emul_add_satellite(dev, i); + } +} +#endif + +static void gnss_emul_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct gnss_emul_data *data = CONTAINER_OF(dwork, struct gnss_emul_data, data_dwork); + const struct device *dev = data->dev; + + if (!gnss_emul_fix_is_acquired(dev)) { + gnss_emul_clear_data(dev); + } else { + gnss_emul_set_fix(dev); + gnss_emul_set_utc(dev); + gnss_emul_set_nav_data(dev); + } + + gnss_publish_data(dev, &data->data); + +#ifdef CONFIG_GNSS_SATELLITES + gnss_emul_set_satellites(dev); + gnss_publish_satellites(dev, data->satellites, data->satellites_len); +#endif + + gnss_emul_update_fix_timestamp(dev, false); + gnss_emul_schedule_work(dev); +} + +static void gnss_emul_init_data(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->dev = dev; + k_sem_init(&data->lock, 1, 1); + k_work_init_delayable(&data->data_dwork, gnss_emul_work_handler); +} + +static int gnss_emul_init(const struct device *dev) +{ + gnss_emul_init_data(dev); + + if (pm_device_is_powered(dev)) { + gnss_emul_update_fix_timestamp(dev, true); + gnss_emul_schedule_work(dev); + } else { + pm_device_init_off(dev); + } + + return pm_device_runtime_enable(dev); +} + +#define GNSS_EMUL_NAME(inst, name) _CONCAT(name, inst) + +#define GNSS_EMUL_DEVICE(inst) \ + static struct gnss_emul_data GNSS_EMUL_NAME(inst, data) = { \ + .fix_interval_ms = GNSS_EMUL_DEFAULT_FIX_INTERVAL_MS, \ + .nav_mode = GNSS_EMUL_DEFAULT_NAV_MODE, \ + .enabled_systems = GNSS_EMUL_DEFAULT_ENABLED_SYSTEMS_MASK, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, gnss_emul_pm_action); \ + \ + DEVICE_DT_INST_DEFINE( \ + inst, \ + gnss_emul_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &GNSS_EMUL_NAME(inst, data), \ + NULL, \ + POST_KERNEL, \ + CONFIG_GNSS_INIT_PRIORITY, \ + &api \ + ); + +DT_INST_FOREACH_STATUS_OKAY(GNSS_EMUL_DEVICE) diff --git a/dts/bindings/gnss/zephyr,gnss-emul.yaml b/dts/bindings/gnss/zephyr,gnss-emul.yaml new file mode 100644 index 00000000000000..eb7d9eec8acc31 --- /dev/null +++ b/dts/bindings/gnss/zephyr,gnss-emul.yaml @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Zephyr emulated GNSS device + +compatible: "zephyr,gnss-emul" From a57ba29c0c6d51cfb5f4b003c714b3c5f97fd404 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0401/1389] tests: drivers: gnss: Add GNSS API test suite Add GNSS API test suite validating the behavior of a GNSS device adheres to the GNSS API. Signed-off-by: Bjarki Arge Andreasen --- tests/drivers/gnss/gnss_api/CMakeLists.txt | 15 ++ tests/drivers/gnss/gnss_api/Kconfig | 32 ++++ tests/drivers/gnss/gnss_api/prj.conf | 6 + .../gnss/gnss_api/src/test_enabled_systems.c | 147 ++++++++++++++++++ .../drivers/gnss/gnss_api/src/test_fix_rate.c | 88 +++++++++++ .../gnss/gnss_api/src/test_navigation_mode.c | 60 +++++++ tests/drivers/gnss/gnss_api/src/test_suite.c | 9 ++ tests/drivers/gnss/gnss_api/testcase.yaml | 7 + 8 files changed, 364 insertions(+) create mode 100644 tests/drivers/gnss/gnss_api/CMakeLists.txt create mode 100644 tests/drivers/gnss/gnss_api/Kconfig create mode 100644 tests/drivers/gnss/gnss_api/prj.conf create mode 100644 tests/drivers/gnss/gnss_api/src/test_enabled_systems.c create mode 100644 tests/drivers/gnss/gnss_api/src/test_fix_rate.c create mode 100644 tests/drivers/gnss/gnss_api/src/test_navigation_mode.c create mode 100644 tests/drivers/gnss/gnss_api/src/test_suite.c create mode 100644 tests/drivers/gnss/gnss_api/testcase.yaml diff --git a/tests/drivers/gnss/gnss_api/CMakeLists.txt b/tests/drivers/gnss/gnss_api/CMakeLists.txt new file mode 100644 index 00000000000000..50762c41059387 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(gnss_api) + +target_sources(app PRIVATE + src/test_enabled_systems.c + src/test_fix_rate.c + src/test_navigation_mode.c + src/test_suite.c +) diff --git a/tests/drivers/gnss/gnss_api/Kconfig b/tests/drivers/gnss/gnss_api/Kconfig new file mode 100644 index 00000000000000..34238dcdf71cf7 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/Kconfig @@ -0,0 +1,32 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +source "Kconfig.zephyr" + +config TEST_ENABLED_SYSTEMS_0 + int "Enabled systems configuration 0" + range 0 255 + default 0 + +config TEST_ENABLED_SYSTEMS_1 + int "Enabled systems configuration 1" + range 0 255 + default 0 + +config TEST_ENABLED_SYSTEMS_2 + int "Enabled systems configuration 2" + range 0 255 + default 0 + +config TEST_ENABLED_SYSTEMS_3 + int "Enabled systems configuration 3" + range 0 255 + default 0 + +config TEST_SEARCH_PERIOD + int "Search period for satellites in seconds" + default 60 + +config TEST_FIX_TIMEOUT + int "Timeout waiting for a fix in seconds" + default 60 diff --git a/tests/drivers/gnss/gnss_api/prj.conf b/tests/drivers/gnss/gnss_api/prj.conf new file mode 100644 index 00000000000000..bfb63abec375d2 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/prj.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS=y +CONFIG_ZTEST=y +CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/drivers/gnss/gnss_api/src/test_enabled_systems.c b/tests/drivers/gnss/gnss_api/src/test_enabled_systems.c new file mode 100644 index 00000000000000..246e94631a80fc --- /dev/null +++ b/tests/drivers/gnss/gnss_api/src/test_enabled_systems.c @@ -0,0 +1,147 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define TEST_SEARCH_PERIOD K_SECONDS(CONFIG_TEST_SEARCH_PERIOD) + +static const struct device *dev = DEVICE_DT_GET(DT_ALIAS(gnss)); +static const gnss_systems_t enabled_systems_array[] = { + CONFIG_TEST_ENABLED_SYSTEMS_0, + CONFIG_TEST_ENABLED_SYSTEMS_1, + CONFIG_TEST_ENABLED_SYSTEMS_2, + CONFIG_TEST_ENABLED_SYSTEMS_3, +}; + +static bool test_reported_are_expected(gnss_systems_t reported, gnss_systems_t expected) +{ + return ((~expected) & reported) == 0; +} + +static void test_set_enabled_systems(gnss_systems_t enabled_systems) +{ + int ret; + + ret = gnss_set_enabled_systems(dev, enabled_systems); + zassert_ok(ret, "failed to set enabled systems (%i)", ret); +} + +static void test_get_system_enabled(gnss_systems_t expected_systems) +{ + int ret; + gnss_systems_t enabled_systems; + + ret = gnss_get_enabled_systems(dev, &enabled_systems); + if (ret == -ENOSYS) { + return; + } + zassert_ok(ret, "failed to get enabled systems (%i)", ret); + + zassert_equal(enabled_systems, expected_systems, + "invalid enabled systems (%u != %u)", + enabled_systems, expected_systems); +} + +#ifdef CONFIG_GNSS_SATELLITES +static atomic_t reported_systems_atom = ATOMIC_INIT(0); + +static void gnss_satellites_cb(const struct device *dev, + const struct gnss_satellite *satellites, + uint16_t size) +{ + for (uint16_t i = 0; i < size; i++) { + atomic_or(&reported_systems_atom, satellites[i].system); + } +} + +GNSS_SATELLITES_CALLBACK_DEFINE(DEVICE_DT_GET(DT_ALIAS(gnss)), gnss_satellites_cb); + +static void test_validate_satellites(gnss_systems_t expected_systems) +{ + gnss_systems_t reported_systems; + bool expected; + + atomic_set(&reported_systems_atom, 0); + PRINT("searching with enabled system %u\n", expected_systems); + k_sleep(TEST_SEARCH_PERIOD); + + reported_systems = atomic_get(&reported_systems_atom); + if (reported_systems == 0) { + PRINT("found no satellites\n"); + } else { + PRINT("found satellites\n"); + } + + expected = test_reported_are_expected(reported_systems, expected_systems); + zassert_true(expected, "unexpected systems reported (%u != %u)", + reported_systems, expected_systems); +} +#endif + +static void test_validate_enabled_systems(void) +{ + gnss_systems_t enabled_systems; + + for (uint8_t i = 0; i < ARRAY_SIZE(enabled_systems_array); i++) { + enabled_systems = enabled_systems_array[i]; + if (enabled_systems == 0) { + continue; + } + + test_set_enabled_systems(enabled_systems); + test_get_system_enabled(enabled_systems); +#ifdef CONFIG_GNSS_SATELLITES + test_validate_satellites(enabled_systems); +#endif + } +} + +static bool test_all_enabled_systems_are_disabled(void) +{ + gnss_systems_t enabled_systems; + + for (uint8_t i = 0; i < ARRAY_SIZE(enabled_systems_array); i++) { + enabled_systems = enabled_systems_array[i]; + if (enabled_systems != 0) { + return false; + } + } + + return true; +} + +static void test_validate_supported_systems(void) +{ + gnss_systems_t supported_systems; + int ret; + gnss_systems_t enabled_systems; + bool supported; + + ret = gnss_get_supported_systems(dev, &supported_systems); + if (ret == -ENOSYS) { + return; + } + zassert_ok(ret, "failed to get supported systems (%i)", ret); + + for (uint8_t i = 0; i < ARRAY_SIZE(enabled_systems_array); i++) { + enabled_systems = enabled_systems_array[0]; + supported = test_reported_are_expected(enabled_systems, supported_systems); + zassert_true(supported, "enabled systems %u is not supported", i); + } +} + +ZTEST(gnss_api, test_enabled_systems) +{ + if (test_all_enabled_systems_are_disabled()) { + ztest_test_skip(); + } + + test_validate_supported_systems(); + test_validate_enabled_systems(); +} diff --git a/tests/drivers/gnss/gnss_api/src/test_fix_rate.c b/tests/drivers/gnss/gnss_api/src/test_fix_rate.c new file mode 100644 index 00000000000000..35ceec38dc3bba --- /dev/null +++ b/tests/drivers/gnss/gnss_api/src/test_fix_rate.c @@ -0,0 +1,88 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define TEST_VALIDATE_PERIOD_MS 10000 +#define TEST_VALIDATE_PERIOD K_MSEC(TEST_VALIDATE_PERIOD_MS) + +#define TEST_MIN_CALLBACK_COUNT(_fix_interval) \ + (((TEST_VALIDATE_PERIOD_MS / _fix_interval) / 5) * 4) + +#define TEST_MAX_CALLBACK_COUNT(_fix_interval) \ + (((TEST_VALIDATE_PERIOD_MS / _fix_interval) / 5) * 6) + +#define TEST_CONFIG_DEFINE(_fix_interval) \ + { \ + .fix_interval = _fix_interval, \ + .min_callback_count = TEST_MIN_CALLBACK_COUNT(_fix_interval), \ + .max_callback_count = TEST_MAX_CALLBACK_COUNT(_fix_interval), \ + } + +static const struct device *dev = DEVICE_DT_GET(DT_ALIAS(gnss)); + +struct test_config { + uint32_t fix_interval; + uint32_t min_callback_count; + uint32_t max_callback_count; +}; + +static const struct test_config configs[] = { + TEST_CONFIG_DEFINE(100), + TEST_CONFIG_DEFINE(500), + TEST_CONFIG_DEFINE(1000), + TEST_CONFIG_DEFINE(2000), +}; + +static atomic_t callback_count_atom = ATOMIC_INIT(0); + +static void gnss_data_cb(const struct device *dev, const struct gnss_data *data) +{ + atomic_inc(&callback_count_atom); +} + +GNSS_DATA_CALLBACK_DEFINE(DEVICE_DT_GET(DT_ALIAS(gnss)), gnss_data_cb); + +static bool test_set_fix_rate(const struct test_config *config) +{ + int ret; + + ret = gnss_set_fix_rate(dev, config->fix_interval); + if (ret == -ENOSYS) { + ztest_test_skip(); + } + if (ret == -EINVAL) { + return false; + } + zassert_ok(ret, "failed to set fix rate %u", config->fix_interval); + return true; +} + +static void test_validate_fix_rate(const struct test_config *config) +{ + bool valid; + uint32_t callback_count; + + atomic_set(&callback_count_atom, 0); + k_sleep(TEST_VALIDATE_PERIOD); + callback_count = atomic_get(&callback_count_atom); + valid = (callback_count >= config->min_callback_count) && + (callback_count <= config->max_callback_count); + zassert_true(valid, "callback count %u invalid", callback_count); +} + +ZTEST(gnss_api, test_fix_rate) +{ + for (uint32_t i = 0; i < ARRAY_SIZE(configs); i++) { + if (!test_set_fix_rate(&configs[i])) { + continue; + } + test_validate_fix_rate(&configs[i]); + } +} diff --git a/tests/drivers/gnss/gnss_api/src/test_navigation_mode.c b/tests/drivers/gnss/gnss_api/src/test_navigation_mode.c new file mode 100644 index 00000000000000..c07843b58f6532 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/src/test_navigation_mode.c @@ -0,0 +1,60 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +static const struct device *dev = DEVICE_DT_GET(DT_ALIAS(gnss)); +static const enum gnss_navigation_mode nav_modes[] = { + GNSS_NAVIGATION_MODE_ZERO_DYNAMICS, + GNSS_NAVIGATION_MODE_LOW_DYNAMICS, + GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS, + GNSS_NAVIGATION_MODE_HIGH_DYNAMICS, +}; + +static bool test_set_nav_mode(enum gnss_navigation_mode nav_mode) +{ + int ret; + + ret = gnss_set_navigation_mode(dev, nav_mode); + if (ret == -ENOSYS) { + ztest_test_skip(); + } + if (ret == -EINVAL) { + return false; + } + zassert_ok(ret, "failed to set navigation mode %u", nav_mode); + return true; +} + +static void test_validate_nav_mode(enum gnss_navigation_mode nav_mode) +{ + int ret; + enum gnss_navigation_mode set_nav_mode; + + ret = gnss_get_navigation_mode(dev, &set_nav_mode); + if (ret == -ENOSYS) { + return; + } + zassert_ok(ret, "failed to get navigation mode %u", nav_mode); +} + +ZTEST(gnss_api, test_navigation_mode) +{ + enum gnss_navigation_mode nav_mode; + + for (uint8_t i = 0; i < ARRAY_SIZE(nav_modes); i++) { + nav_mode = nav_modes[i]; + + if (!test_set_nav_mode(nav_mode)) { + continue; + } + + test_validate_nav_mode(nav_mode); + } +} diff --git a/tests/drivers/gnss/gnss_api/src/test_suite.c b/tests/drivers/gnss/gnss_api/src/test_suite.c new file mode 100644 index 00000000000000..15439f5d9f3764 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/src/test_suite.c @@ -0,0 +1,9 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +ZTEST_SUITE(gnss_api, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/gnss/gnss_api/testcase.yaml b/tests/drivers/gnss/gnss_api/testcase.yaml new file mode 100644 index 00000000000000..7ce2c22de3efb8 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/testcase.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.gnss.gnss_api: + filter: dt_alias_exists("gnss") + timeout: 300 From 5a5a0e8003425bbe259824d3a63691830bda23b8 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0402/1389] tests: drivers: gnss: gnss_api: Add overlay for emulated boards Add overlay and conf for emulated boards allowing the test suite along with the emulated GNSS driver to be built and tested by CI. Signed-off-by: Bjarki Arge Andreasen --- .../gnss/gnss_api/boards/native_sim.conf | 13 +++++++++++++ .../gnss/gnss_api/boards/native_sim.overlay | 16 ++++++++++++++++ .../gnss/gnss_api/boards/native_sim_64.conf | 13 +++++++++++++ .../gnss/gnss_api/boards/native_sim_64.overlay | 16 ++++++++++++++++ .../drivers/gnss/gnss_api/boards/qemu_x86.conf | 13 +++++++++++++ .../gnss/gnss_api/boards/qemu_x86.overlay | 16 ++++++++++++++++ .../gnss/gnss_api/boards/qemu_x86_64.conf | 18 ++++++++++++++++++ .../gnss/gnss_api/boards/qemu_x86_64.overlay | 16 ++++++++++++++++ 8 files changed, 121 insertions(+) create mode 100644 tests/drivers/gnss/gnss_api/boards/native_sim.conf create mode 100644 tests/drivers/gnss/gnss_api/boards/native_sim.overlay create mode 100644 tests/drivers/gnss/gnss_api/boards/native_sim_64.conf create mode 100644 tests/drivers/gnss/gnss_api/boards/native_sim_64.overlay create mode 100644 tests/drivers/gnss/gnss_api/boards/qemu_x86.conf create mode 100644 tests/drivers/gnss/gnss_api/boards/qemu_x86.overlay create mode 100644 tests/drivers/gnss/gnss_api/boards/qemu_x86_64.conf create mode 100644 tests/drivers/gnss/gnss_api/boards/qemu_x86_64.overlay diff --git a/tests/drivers/gnss/gnss_api/boards/native_sim.conf b/tests/drivers/gnss/gnss_api/boards/native_sim.conf new file mode 100644 index 00000000000000..58a3450defba74 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/native_sim.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS_SATELLITES=y + +# GPS +CONFIG_TEST_ENABLED_SYSTEMS_0=1 +# GPS + GLONASS +CONFIG_TEST_ENABLED_SYSTEMS_1=3 +# GPS + GLONASS + QZSS +CONFIG_TEST_ENABLED_SYSTEMS_2=19 +# GPS + GLONASS + GALILEO + BEIDOU + QZSS + SBAS +CONFIG_TEST_ENABLED_SYSTEMS_3=95 diff --git a/tests/drivers/gnss/gnss_api/boards/native_sim.overlay b/tests/drivers/gnss/gnss_api/boards/native_sim.overlay new file mode 100644 index 00000000000000..c81955df1acc96 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/native_sim.overlay @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + gnss = &gnss; + }; + + gnss: gnss { + compatible = "zephyr,gnss-emul"; + status = "okay"; + }; +}; diff --git a/tests/drivers/gnss/gnss_api/boards/native_sim_64.conf b/tests/drivers/gnss/gnss_api/boards/native_sim_64.conf new file mode 100644 index 00000000000000..58a3450defba74 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/native_sim_64.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS_SATELLITES=y + +# GPS +CONFIG_TEST_ENABLED_SYSTEMS_0=1 +# GPS + GLONASS +CONFIG_TEST_ENABLED_SYSTEMS_1=3 +# GPS + GLONASS + QZSS +CONFIG_TEST_ENABLED_SYSTEMS_2=19 +# GPS + GLONASS + GALILEO + BEIDOU + QZSS + SBAS +CONFIG_TEST_ENABLED_SYSTEMS_3=95 diff --git a/tests/drivers/gnss/gnss_api/boards/native_sim_64.overlay b/tests/drivers/gnss/gnss_api/boards/native_sim_64.overlay new file mode 100644 index 00000000000000..c81955df1acc96 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/native_sim_64.overlay @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + gnss = &gnss; + }; + + gnss: gnss { + compatible = "zephyr,gnss-emul"; + status = "okay"; + }; +}; diff --git a/tests/drivers/gnss/gnss_api/boards/qemu_x86.conf b/tests/drivers/gnss/gnss_api/boards/qemu_x86.conf new file mode 100644 index 00000000000000..58a3450defba74 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/qemu_x86.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS_SATELLITES=y + +# GPS +CONFIG_TEST_ENABLED_SYSTEMS_0=1 +# GPS + GLONASS +CONFIG_TEST_ENABLED_SYSTEMS_1=3 +# GPS + GLONASS + QZSS +CONFIG_TEST_ENABLED_SYSTEMS_2=19 +# GPS + GLONASS + GALILEO + BEIDOU + QZSS + SBAS +CONFIG_TEST_ENABLED_SYSTEMS_3=95 diff --git a/tests/drivers/gnss/gnss_api/boards/qemu_x86.overlay b/tests/drivers/gnss/gnss_api/boards/qemu_x86.overlay new file mode 100644 index 00000000000000..c81955df1acc96 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/qemu_x86.overlay @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + gnss = &gnss; + }; + + gnss: gnss { + compatible = "zephyr,gnss-emul"; + status = "okay"; + }; +}; diff --git a/tests/drivers/gnss/gnss_api/boards/qemu_x86_64.conf b/tests/drivers/gnss/gnss_api/boards/qemu_x86_64.conf new file mode 100644 index 00000000000000..b1cf5b22cbef1a --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/qemu_x86_64.conf @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_GNSS_SATELLITES=y + +# GPS +CONFIG_TEST_ENABLED_SYSTEMS_0=1 +# GPS + GLONASS +CONFIG_TEST_ENABLED_SYSTEMS_1=3 +# GPS + GLONASS + QZSS +CONFIG_TEST_ENABLED_SYSTEMS_2=19 +# GPS + GLONASS + GALILEO + BEIDOU + QZSS + SBAS +CONFIG_TEST_ENABLED_SYSTEMS_3=95 + +# This emulated board runs real-time +# Lower timeouts to prevent unnecessary waiting +CONFIG_TEST_SEARCH_PERIOD=5 +CONFIG_TEST_FIX_TIMEOUT=1 diff --git a/tests/drivers/gnss/gnss_api/boards/qemu_x86_64.overlay b/tests/drivers/gnss/gnss_api/boards/qemu_x86_64.overlay new file mode 100644 index 00000000000000..c81955df1acc96 --- /dev/null +++ b/tests/drivers/gnss/gnss_api/boards/qemu_x86_64.overlay @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + gnss = &gnss; + }; + + gnss: gnss { + compatible = "zephyr,gnss-emul"; + status = "okay"; + }; +}; From 4bf25c708a35d565267920d1b0bf3128c8bada4f Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0403/1389] shell: backends: uart: avoid unnecessary TX IRQs The shell UART TX code would only disable the TX IRQ when no data was available in the TX ring buffer. However, it should also disable the IRQ when all data retrieved from the buffer has been written. Otherwise it will just result in another immediate TX IRQ which results in the IRQ finally being disabled. For this to work, since ring_buf_get_claim may not always return all available data in the ring buffer on a single call, we need to loop until either no data is left in the ring buffer or the UART was unable to consume any of the data. Signed-off-by: Robert Hancock --- subsys/shell/backends/shell_uart.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/subsys/shell/backends/shell_uart.c b/subsys/shell/backends/shell_uart.c index e80317664b9744..5384977b614fc1 100644 --- a/subsys/shell/backends/shell_uart.c +++ b/subsys/shell/backends/shell_uart.c @@ -166,7 +166,8 @@ static void dtr_timer_handler(struct k_timer *timer) static void uart_tx_handle(const struct device *dev, struct shell_uart_int_driven *sh_uart) { - uint32_t len; + uint32_t avail; + uint32_t written; const uint8_t *data; if (!uart_dtr_check(dev)) { @@ -176,16 +177,22 @@ static void uart_tx_handle(const struct device *dev, struct shell_uart_int_drive return; } - len = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, - sh_uart->tx_ringbuf.size); - if (len) { - int err; + do { + avail = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, + sh_uart->tx_ringbuf.size); + if (avail) { + int err; - len = uart_fifo_fill(dev, data, len); - err = ring_buf_get_finish(&sh_uart->tx_ringbuf, len); - __ASSERT_NO_MSG(err == 0); - ARG_UNUSED(err); - } else { + written = uart_fifo_fill(dev, data, avail); + err = ring_buf_get_finish(&sh_uart->tx_ringbuf, written); + __ASSERT_NO_MSG(err == 0); + ARG_UNUSED(err); + } else { + written = 0; + } + } while (avail && written); + + if (avail == 0) { uart_irq_tx_disable(dev); sh_uart->tx_busy = 0; } From 9ba4566d72d89ed1c2d659b106b575913859761a Mon Sep 17 00:00:00 2001 From: Mayank Mahajan Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0404/1389] ADD: Driver for Sensor INA226 INA226 - Bidirectional Current and Power Monitor w/ I2C Boards Tested: mr_canhubk3 Signed-off-by: Mayank Mahajan --- drivers/sensor/ti/CMakeLists.txt | 1 + drivers/sensor/ti/Kconfig | 1 + drivers/sensor/ti/ina226/CMakeLists.txt | 6 + drivers/sensor/ti/ina226/Kconfig | 26 ++ drivers/sensor/ti/ina226/ina226.c | 335 +++++++++++++++++++++ dts/bindings/sensor/ti,ina226.yaml | 73 +++++ include/zephyr/dt-bindings/sensor/ina226.h | 45 +++ tests/drivers/build_all/sensor/i2c.dtsi | 8 + 8 files changed, 495 insertions(+) create mode 100644 drivers/sensor/ti/ina226/CMakeLists.txt create mode 100644 drivers/sensor/ti/ina226/Kconfig create mode 100644 drivers/sensor/ti/ina226/ina226.c create mode 100644 dts/bindings/sensor/ti,ina226.yaml create mode 100644 include/zephyr/dt-bindings/sensor/ina226.h diff --git a/drivers/sensor/ti/CMakeLists.txt b/drivers/sensor/ti/CMakeLists.txt index 6fae283ad4b678..4af7aa8996d06f 100644 --- a/drivers/sensor/ti/CMakeLists.txt +++ b/drivers/sensor/ti/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory_ifdef(CONFIG_BQ274XX bq274xx) add_subdirectory_ifdef(CONFIG_FDC2X1X fdc2x1x) add_subdirectory_ifdef(CONFIG_INA219 ina219) +add_subdirectory_ifdef(CONFIG_INA226 ina226) add_subdirectory_ifdef(CONFIG_INA23X ina23x) add_subdirectory_ifdef(CONFIG_INA3221 ina3221) add_subdirectory_ifdef(CONFIG_OPT3001 opt3001) diff --git a/drivers/sensor/ti/Kconfig b/drivers/sensor/ti/Kconfig index d3b55698159112..02c5a6e9780fe7 100644 --- a/drivers/sensor/ti/Kconfig +++ b/drivers/sensor/ti/Kconfig @@ -5,6 +5,7 @@ source "drivers/sensor/ti/bq274xx/Kconfig" source "drivers/sensor/ti/fdc2x1x/Kconfig" source "drivers/sensor/ti/ina219/Kconfig" +source "drivers/sensor/ti/ina226/Kconfig" source "drivers/sensor/ti/ina23x/Kconfig" source "drivers/sensor/ti/ina3221/Kconfig" source "drivers/sensor/ti/opt3001/Kconfig" diff --git a/drivers/sensor/ti/ina226/CMakeLists.txt b/drivers/sensor/ti/ina226/CMakeLists.txt new file mode 100644 index 00000000000000..fd0e774e908e1f --- /dev/null +++ b/drivers/sensor/ti/ina226/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_INA226 ina226.c) diff --git a/drivers/sensor/ti/ina226/Kconfig b/drivers/sensor/ti/ina226/Kconfig new file mode 100644 index 00000000000000..f0e9cc75beeca9 --- /dev/null +++ b/drivers/sensor/ti/ina226/Kconfig @@ -0,0 +1,26 @@ +# INA226 Bidirectional Current/Power Monitor + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config INA226 + bool "INA226 Current/Power Monitor" + default y + depends on DT_HAS_TI_INA226_ENABLED + select I2C + help + Enable driver for INA226 Bidirectional Current/Power Monitor. + +config INA226_VSHUNT + bool "INA226 VShunt Measurement Enable" + depends on DT_HAS_TI_INA226_ENABLED + help + Enable shunt voltage measurement for INA226. + + This is the actual shunt voltage measured which is scaled within the + INA226 based upon the SHUNT_CAL register. This value is useful for + determining the measurement noise or debugging the SHUNT_CAL value. + + Note that enabling this option requires an extra I2C read when the + SENSOR_CHAN_ALL is selected. Hence, only enable this option if the + shunt voltage measurement is required. diff --git a/drivers/sensor/ti/ina226/ina226.c b/drivers/sensor/ti/ina226/ina226.c new file mode 100644 index 00000000000000..5f46b0322f0648 --- /dev/null +++ b/drivers/sensor/ti/ina226/ina226.c @@ -0,0 +1,335 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* TODO: Add functionality for Trigger. */ + +#define DT_DRV_COMPAT ti_ina226 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Device register addresses. */ +#define INA226_REG_CONFIG 0x00 +#define INA226_REG_SHUNT_VOLT 0x01 +#define INA226_REG_BUS_VOLT 0x02 +#define INA226_REG_POWER 0x03 +#define INA226_REG_CURRENT 0x04 +#define INA226_REG_CALIB 0x05 +#define INA226_REG_MASK 0x06 +#define INA226_REG_ALERT 0x07 +#define INA226_REG_MANUFACTURER_ID 0xFE +#define INA226_REG_DEVICE_ID 0xFF + +/* Device register values. */ +#define INA226_MANUFACTURER_ID 0x5449 +#define INA226_DEVICE_ID 0x2260 + +struct ina226_data { + const struct device *dev; + int16_t current; + uint16_t bus_voltage; + uint16_t power; +#ifdef CONFIG_INA226_VSHUNT + int16_t shunt_voltage; +#endif + enum sensor_channel chan; +}; + +struct ina226_config { + const struct i2c_dt_spec bus; + uint16_t config; + uint32_t current_lsb; + uint16_t cal; +}; + +LOG_MODULE_REGISTER(INA226, CONFIG_SENSOR_LOG_LEVEL); + +/** @brief Calibration scaling value (scaled by 10^-5) */ +#define INA226_CAL_SCALING 512ULL + +/** @brief The LSB value for the bus voltage register, in microvolts/LSB. */ +#define INA226_BUS_VOLTAGE_TO_uV(x) ((x) * 1250U) + +/** @brief The LSB value for the shunt voltage register, in microvolts/LSB. */ +#define INA226_SHUNT_VOLTAGE_TO_uV(x) ((x) * 2500U / 1000U) + +/** @brief Power scaling (need factor of 0.2) */ +#define INA226_POWER_TO_uW(x) ((x) * 25ULL) + + +int ina226_reg_read_16(const struct i2c_dt_spec *bus, uint8_t reg, uint16_t *val) +{ + uint8_t data[2]; + int ret; + + ret = i2c_burst_read_dt(bus, reg, data, sizeof(data)); + if (ret < 0) { + return ret; + } + + *val = sys_get_be16(data); + + return ret; +} + +int ina226_reg_write(const struct i2c_dt_spec *bus, uint8_t reg, uint16_t val) +{ + uint8_t tx_buf[3]; + + tx_buf[0] = reg; + sys_put_be16(val, &tx_buf[1]); + + return i2c_write_dt(bus, tx_buf, sizeof(tx_buf)); +} + +static void micro_s32_to_sensor_value(struct sensor_value *val, int32_t value_microX) +{ + val->val1 = value_microX / 1000000L; + val->val2 = value_microX % 1000000L; +} + +static int ina226_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct ina226_data *data = dev->data; + const struct ina226_config *config = dev->config; + + switch (chan) { + case SENSOR_CHAN_VOLTAGE: + micro_s32_to_sensor_value(val, INA226_BUS_VOLTAGE_TO_uV(data->bus_voltage)); + break; + case SENSOR_CHAN_CURRENT: + /* see datasheet "Current and Power calculations" section */ + micro_s32_to_sensor_value(val, data->current * config->current_lsb); + break; + case SENSOR_CHAN_POWER: + /* power in uW is power_reg * current_lsb * 0.2 */ + micro_s32_to_sensor_value(val, + INA226_POWER_TO_uW((uint32_t)data->power * config->current_lsb)); + break; +#ifdef CONFIG_INA226_VSHUNT + case SENSOR_CHAN_VSHUNT: + micro_s32_to_sensor_value(val, INA226_SHUNT_VOLTAGE_TO_uV(data->shunt_voltage)); + break; +#endif /* CONFIG_INA226_VSHUNT */ + default: + return -ENOTSUP; + } + + return 0; +} + +static int ina226_read_data(const struct device *dev) +{ + struct ina226_data *data = dev->data; + const struct ina226_config *config = dev->config; + int ret; + + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_VOLTAGE)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_BUS_VOLT, &data->bus_voltage); + if (ret < 0) { + LOG_ERR("Failed to read bus voltage"); + return ret; + } + } + + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_CURRENT)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_CURRENT, &data->current); + if (ret < 0) { + LOG_ERR("Failed to read current"); + return ret; + } + } + + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_POWER)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_POWER, &data->power); + if (ret < 0) { + LOG_ERR("Failed to read power"); + return ret; + } + } + +#ifdef CONFIG_INA226_VSHUNT + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_VSHUNT)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_SHUNT_VOLT, &data->shunt_voltage); + if (ret < 0) { + LOG_ERR("Failed to read shunt voltage"); + return ret; + } + } +#endif /* CONFIG_INA226_VSHUNT */ + + return 0; +} + +static int ina226_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct ina226_data *data = dev->data; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_VOLTAGE + && chan != SENSOR_CHAN_CURRENT && chan != SENSOR_CHAN_POWER +#ifdef CONFIG_INA226_VSHUNT + && chan != SENSOR_CHAN_VSHUNT +#endif /* CONFIG_INA226_VSHUNT */ + ) { + return -ENOTSUP; + } + + data->chan = chan; + + return ina226_read_data(dev); +} + +static int ina226_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + const struct ina226_config *config = dev->config; + uint16_t data = val->val1; + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + return ina226_reg_write(&config->bus, INA226_REG_CONFIG, data); + case SENSOR_ATTR_CALIBRATION: + return ina226_reg_write(&config->bus, INA226_REG_CALIB, data); + default: + LOG_ERR("INA226 attribute not supported."); + return -ENOTSUP; + } +} + +static int ina226_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + const struct ina226_config *config = dev->config; + uint16_t data; + int ret; + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + ret = ina226_reg_read_16(&config->bus, INA226_REG_CONFIG, &data); + if (ret < 0) { + return ret; + } + break; + case SENSOR_ATTR_CALIBRATION: + ret = ina226_reg_read_16(&config->bus, INA226_REG_CALIB, &data); + if (ret < 0) { + return ret; + } + break; + default: + LOG_ERR("INA226 attribute not supported."); + return -ENOTSUP; + } + + val->val1 = data; + val->val2 = 0; + + return 0; +} + +static int ina226_calibrate(const struct device *dev) +{ + const struct ina226_config *config = dev->config; + int ret; + + ret = ina226_reg_write(&config->bus, INA226_REG_CALIB, config->cal); + if (ret < 0) { + return ret; + } + + return 0; +} + +static int ina226_init(const struct device *dev) +{ + struct ina226_data *data = dev->data; + const struct ina226_config *config = dev->config; + uint16_t id; + int ret; + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("I2C bus %s is not ready", config->bus.bus->name); + return -ENODEV; + } + + data->dev = dev; + + ret = ina226_reg_read_16(&config->bus, INA226_REG_MANUFACTURER_ID, &id); + if (ret < 0) { + LOG_ERR("Failed to read manufacturer register."); + return ret; + } + + if (id != INA226_MANUFACTURER_ID) { + LOG_ERR("Manufacturer ID doesn't match."); + return -ENODEV; + } + + ret = ina226_reg_read_16(&config->bus, INA226_REG_DEVICE_ID, &id); + if (ret < 0) { + LOG_ERR("Failed to read device register."); + return ret; + } + + if (id != INA226_DEVICE_ID) { + LOG_ERR("Device ID doesn't match."); + return -ENODEV; + } + + ret = ina226_reg_write(&config->bus, INA226_REG_CONFIG, config->config); + if (ret < 0) { + LOG_ERR("Failed to write configuration register."); + return ret; + } + + ret = ina226_calibrate(dev); + if (ret < 0) { + LOG_ERR("Failed to write calibration register."); + return ret; + } + + return 0; +} + +static const struct sensor_driver_api ina226_driver_api = { + .attr_set = ina226_attr_set, + .attr_get = ina226_attr_get, + .sample_fetch = ina226_sample_fetch, + .channel_get = ina226_channel_get, +}; + +#define INA226_DRIVER_INIT(inst) \ + static struct ina226_data ina226_data_##inst; \ + static const struct ina226_config ina226_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \ + .cal = INA226_CAL_SCALING * 10000000ULL / \ + (DT_INST_PROP(inst, current_lsb_microamps) * \ + DT_INST_PROP(inst, rshunt_micro_ohms)), \ + .config = (DT_INST_ENUM_IDX(inst, avg_count) << 9) | \ + (DT_INST_ENUM_IDX(inst, vbus_conversion_time_us) << 6) | \ + (DT_INST_ENUM_IDX(inst, vshunt_conversion_time_us) << 3) | \ + DT_INST_ENUM_IDX(inst, operating_mode), \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, \ + &ina226_init, \ + NULL, \ + &ina226_data_##inst, \ + &ina226_config_##inst, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &ina226_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(INA226_DRIVER_INIT) diff --git a/dts/bindings/sensor/ti,ina226.yaml b/dts/bindings/sensor/ti,ina226.yaml new file mode 100644 index 00000000000000..0752e2902d5732 --- /dev/null +++ b/dts/bindings/sensor/ti,ina226.yaml @@ -0,0 +1,73 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + TI INA226 Bidirectional Current and Power Monitor. + The file should be included in the + DeviceTree as it provides macros that can be used for initializing the + configuration registers. + +compatible: "ti,ina226" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + avg-count: + type: int + description: | + Number of samples to average (applies to all inputs). + Default is the power-on reset value. + default: 1 + enum: [1, 4, 16, 64, 128, 256, 512, 1024] + + vbus-conversion-time-us: + type: int + description: | + Vbus conversion time in microseconds. + Default is the power-on reset value. + default: 1100 + enum: [140, 204, 332, 588, 1100, 2116, 4156, 8244] + + vshunt-conversion-time-us: + type: int + description: | + Vshunt conversion time in microseconds. + Default is the power-on reset value. + default: 1100 + enum: [140, 204, 332, 588, 1100, 2116, 4156, 8244] + + operating-mode: + type: string + description: | + Selects mode of operation. + Default is the power-on reset value. + default: "Shunt and Bus, Continuous" + enum: + - "Power-Down (or Shutdown)" + - "Shunt Voltage, Triggered" + - "Bus Voltage, Triggered" + - "Shunt and Bus, Triggered" + - "Power-Down (or Shutdown)" + - "Shunt Voltage, Continuous" + - "Bus Voltage, Continuous" + - "Shunt and Bus, Continuous" + + current-lsb-microamps: + type: int + required: true + description: | + Current LSB value in microAmpere. + This value gives the measurement resolution for current measurement. + Formula: current-lsb [μA] = maximum expected current [μA] / 2^15 + Higher resolution means lower range of current measurement, vice versa. + + For example, if maximum expected current is 15 [A]: + then, current-lsb [μA] = 15000000 [μA] / 2^15 ~= 457.763 [μA]. + + Note: rounded values may be used for convenience, e.g. 500uA/LSB. + + rshunt-micro-ohms: + type: int + required: true + description: | + Shunt resistor value in micro-ohms. diff --git a/include/zephyr/dt-bindings/sensor/ina226.h b/include/zephyr/dt-bindings/sensor/ina226.h new file mode 100644 index 00000000000000..9efd704eb9da46 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/ina226.h @@ -0,0 +1,45 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INA226_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INA226_H_ + +#include + +/* Reset Mode. */ +#define INA226_RST_NORMAL_OPERATION 0x00 +#define INA226_RST_SYSTEM_RESET 0x01 + +/* Averaging Mode. */ +#define INA226_AVG_MODE_1 0x00 +#define INA226_AVG_MODE_4 0x01 +#define INA226_AVG_MODE_16 0x02 +#define INA226_AVG_MODE_64 0x03 +#define INA226_AVG_MODE_128 0x04 +#define INA226_AVG_MODE_256 0x05 +#define INA226_AVG_MODE_512 0x06 +#define INA226_AVG_MODE_1024 0x07 + +/* Conversion time for bus and shunt voltage in micro-seconds. */ +#define INA226_CONV_TIME_140 0x00 +#define INA226_CONV_TIME_204 0x01 +#define INA226_CONV_TIME_332 0x02 +#define INA226_CONV_TIME_588 0x03 +#define INA226_CONV_TIME_1100 0x04 +#define INA226_CONV_TIME_2116 0x05 +#define INA226_CONV_TIME_4156 0x06 +#define INA226_CONV_TIME_8244 0x07 + +/* Operating Mode. */ +#define INA226_OPER_MODE_POWER_DOWN 0x00 +#define INA226_OPER_MODE_SHUNT_VOLTAGE_TRIG 0x01 +#define INA226_OPER_MODE_BUS_VOLTAGE_TRIG 0x02 +#define INA226_OPER_MODE_SHUNT_BUS_VOLTAGE_TRIG 0x03 +#define INA226_OPER_MODE_SHUNT_VOLTAGE_CONT 0x05 +#define INA226_OPER_MODE_BUS_VOLTAGE_CONT 0x06 +#define INA226_OPER_MODE_SHUNT_BUS_VOLTAGE_CONT 0x07 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INA226_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index eb5a0e973789da..5de1f832802d5c 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -22,6 +22,7 @@ #include #include #include +#include /**************************************** * PLEASE KEEP REG ADDRESSES SEQUENTIAL * @@ -1041,3 +1042,10 @@ test_i2c_tmp114: tmp114@8c { compatible = "ti,tmp114"; reg = <0x8c>; }; + +test_i2c_ina226: ina226@8d { + compatible = "ti,ina226"; + reg = <0x8d>; + current-lsb-microamps = <5000>; + rshunt-micro-ohms = <500>; +}; From 8a8c9157b12373621cd070627bd081178740e4a2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0405/1389] kernel: sem: Remove constant expression limit is unsigned int and K_SEM_MAX_LIMIT is defined as UINT_MAX this means that limit will never be greater K_SEM_MAX_LIMIT. Signed-off-by: Flavio Ceolin --- kernel/sem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sem.c b/kernel/sem.c index c3c8055d0de9d3..52f1e0c1b0ab85 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -48,7 +48,7 @@ int z_impl_k_sem_init(struct k_sem *sem, unsigned int initial_count, /* * Limit cannot be zero and count cannot be greater than limit */ - CHECKIF(limit == 0U || limit > K_SEM_MAX_LIMIT || initial_count > limit) { + CHECKIF(limit == 0U || initial_count > limit) { SYS_PORT_TRACING_OBJ_FUNC(k_sem, init, sem, -EINVAL); return -EINVAL; From 40ee329112f1a11d02212fdb1ae2b0de7d81c367 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0406/1389] ipc: icmsg_me: Fix possible integer overflow Fix possible integer overflow and underflow. Signed-off-by: Flavio Ceolin --- subsys/ipc/ipc_service/lib/icmsg_me.c | 33 ++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/subsys/ipc/ipc_service/lib/icmsg_me.c b/subsys/ipc/ipc_service/lib/icmsg_me.c index 24e3ba6514e9c1..b4d384e6bb0ee2 100644 --- a/subsys/ipc/ipc_service/lib/icmsg_me.c +++ b/subsys/ipc/ipc_service/lib/icmsg_me.c @@ -5,6 +5,7 @@ */ #include +#include #include @@ -20,14 +21,24 @@ static void *icmsg_buffer_to_user_buffer(const void *icmsg_buffer) return (void *)(((char *)icmsg_buffer) + HEADER_SIZE); } -static size_t icmsg_buffer_len_to_user_buffer_len(size_t icmsg_buffer_len) +static ssize_t icmsg_buffer_len_to_user_buffer_len(size_t icmsg_buffer_len) { - return icmsg_buffer_len - HEADER_SIZE; + if (icmsg_buffer_len < HEADER_SIZE) { + return -EINVAL; + } + + return (ssize_t)(icmsg_buffer_len - HEADER_SIZE); } -static size_t user_buffer_len_to_icmsg_buffer_len(size_t user_buffer_len) +static ssize_t user_buffer_len_to_icmsg_buffer_len(size_t user_buffer_len) { - return user_buffer_len + HEADER_SIZE; + size_t ret; + + if (size_add_overflow(user_buffer_len, HEADER_SIZE, &ret)) { + return -EINVAL; + } + + return (ssize_t)ret; } static void set_ept_id_in_send_buffer(uint8_t *send_buffer, @@ -141,6 +152,7 @@ void icmsg_me_received_data(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, { int r; const struct ipc_ept_cfg *ept; + ssize_t user_buffer_len; r = icmsg_me_get_ept_cfg(data, id, &ept); if (r < 0) { @@ -151,10 +163,14 @@ void icmsg_me_received_data(struct icmsg_me_data_t *data, icmsg_me_ept_id_t id, return; } + user_buffer_len = icmsg_buffer_len_to_user_buffer_len(len); + if (user_buffer_len < 0) { + return; + } + if (ept->cb.received) { ept->cb.received(icmsg_buffer_to_user_buffer(msg), - icmsg_buffer_len_to_user_buffer_len(len), - ept->priv); + user_buffer_len, ept->priv); } } @@ -164,8 +180,9 @@ int icmsg_me_send(const struct icmsg_config_t *conf, { int r; int sent_bytes = 0; + ssize_t icmsg_buffer_len = user_buffer_len_to_icmsg_buffer_len(len); - if (user_buffer_len_to_icmsg_buffer_len(len) >= SEND_BUF_SIZE) { + if ((icmsg_buffer_len < 0) || (icmsg_buffer_len >= SEND_BUF_SIZE)) { return -EBADMSG; } @@ -179,7 +196,7 @@ int icmsg_me_send(const struct icmsg_config_t *conf, memcpy(icmsg_buffer_to_user_buffer(data->send_buffer), msg, len); r = icmsg_send(conf, &data->icmsg_data, data->send_buffer, - user_buffer_len_to_icmsg_buffer_len(len)); + icmsg_buffer_len); if (r > 0) { sent_bytes = icmsg_buffer_len_to_user_buffer_len(r); } From 29239cab2eda37a3c5d9da6dd0263bf924bfd4ff Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0407/1389] drivers: sensor: tmp112: only show options when device enabled Only show the tmp112 runtime options when the tmp112 driver is enabled, otherwise the option is confusing and does not appear hierarchically in menuconfig. Signed-off-by: Aurelien Jarno --- drivers/sensor/ti/tmp112/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/sensor/ti/tmp112/Kconfig b/drivers/sensor/ti/tmp112/Kconfig index 19baeade7dcd3e..c6ece4e4b8ce0a 100644 --- a/drivers/sensor/ti/tmp112/Kconfig +++ b/drivers/sensor/ti/tmp112/Kconfig @@ -15,6 +15,8 @@ config TMP112 The TMP102 is compatible with the TMP112 but is less accurate and has been successfully tested with this driver. +if TMP112 + config TMP112_FULL_SCALE_RUNTIME bool "Allow to set extended mode at runtime" default y @@ -28,3 +30,5 @@ config TMP112_SAMPLING_FREQUENCY_RUNTIME help When set conversion rate can be set at runtime using sensor_attr_set with SENSOR_ATTR_SAMPLING_FREQUENCY + +endif # TMP112 From 95fe27aa408f423ccb4683116bc814a12859a0d5 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0408/1389] soc: nordic: nrf54h20: Make HSFLL trims optional If no HSFLL needs trimming, then `trim_hsfll()` should be compiled out. This makes it easier to reuse the rest of `soc.c` out of tree. Furthermore, some HSFLL instances can be trimmed before booting Zephyr, so the FICR client properties in the DT binding should not be required. Signed-off-by: Grzegorz Swiderski --- dts/bindings/clock/nordic,nrf-hsfll.yaml | 6 ------ soc/nordic/nrf54h/soc.c | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dts/bindings/clock/nordic,nrf-hsfll.yaml b/dts/bindings/clock/nordic,nrf-hsfll.yaml index 3614d80870fa00..f1077dbc4f0e9b 100644 --- a/dts/bindings/clock/nordic,nrf-hsfll.yaml +++ b/dts/bindings/clock/nordic,nrf-hsfll.yaml @@ -57,9 +57,3 @@ properties: - 368000000 - 384000000 - 400000000 - - nordic,ficrs: - required: true - - nordic,ficr-names: - required: true diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index df72cdb977b093..1ba620473a08dc 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -55,6 +55,8 @@ static void power_domain_init(void) static int trim_hsfll(void) { +#if defined(HSFLL_NODE) + NRF_HSFLL_Type *hsfll = (NRF_HSFLL_Type *)DT_REG_ADDR(HSFLL_NODE); nrf_hsfll_trim_t trim = { .vsup = sys_read32(FICR_ADDR_GET(HSFLL_NODE, vsup)), @@ -77,6 +79,8 @@ static int trim_hsfll(void) LOG_DBG("NRF_HSFLL->TRIM.COARSE = %d", hsfll->TRIM.COARSE); LOG_DBG("NRF_HSFLL->TRIM.FINE = %d", hsfll->TRIM.FINE); +#endif /* defined(HSFLL_NODE) */ + return 0; } From 64381acb23e5ca6b80f3d8092a237d845cd9e0fa Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0409/1389] soc: nordic: nrf54h20: Use KERNEL_INIT_PRIORITY_DEFAULT Make the SoC initialization priority configurable. Signed-off-by: Grzegorz Swiderski --- soc/nordic/nrf54h/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index 1ba620473a08dc..ce5af2e25af90a 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -111,4 +111,4 @@ void arch_busy_wait(uint32_t time_us) nrfx_coredep_delay_us(time_us); } -SYS_INIT(nordicsemi_nrf54h_init, PRE_KERNEL_1, 0); +SYS_INIT(nordicsemi_nrf54h_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From 5f1c6bb6e2f3f076ff2cfcb3f9a1d355b13b2c00 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0410/1389] soc: nordic: Extend address validation for nRF54H20 Add `CHECK_DT_REG()` entries for a few additional peripheral types: BELLBOARD, CCM, GRTC, HSFLL, UICR, and VPR. For peripheral instances outside of the Global Domain, such as DPPIC020, use domain-specific defines like NRF_RADIOCORE_DPPIC020 when validating. These are always defined by the MDK, while NRF_DPPIC020 isn't guaranteed to exist in those cases. Revise existing macro checks accordingly. Signed-off-by: Grzegorz Swiderski --- soc/nordic/validate_base_addresses.c | 38 ++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/soc/nordic/validate_base_addresses.c b/soc/nordic/validate_base_addresses.c index 9dfd1e409c89e7..4fca3501e27a4b 100644 --- a/soc/nordic/validate_base_addresses.c +++ b/soc/nordic/validate_base_addresses.c @@ -37,6 +37,14 @@ #define NRF_QDEC0 NRF_QDEC #endif +#if !defined(NRF_RADIO) && defined(NRF_RADIOCORE_RADIO) +#define NRF_RADIO NRF_RADIOCORE_RADIO +#endif + +#if !defined(NRF_RTC) && defined(NRF_RADIOCORE_RTC) +#define NRF_RTC NRF_RADIOCORE_RTC +#endif + #if !defined(NRF_SWI0) && defined(NRF_SWI_BASE) #define NRF_SWI0 ((0 * 0x1000) + NRF_SWI_BASE) #endif @@ -126,8 +134,13 @@ CHECK_DT_REG(acl, NRF_ACL); CHECK_DT_REG(adc, NODE_ADDRESS(adc, nordic_nrf_adc, NRF_ADC, NRF_SAADC)); +CHECK_DT_REG(cpusec_bellboard, NRF_SECDOMBELLBOARD); +CHECK_DT_REG(cpuapp_bellboard, NRF_APPLICATION_BELLBOARD); +CHECK_DT_REG(cpurad_bellboard, NRF_RADIOCORE_BELLBOARD); CHECK_DT_REG(bprot, NRF_BPROT); CHECK_DT_REG(ccm, NRF_CCM); +CHECK_DT_REG(ccm030, NRF_RADIOCORE_CCM030); +CHECK_DT_REG(ccm031, NRF_RADIOCORE_CCM031); CHECK_DT_REG(clock, NRF_CLOCK); CHECK_DT_REG(comp, NODE_ADDRESS(comp, nordic_nrf_comp, NRF_COMP, NRF_LPCOMP)); CHECK_DT_REG(cryptocell, NRF_CRYPTOCELL); @@ -138,7 +151,7 @@ CHECK_DT_REG(dppic00, NRF_DPPIC00); CHECK_DT_REG(dppic10, NRF_DPPIC10); CHECK_DT_REG(dppic20, NRF_DPPIC20); CHECK_DT_REG(dppic30, NRF_DPPIC30); -CHECK_DT_REG(dppic020, NRF_DPPIC020); +CHECK_DT_REG(dppic020, NRF_RADIOCORE_DPPIC020); CHECK_DT_REG(dppic120, NRF_DPPIC120); CHECK_DT_REG(dppic130, NRF_DPPIC130); CHECK_DT_REG(dppic131, NRF_DPPIC131); @@ -149,7 +162,8 @@ CHECK_DT_REG(dppic135, NRF_DPPIC135); CHECK_DT_REG(dppic136, NRF_DPPIC136); CHECK_DT_REG(ecb, NRF_ECB); CHECK_DT_REG(ecb020, NRF_ECB020); -CHECK_DT_REG(ecb030, NRF_ECB030); +CHECK_DT_REG(ecb030, NRF_RADIOCORE_ECB030); +CHECK_DT_REG(ecb031, NRF_RADIOCORE_ECB031); CHECK_DT_REG(egu0, NRF_EGU0); CHECK_DT_REG(egu1, NRF_EGU1); CHECK_DT_REG(egu2, NRF_EGU2); @@ -158,7 +172,7 @@ CHECK_DT_REG(egu4, NRF_EGU4); CHECK_DT_REG(egu5, NRF_EGU5); CHECK_DT_REG(egu10, NRF_EGU10); CHECK_DT_REG(egu20, NRF_EGU20); -CHECK_DT_REG(egu020, NRF_EGU020); +CHECK_DT_REG(egu020, NRF_RADIOCORE_EGU020); CHECK_DT_REG(ficr, NRF_FICR); CHECK_DT_REG(flash_controller, NRF_NVMC); CHECK_DT_REG(gpio0, NRF_P0); @@ -174,6 +188,9 @@ CHECK_DT_REG(gpiote20, NRF_GPIOTE20); CHECK_DT_REG(gpiote30, NRF_GPIOTE30); CHECK_DT_REG(gpiote130, NRF_GPIOTE130); CHECK_DT_REG(gpiote131, NRF_GPIOTE131); +CHECK_DT_REG(grtc, NRF_GRTC); +CHECK_DT_REG(cpuapp_hsfll, NRF_APPLICATION_HSFLL); +CHECK_DT_REG(cpurad_hsfll, NRF_RADIOCORE_HSFLL); CHECK_I2C_REG(i2c0, 0); CHECK_I2C_REG(i2c1, 1); CHECK_DT_REG(i2c2, NRF_TWIM2); @@ -193,8 +210,8 @@ CHECK_DT_REG(i2c137, NRF_TWIM137); CHECK_DT_REG(i2s0, NRF_I2S0); CHECK_DT_REG(i2s20, NRF_I2S20); CHECK_DT_REG(ipc, NRF_IPC); -CHECK_DT_REG(cpuapp_ipct, NRF_IPCT); -CHECK_DT_REG(cpurad_ipct, NRF_IPCT); +CHECK_DT_REG(cpuapp_ipct, NRF_APPLICATION_IPCT); +CHECK_DT_REG(cpurad_ipct, NRF_RADIOCORE_IPCT); CHECK_DT_REG(ipct120, NRF_IPCT120); CHECK_DT_REG(ipct130, NRF_IPCT130); CHECK_DT_REG(kmu, NRF_KMU); @@ -275,9 +292,9 @@ CHECK_DT_REG(timer21, NRF_TIMER21); CHECK_DT_REG(timer22, NRF_TIMER22); CHECK_DT_REG(timer23, NRF_TIMER23); CHECK_DT_REG(timer24, NRF_TIMER24); -CHECK_DT_REG(timer020, NRF_TIMER020); -CHECK_DT_REG(timer021, NRF_TIMER021); -CHECK_DT_REG(timer022, NRF_TIMER022); +CHECK_DT_REG(timer020, NRF_RADIOCORE_TIMER020); +CHECK_DT_REG(timer021, NRF_RADIOCORE_TIMER021); +CHECK_DT_REG(timer022, NRF_RADIOCORE_TIMER022); CHECK_DT_REG(timer120, NRF_TIMER120); CHECK_DT_REG(timer121, NRF_TIMER121); CHECK_DT_REG(timer130, NRF_TIMER130); @@ -307,6 +324,8 @@ CHECK_DT_REG(uart135, NRF_UARTE135); CHECK_DT_REG(uart136, NRF_UARTE136); CHECK_DT_REG(uart137, NRF_UARTE137); CHECK_DT_REG(uicr, NRF_UICR); +CHECK_DT_REG(cpuapp_uicr, NRF_APPLICATION_UICR); +CHECK_DT_REG(cpurad_uicr, NRF_RADIOCORE_UICR); CHECK_DT_REG(usbd, NRF_USBD); CHECK_DT_REG(usbhs, NRF_USBHS); CHECK_DT_REG(usbhs_core, NRF_USBHSCORE0); @@ -315,6 +334,9 @@ CHECK_DT_REG(vmc, NRF_VMC); CHECK_DT_REG(cpuflpr_clic, NRF_FLPR_VPRCLIC); #if defined(CONFIG_SOC_NRF54L15) CHECK_DT_REG(cpuflpr_vpr, NRF_VPR00); +#elif defined(CONFIG_SOC_NRF54H20) +CHECK_DT_REG(cpuflpr_vpr, NRF_VPR121); +CHECK_DT_REG(cpuppr_vpr, NRF_VPR130); #endif CHECK_DT_REG(wdt, NRF_WDT0); /* this should be the same node as wdt0 */ CHECK_DT_REG(wdt0, NRF_WDT0); From 65b502426a9f2c98593f958588d637b150a00869 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0411/1389] drivers: sensor: grow_r502a: fix in fps_search return -ENOENT; when no record found on getting attribute SENSOR_ATTR_R502A_FIND and fix array indexing for tx data in fps_search. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 028b5919407228..0715771916c3a5 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -454,8 +454,8 @@ static int fps_search(const struct device *dev, uint8_t char_buf_idx) .pid = R502A_COMMAND_PACKET, .data = {R502A_SEARCH, char_buf_idx} }; - sys_put_be16(R02A_LIBRARY_START_IDX, &tx_packet.data[1]); - sys_put_be16(R502A_DEFAULT_CAPACITY, &tx_packet.data[3]); + sys_put_be16(R02A_LIBRARY_START_IDX, &tx_packet.data[2]); + sys_put_be16(R502A_DEFAULT_CAPACITY, &tx_packet.data[4]); transceive_packet(dev, &tx_packet, &rx_packet, search_len); @@ -478,6 +478,7 @@ static int fps_search(const struct device *dev, uint8_t char_buf_idx) led_ctrl.cycle = 0x02; fps_led_control(dev, &led_ctrl); LOG_ERR("Did not find a match"); + return -ENOENT; } else { led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; led_ctrl.color_idx = LED_COLOR_RED; From d7eb772695c11130f7299c5d81b463aee2a4577f Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0412/1389] drivers: sensor: grow_r502a: fix in fps_empty_db return ret; on goto unlock in fps_empty_db function. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 0715771916c3a5..8a822c08da7ca7 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -434,7 +434,7 @@ static int fps_empty_db(const struct device *dev) unlock: k_mutex_unlock(&drv_data->lock); - return 0; + return ret; } static int fps_search(const struct device *dev, uint8_t char_buf_idx) From 7e42abb77f349e251f8253514458e8bb3c38cdd3 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0413/1389] drivers: sensor: grow_r502a: fix in checksum calculation change checksum calculation to consider 2 bytes in pkg_len. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 8a822c08da7ca7..5445c981b0808d 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -27,7 +27,7 @@ static void transceive_packet(const struct device *dev, union r502a_packet *tx_p uint16_t check_sum, pkg_len; pkg_len = data_len + R502A_CHECKSUM_LEN; - check_sum = pkg_len + tx_packet->pid; + check_sum = (pkg_len >> 8) + (pkg_len & 0xFF) + tx_packet->pid; sys_put_be16(R502A_STARTCODE, tx_packet->start); sys_put_be32(cfg->comm_addr, tx_packet->addr); From f95ac8a3822c321d98d5f78a50fb52477a221645 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:46 +0200 Subject: [PATCH 0414/1389] drivers: sensor: grow_r502a: fix in fps_read_template_table consuming sensor_value struct instead of local device driver variable. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 7 +++---- drivers/sensor/grow_r502a/grow_r502a.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 5445c981b0808d..0047f94da6a86f 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -193,7 +193,7 @@ static int fps_get_template_count(const struct device *dev) return 0; } -static int fps_read_template_table(const struct device *dev) +static int fps_read_template_table(const struct device *dev, uint32_t *free_idx) { struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; @@ -232,7 +232,7 @@ static int fps_read_template_table(const struct device *dev) continue; } - drv_data->free_idx = (group_idx * 8) + find_lsb_set(~group) - 1; + *free_idx = (group_idx * 8) + find_lsb_set(~group) - 1; goto unlock; } @@ -672,8 +672,7 @@ static int grow_r502a_attr_get(const struct device *dev, enum sensor_channel cha ret = fps_match(dev, val); break; case SENSOR_ATTR_R502A_RECORD_FREE_IDX: - ret = fps_read_template_table(dev); - val->val1 = drv_data->free_idx; + ret = fps_read_template_table(dev, &val->val1); break; default: LOG_ERR("Sensor attribute not supported"); diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index c8374fb17d3dd5..f61e7edab071d6 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -190,7 +190,6 @@ struct grow_r502a_data { uint16_t finger_id; uint16_t matching_score; uint16_t template_count; - int8_t free_idx; }; struct grow_r502a_config { From b23c55498258147bff979dc27bf1efc7cb8b03fe Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0415/1389] drivers: sensor: grow_r502a: move enroll, search, delete to application Removed fps_enroll, fps_search and fps_delete from driver code, since they did application usage inside driver. add the following attributes to achieve the above functionality from application. 1. SENSOR_ATTR_R502A_CAPTURE 2. SENSOR_ATTR_R502A_TEMPLATE_CREATE 3. SENSOR_ATTR_R502A_RECORD_ADD 4. SENSOR_ATTR_R502A_RECORD_LOAD 5. SENSOR_ATTR_R502A_COMPARE Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 175 +++++++++++++-------- drivers/sensor/grow_r502a/grow_r502a.h | 8 +- include/zephyr/drivers/sensor/grow_r502a.h | 41 ++++- samples/sensor/grow_r502a/src/main.c | 52 ++++-- 4 files changed, 192 insertions(+), 84 deletions(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 0047f94da6a86f..69b66ee5cb801e 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -335,8 +335,10 @@ static int fps_create_model(const struct device *dev) static int fps_store_model(const struct device *dev, uint16_t id) { + struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const store_model_len = 4; + int ret = 0; struct led_params led_ctrl = { .ctrl_code = LED_CTRL_BREATHING, @@ -351,11 +353,14 @@ static int fps_store_model(const struct device *dev, uint16_t id) }; sys_put_be16(id, &tx_packet.data[2]); + k_mutex_lock(&drv_data->lock, K_FOREVER); + transceive_packet(dev, &tx_packet, &rx_packet, store_model_len); if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = -EIO; + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -366,16 +371,19 @@ static int fps_store_model(const struct device *dev, uint16_t id) LOG_INF("Fingerprint stored! at ID #%d", id); } else { LOG_ERR("Error storing model 0x%X", rx_packet.buf[R502A_CC_IDX]); - return -EIO; + ret = -EIO; } - - return 0; +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; } static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t count) { + struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const delete_model_len = 5; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, @@ -384,21 +392,25 @@ static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t coun sys_put_be16(id, &tx_packet.data[1]); sys_put_be16(count + R502A_DELETE_COUNT_OFFSET, &tx_packet.data[3]); + k_mutex_lock(&drv_data->lock, K_FOREVER); + transceive_packet(dev, &tx_packet, &rx_packet, delete_model_len); if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = -EIO; + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { LOG_INF("Fingerprint Deleted from ID #%d to #%d", id, (id + count)); } else { LOG_ERR("Error deleting image 0x%X", rx_packet.buf[R502A_CC_IDX]); - return -EIO; + ret = -EIO; } - - return 0; +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; } static int fps_empty_db(const struct device *dev) @@ -429,7 +441,6 @@ static int fps_empty_db(const struct device *dev) LOG_ERR("Error emptying fingerprint library 0x%X", rx_packet.buf[R502A_CC_IDX]); ret = -EIO; - goto unlock; } unlock: @@ -437,11 +448,12 @@ static int fps_empty_db(const struct device *dev) return ret; } -static int fps_search(const struct device *dev, uint8_t char_buf_idx) +static int fps_search(const struct device *dev, struct sensor_value *val) { struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const search_len = 6; + int ret = 0; struct led_params led_ctrl = { .ctrl_code = LED_CTRL_BREATHING, @@ -452,16 +464,19 @@ static int fps_search(const struct device *dev, uint8_t char_buf_idx) union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, - .data = {R502A_SEARCH, char_buf_idx} + .data = {R502A_SEARCH, R502A_CHAR_BUF_1} }; sys_put_be16(R02A_LIBRARY_START_IDX, &tx_packet.data[2]); sys_put_be16(R502A_DEFAULT_CAPACITY, &tx_packet.data[4]); + k_mutex_lock(&drv_data->lock, K_FOREVER); + transceive_packet(dev, &tx_packet, &rx_packet, search_len); if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = -EIO; + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -469,94 +484,119 @@ static int fps_search(const struct device *dev, uint8_t char_buf_idx) led_ctrl.color_idx = LED_COLOR_PURPLE; led_ctrl.cycle = 0x01; fps_led_control(dev, &led_ctrl); - drv_data->finger_id = sys_get_be16(&rx_packet.data[1]); - drv_data->matching_score = sys_get_be16(&rx_packet.data[3]); - LOG_INF("Found a matching print! at ID #%d", drv_data->finger_id); - } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND) { + val->val1 = sys_get_be16(&rx_packet.data[1]); + val->val2 = sys_get_be16(&rx_packet.data[3]); + LOG_INF("Found a matching print! at ID #%d", val->val1); + } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND_CC) { led_ctrl.ctrl_code = LED_CTRL_BREATHING; led_ctrl.color_idx = LED_COLOR_RED; led_ctrl.cycle = 0x02; fps_led_control(dev, &led_ctrl); LOG_ERR("Did not find a match"); - return -ENOENT; + ret = -ENOENT; } else { led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; led_ctrl.color_idx = LED_COLOR_RED; fps_led_control(dev, &led_ctrl); LOG_ERR("Error searching for image 0x%X", rx_packet.buf[R502A_CC_IDX]); - return -EIO; + ret = -EIO; } - - return 0; +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; } -static int fps_enroll(const struct device *dev, const struct sensor_value *val) +static int fps_load_template(const struct device *dev, uint16_t id) { struct grow_r502a_data *drv_data = dev->data; - int ret = -1; + union r502a_packet rx_packet = {0}; + char const load_tmp_len = 4; + int ret = 0; - if (val->val1 < 0 || val->val1 > R502A_DEFAULT_CAPACITY) { - LOG_ERR("Invalid ID number"); - return -EINVAL; - } + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_LOAD, R502A_CHAR_BUF_1} + }; + sys_put_be16(id, &tx_packet.data[2]); k_mutex_lock(&drv_data->lock, K_FOREVER); - ret = fps_get_image(dev); - if (ret != 0) { - goto unlock; - } - - ret = fps_image_to_char(dev, R502A_CHAR_BUF_1); - if (ret != 0) { - goto unlock; - } - - ret = fps_get_image(dev); - if (ret != 0) { - goto unlock; - } + transceive_packet(dev, &tx_packet, &rx_packet, load_tmp_len); - ret = fps_image_to_char(dev, R502A_CHAR_BUF_2); - if (ret != 0) { + if (rx_packet.pid != R502A_ACK_PACKET) { + LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); + ret = -EIO; goto unlock; } - ret = fps_create_model(dev); - if (ret != 0) { - goto unlock; + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("Load template data from id #%d to Char_buffer2", id); + } else { + LOG_ERR("Error Loading template 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; } - ret = fps_store_model(dev, val->val1); - unlock: k_mutex_unlock(&drv_data->lock); return ret; } -static int fps_delete(const struct device *dev, const struct sensor_value *val) +static int fps_match_templates(const struct device *dev, struct sensor_value *val) { struct grow_r502a_data *drv_data = dev->data; - int ret = -1; + union r502a_packet rx_packet = {0}; + char const match_templates_len = 1; + int ret = 0; + + struct led_params led_ctrl = { + .ctrl_code = LED_CTRL_BREATHING, + .color_idx = LED_COLOR_BLUE, + .speed = LED_SPEED_HALF, + .cycle = 0x01, + }; + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_MATCH} + }; k_mutex_lock(&drv_data->lock, K_FOREVER); - ret = fps_delete_model(dev, val->val1, val->val2); - if (ret != 0) { + transceive_packet(dev, &tx_packet, &rx_packet, match_templates_len); + + if (rx_packet.pid != R502A_ACK_PACKET) { + LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); + ret = -EIO; goto unlock; } - ret = fps_get_template_count(dev); - + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + fps_led_control(dev, &led_ctrl); + val->val1 = R502A_FINGER_MATCH_FOUND; + val->val2 = sys_get_be16(&rx_packet.data[1]); + LOG_INF("Fingerprint matched with a score %d", val->val2); + } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_MATCH_CC) { + val->val1 = R502A_FINGER_MATCH_NOT_FOUND; + LOG_ERR("Fingerprint not matched"); + ret = -ENOENT; + } else { + led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = LED_COLOR_RED; + fps_led_control(dev, &led_ctrl); + LOG_ERR("Error Matching templates 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + } unlock: k_mutex_unlock(&drv_data->lock); return ret; } -static int fps_match(const struct device *dev, struct sensor_value *val) +static int fps_capture(const struct device *dev) { struct grow_r502a_data *drv_data = dev->data; - int ret = -1; + int ret; k_mutex_lock(&drv_data->lock, K_FOREVER); @@ -570,12 +610,13 @@ static int fps_match(const struct device *dev, struct sensor_value *val) goto unlock; } - ret = fps_search(dev, R502A_CHAR_BUF_1); - if (ret == 0) { - val->val1 = drv_data->finger_id; - val->val2 = drv_data->matching_score; + ret = fps_get_image(dev); + if (ret != 0) { + goto unlock; } + ret = fps_image_to_char(dev, R502A_CHAR_BUF_2); + unlock: k_mutex_unlock(&drv_data->lock); return ret; @@ -643,12 +684,18 @@ static int grow_r502a_attr_set(const struct device *dev, enum sensor_channel cha } switch ((enum sensor_attribute_grow_r502a)attr) { + case SENSOR_ATTR_R502A_CAPTURE: + return fps_capture(dev); + case SENSOR_ATTR_R502A_TEMPLATE_CREATE: + return fps_create_model(dev); case SENSOR_ATTR_R502A_RECORD_ADD: - return fps_enroll(dev, val); + return fps_store_model(dev, val->val1); case SENSOR_ATTR_R502A_RECORD_DEL: - return fps_delete(dev, val); + return fps_delete_model(dev, val->val1, val->val2); case SENSOR_ATTR_R502A_RECORD_EMPTY: return fps_empty_db(dev); + case SENSOR_ATTR_R502A_RECORD_LOAD: + return fps_load_template(dev, val->val1); default: LOG_ERR("Sensor attribute not supported"); return -ENOTSUP; @@ -660,7 +707,6 @@ static int grow_r502a_attr_get(const struct device *dev, enum sensor_channel cha enum sensor_attribute attr, struct sensor_value *val) { int ret; - struct grow_r502a_data *drv_data = dev->data; if ((enum sensor_channel_grow_r502a)chan != SENSOR_CHAN_FINGERPRINT) { LOG_ERR("Channel not supported"); @@ -669,11 +715,14 @@ static int grow_r502a_attr_get(const struct device *dev, enum sensor_channel cha switch ((enum sensor_attribute_grow_r502a)attr) { case SENSOR_ATTR_R502A_RECORD_FIND: - ret = fps_match(dev, val); + ret = fps_search(dev, val); break; case SENSOR_ATTR_R502A_RECORD_FREE_IDX: ret = fps_read_template_table(dev, &val->val1); break; + case SENSOR_ATTR_R502A_COMPARE: + ret = fps_match_templates(dev, val); + break; default: LOG_ERR("Sensor attribute not supported"); ret = -ENOTSUP; diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index f61e7edab071d6..00044359a0bade 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -61,7 +61,6 @@ */ #define R502A_OK 0x00 /*commad execution complete*/ -#define R502A_NOT_FOUND 0x09 /*fail to find the matching finger*/ /*Package Identifier's definition*/ #define R502A_COMMAND_PACKET 0x1 /*Command packet*/ @@ -95,6 +94,11 @@ #define R502A_HANDSHAKE 0x40 /*Handshake*/ #define R502A_BADPACKET 0xFE /* Bad packet was sent*/ +#define R502A_NOT_MATCH_CC 0x08 /* templates of two buffers not matching*/ +#define R502A_NOT_FOUND_CC 0x09 /*fail to find the matching finger*/ +#define R502A_FINGER_MATCH_NOT_FOUND 0 +#define R502A_FINGER_MATCH_FOUND 1 + #define R502A_STARTCODE 0xEF01 /*Fixed value, High byte transferred first*/ #define R502A_DEFAULT_PASSWORD 0x00000000 #define R502A_DEFAULT_ADDRESS 0xFFFFFFFF @@ -187,8 +191,6 @@ struct grow_r502a_data { struct k_mutex lock; struct k_sem uart_rx_sem; - uint16_t finger_id; - uint16_t matching_score; uint16_t template_count; }; diff --git a/include/zephyr/drivers/sensor/grow_r502a.h b/include/zephyr/drivers/sensor/grow_r502a.h index 8b0db47188d356..fafcfd78559954 100644 --- a/include/zephyr/drivers/sensor/grow_r502a.h +++ b/include/zephyr/drivers/sensor/grow_r502a.h @@ -24,16 +24,53 @@ enum sensor_trigger_type_grow_r502a { }; enum sensor_attribute_grow_r502a { - /** Add values to the sensor which are having record storage facility */ - SENSOR_ATTR_R502A_RECORD_ADD = SENSOR_ATTR_PRIV_START, + /** To capture finger and store as feature file in + * RAM buffers char_buf_1 and char_buf_2. + */ + SENSOR_ATTR_R502A_CAPTURE = SENSOR_ATTR_PRIV_START, + /** create template from feature files at RAM buffers + * char_buf_1 & char_buf_2 and store a template data + * back in both RAM buffers char_buf_1 and char_buf_2. + */ + SENSOR_ATTR_R502A_TEMPLATE_CREATE, + /** Add template to the sensor record storage */ + /** + * @param val->val1 record index for template to be + * stored in the sensor device's flash + * library. + */ + SENSOR_ATTR_R502A_RECORD_ADD, /** To find requested data in record storage */ + /** + * @result val->val1 matched record index. + * val->val2 matching score. + */ SENSOR_ATTR_R502A_RECORD_FIND, /** To delete mentioned data from record storage */ + /** + * @param val->val1 record start index to be deleted. + * @param val->val2 number of records to be deleted. + */ SENSOR_ATTR_R502A_RECORD_DEL, /** To get available position to store data on record storage */ SENSOR_ATTR_R502A_RECORD_FREE_IDX, /** To empty the storage record*/ SENSOR_ATTR_R502A_RECORD_EMPTY, + /** To load template from storage to RAM buffer of sensor*/ + /** + * @param val->val1 record start index to be loaded in + * device internal RAM buffer. + */ + SENSOR_ATTR_R502A_RECORD_LOAD, + /** To template data stored in sensor's RAM buffer*/ + /** + * @result + * val->val1 match result. + * [R502A_FINGER_MATCH_FOUND or + * R502A_FINGER_MATCH_NOT_FOUND] + * val->val2 matching score. + */ + SENSOR_ATTR_R502A_COMPARE, }; #ifdef __cplusplus diff --git a/samples/sensor/grow_r502a/src/main.c b/samples/sensor/grow_r502a/src/main.c index 583d1ed3f6fadb..573a03aa5fb710 100644 --- a/samples/sensor/grow_r502a/src/main.c +++ b/samples/sensor/grow_r502a/src/main.c @@ -11,32 +11,54 @@ #include static bool enroll; -static struct sensor_value fid, val; +static struct sensor_value fid_get, count, find, del; -static void finger_match(const struct device *dev) +static void finger_find(const struct device *dev) { - struct sensor_value input; int ret; + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_CAPTURE, NULL); + if (ret != 0) { + printk("Capture fingerprint failed %d\n", ret); + return; + } + ret = sensor_attr_get(dev, SENSOR_CHAN_FINGERPRINT, - SENSOR_ATTR_R502A_RECORD_FIND, &input); + SENSOR_ATTR_R502A_RECORD_FIND, &find); if (ret != 0) { - printk("Sensor attr get failed %d\n", ret); + printk("Find fingerprint failed %d\n", ret); return; } - printk("Matched ID : %d\n", input.val1); - printk("confidence : %d\n", input.val2); + printk("Matched ID : %d\n", find.val1); + printk("confidence : %d\n", find.val2); } static void finger_enroll(const struct device *dev) { int ret; - ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, SENSOR_ATTR_R502A_RECORD_ADD, &fid); + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_CAPTURE, NULL); + if (ret != 0) { + printk("Capture fingerprint failed %d\n", ret); + return; + } + + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_TEMPLATE_CREATE, NULL); + if (ret != 0) { + printk("Create template failed %d\n", ret); + return; + } - if (ret == 0) { - printk("Fingerprint successfully stored at #%d\n", fid.val1); + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_RECORD_ADD, &fid_get); + if (!ret) { + printk("Fingerprint successfully stored at #%d\n", fid_get.val1); enroll = false; + } else { + printk("Fingerprint store failed %d\n", ret); } } @@ -49,12 +71,12 @@ static void template_count_get(const struct device *dev) printk("Sample Fetch Error %d\n", ret); return; } - ret = sensor_channel_get(dev, SENSOR_CHAN_FINGERPRINT, &val); + ret = sensor_channel_get(dev, SENSOR_CHAN_FINGERPRINT, &count); if (ret < 0) { printk("Channel Get Error %d\n", ret); return; } - printk("template count : %d\n", val.val1); + printk("template count : %d\n", count.val1); } static void trigger_handler(const struct device *dev, @@ -64,13 +86,12 @@ static void trigger_handler(const struct device *dev, finger_enroll(dev); } else { template_count_get(dev); - finger_match(dev); + finger_find(dev); } } int main(void) { - static struct sensor_value del, fid_get; int ret; const struct device *dev = DEVICE_DT_GET_ONE(hzgrow_r502a); @@ -103,9 +124,8 @@ int main(void) } printk("Fingerprint template free idx at ID #%d\n", fid_get.val1); - fid.val1 = fid_get.val1; printk("Waiting for valid finger to enroll as ID #%d\n" - "Place your finger\n", fid.val1); + "Place your finger\n", fid_get.val1); enroll = true; if (IS_ENABLED(CONFIG_GROW_R502A_TRIGGER)) { From be62a196336a878d35c5254f318acea676bc3f54 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0416/1389] drivers: sensor: grow_r502a: add built-in LED control Add LED control attribute for sensor device's built-in LED using zephyr's led driver APIs. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 135 +++++++++++++----- drivers/sensor/grow_r502a/grow_r502a.h | 44 ++++-- include/zephyr/drivers/sensor/grow_r502a.h | 7 + .../boards/esp32_devkitc_wroom_procpu.overlay | 5 + samples/sensor/grow_r502a/prj.conf | 1 + samples/sensor/grow_r502a/src/main.c | 39 +++++ 6 files changed, 182 insertions(+), 49 deletions(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 69b66ee5cb801e..5a8be3a7fca30f 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -4,14 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT hzgrow_r502a - #include #include #include #include #include #include +#include #include #include "grow_r502a.h" @@ -105,7 +104,7 @@ static void uart_cb_handler(const struct device *dev, void *user_data) } } -static int fps_led_control(const struct device *dev, struct led_params *led_control) +static int fps_led_control(const struct device *dev, struct r502a_led_params *led_control) { union r502a_packet rx_packet = {0}; char const led_ctrl_len = 5; @@ -246,10 +245,10 @@ static int fps_get_image(const struct device *dev) union r502a_packet rx_packet = {0}; char const get_img_len = 1; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; @@ -269,8 +268,8 @@ static int fps_get_image(const struct device *dev) fps_led_control(dev, &led_ctrl); LOG_DBG("Image taken"); } else { - led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; - led_ctrl.color_idx = LED_COLOR_RED; + led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = R502A_LED_COLOR_RED; fps_led_control(dev, &led_ctrl); LOG_ERR("Error getting image 0x%X", rx_packet.buf[R502A_CC_IDX]); return -EIO; @@ -340,10 +339,10 @@ static int fps_store_model(const struct device *dev, uint16_t id) char const store_model_len = 4; int ret = 0; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; @@ -364,8 +363,8 @@ static int fps_store_model(const struct device *dev, uint16_t id) } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { - led_ctrl.color_idx = LED_COLOR_BLUE; - led_ctrl.ctrl_code = LED_CTRL_FLASHING; + led_ctrl.color_idx = R502A_LED_COLOR_BLUE; + led_ctrl.ctrl_code = R502A_LED_CTRL_FLASHING; led_ctrl.cycle = 0x03; fps_led_control(dev, &led_ctrl); LOG_INF("Fingerprint stored! at ID #%d", id); @@ -455,10 +454,10 @@ static int fps_search(const struct device *dev, struct sensor_value *val) char const search_len = 6; int ret = 0; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; @@ -480,23 +479,23 @@ static int fps_search(const struct device *dev, struct sensor_value *val) } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { - led_ctrl.ctrl_code = LED_CTRL_FLASHING; - led_ctrl.color_idx = LED_COLOR_PURPLE; + led_ctrl.ctrl_code = R502A_LED_CTRL_FLASHING; + led_ctrl.color_idx = R502A_LED_COLOR_PURPLE; led_ctrl.cycle = 0x01; fps_led_control(dev, &led_ctrl); val->val1 = sys_get_be16(&rx_packet.data[1]); val->val2 = sys_get_be16(&rx_packet.data[3]); LOG_INF("Found a matching print! at ID #%d", val->val1); } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND_CC) { - led_ctrl.ctrl_code = LED_CTRL_BREATHING; - led_ctrl.color_idx = LED_COLOR_RED; + led_ctrl.ctrl_code = R502A_LED_CTRL_BREATHING; + led_ctrl.color_idx = R502A_LED_COLOR_RED; led_ctrl.cycle = 0x02; fps_led_control(dev, &led_ctrl); LOG_ERR("Did not find a match"); ret = -ENOENT; } else { - led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; - led_ctrl.color_idx = LED_COLOR_RED; + led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = R502A_LED_COLOR_RED; fps_led_control(dev, &led_ctrl); LOG_ERR("Error searching for image 0x%X", rx_packet.buf[R502A_CC_IDX]); ret = -EIO; @@ -549,10 +548,10 @@ static int fps_match_templates(const struct device *dev, struct sensor_value *va char const match_templates_len = 1; int ret = 0; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; @@ -581,8 +580,8 @@ static int fps_match_templates(const struct device *dev, struct sensor_value *va LOG_ERR("Fingerprint not matched"); ret = -ENOENT; } else { - led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; - led_ctrl.color_idx = LED_COLOR_RED; + led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = R502A_LED_COLOR_RED; fps_led_control(dev, &led_ctrl); LOG_ERR("Error Matching templates 0x%X", rx_packet.buf[R502A_CC_IDX]); @@ -627,10 +626,10 @@ static int fps_init(const struct device *dev) struct grow_r502a_data *drv_data = dev->data; int ret; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_FLASHING, - .color_idx = LED_COLOR_PURPLE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_FLASHING, + .color_idx = R502A_LED_COLOR_PURPLE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x02, }; @@ -678,6 +677,8 @@ static int grow_r502a_channel_get(const struct device *dev, enum sensor_channel static int grow_r502a_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { + struct grow_r502a_data *drv_data = dev->data; + if ((enum sensor_channel_grow_r502a)chan != SENSOR_CHAN_FINGERPRINT) { LOG_ERR("Channel not supported"); return -ENOTSUP; @@ -808,6 +809,53 @@ static const struct sensor_driver_api grow_r502a_api = { #endif }; +#ifdef CONFIG_LED +static int grow_r502a_led_set_color(const struct device *dev, uint32_t led, + uint8_t num_colors, const uint8_t *color) +{ + struct grow_r502a_data *drv_data = dev->data; + + if (!(*color)) { + LOG_ERR("invalid color code value"); + return -ENOTSUP; + } + drv_data->led_color = *color; + + return 0; +} + +static int grow_r502a_led_on(const struct device *dev, uint32_t led) +{ + struct grow_r502a_data *drv_data = dev->data; + + if (!drv_data->led_color) { + drv_data->led_color = R502A_LED_COLOR_BLUE; + } + + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_ON_ALWAYS, + .color_idx = drv_data->led_color, + }; + + return fps_led_control(dev, &led_ctrl); +} + +static int grow_r502a_led_off(const struct device *dev, uint32_t led) +{ + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_OFF_ALWAYS, + }; + + return fps_led_control(dev, &led_ctrl); +} + +static const struct led_driver_api grow_r502a_leds_api = { + .set_color = grow_r502a_led_set_color, + .on = grow_r502a_led_on, + .off = grow_r502a_led_off, +}; +#endif + #define GROW_R502A_INIT(index) \ static struct grow_r502a_data grow_r502a_data_##index; \ \ @@ -822,7 +870,20 @@ static const struct sensor_driver_api grow_r502a_api = { }; \ \ DEVICE_DT_INST_DEFINE(index, &grow_r502a_init, NULL, &grow_r502a_data_##index, \ - &grow_r502a_config_##index, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, &grow_r502a_api); + &grow_r502a_config_##index, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &grow_r502a_api); \ +#define GROW_R502A_LED_INIT(index) \ + DEVICE_DT_INST_DEFINE(index, NULL, NULL, &grow_r502a_data_##index, \ + &grow_r502a_config_##index, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, &grow_r502a_leds_api); \ + +#define DT_DRV_COMPAT hzgrow_r502a DT_INST_FOREACH_STATUS_OKAY(GROW_R502A_INIT) +#undef DT_DRV_COMPAT + +#ifdef CONFIG_LED +#define DT_DRV_COMPAT hzgrow_r502a_led +DT_INST_FOREACH_STATUS_OKAY(GROW_R502A_LED_INIT) +#undef DT_DRV_COMPAT +#endif diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index 00044359a0bade..9e26f863601297 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -131,21 +131,40 @@ #define R502A_DELAY 200 #define R502A_RETRY_DELAY 5 -#define LED_CTRL_BREATHING 0x01 -#define LED_CTRL_FLASHING 0x02 -#define LED_CTRL_ON_ALWAYS 0x03 -#define LED_CTRL_OFF_ALWAYS 0x04 -#define LED_CTRL_ON_GRADUALLY 0x05 -#define LED_CTRL_OFF_GRADUALLY 0x06 +/*LED glow control code*/ +enum r502a_led_ctrl_code { + R502A_LED_CTRL_BREATHING = 0x01, + R502A_LED_CTRL_FLASHING, + R502A_LED_CTRL_ON_ALWAYS, + R502A_LED_CTRL_OFF_ALWAYS, + R502A_LED_CTRL_ON_GRADUALLY, + R502A_LED_CTRL_OFF_GRADUALLY, +}; + +/* LED glow speed code + * if needed, use desired speed between 0-255 + */ +enum r502a_led_speed { + R502A_LED_SPEED_MAX = 0x00, + R502A_LED_SPEED_HALF = 0x50, + R502A_LED_SPEED_MIN = 0xFF, +}; -#define LED_SPEED_HALF 0x50 -#define LED_SPEED_FULL 0xFF +/* LED glowing cycle + * if needed, use desired cycle count between 1-255 + */ +enum r502a_led_cycle { + R502A_LED_CYCLE_INFINITE = 0x00, + R502A_LED_CYCLE_1, + R502A_LED_CYCLE_2, + R502A_LED_CYCLE_3, + R502A_LED_CYCLE_4, + R502A_LED_CYCLE_5, + R502A_LED_CYCLE_255 = 0xFF, +}; -#define LED_COLOR_RED 0x01 -#define LED_COLOR_BLUE 0x02 -#define LED_COLOR_PURPLE 0x03 -struct led_params { +struct r502a_led_params { uint8_t ctrl_code; uint8_t color_idx; uint8_t speed; /* Speed 0x00-0xff */ @@ -192,6 +211,7 @@ struct grow_r502a_data { struct k_sem uart_rx_sem; uint16_t template_count; + uint8_t led_color; }; struct grow_r502a_config { diff --git a/include/zephyr/drivers/sensor/grow_r502a.h b/include/zephyr/drivers/sensor/grow_r502a.h index fafcfd78559954..37bbeb486b42cc 100644 --- a/include/zephyr/drivers/sensor/grow_r502a.h +++ b/include/zephyr/drivers/sensor/grow_r502a.h @@ -13,6 +13,13 @@ extern "C" { #include +/*LED color code*/ +enum r502a_led_color_idx { + R502A_LED_COLOR_RED = 0x01, + R502A_LED_COLOR_BLUE, + R502A_LED_COLOR_PURPLE, +}; + enum sensor_channel_grow_r502a { /** Fingerprint template count, ID number for enrolling and searching*/ SENSOR_CHAN_FINGERPRINT = SENSOR_CHAN_PRIV_START, diff --git a/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay b/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay index 2fa0bb3197f777..7add14e5350cb7 100644 --- a/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay +++ b/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay @@ -25,4 +25,9 @@ int-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; }; }; + + led { + compatible = "hzgrow,r502a-led"; + status = "okay"; + }; }; diff --git a/samples/sensor/grow_r502a/prj.conf b/samples/sensor/grow_r502a/prj.conf index 0f507ebe69d09f..360ccc6182a250 100644 --- a/samples/sensor/grow_r502a/prj.conf +++ b/samples/sensor/grow_r502a/prj.conf @@ -2,4 +2,5 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_SENSOR=y +CONFIG_LED=y CONFIG_GROW_R502A_TRIGGER_OWN_THREAD=y diff --git a/samples/sensor/grow_r502a/src/main.c b/samples/sensor/grow_r502a/src/main.c index 573a03aa5fb710..a11332b469eff8 100644 --- a/samples/sensor/grow_r502a/src/main.c +++ b/samples/sensor/grow_r502a/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include static bool enroll; static struct sensor_value fid_get, count, find, del; @@ -79,6 +80,38 @@ static void template_count_get(const struct device *dev) printk("template count : %d\n", count.val1); } +static int r502a_led(void) +{ + int ret; + const int led_num = 0; + const int led_color_a_inst = 1; + uint8_t led_color = R502A_LED_COLOR_PURPLE; + const struct device *led_dev = DEVICE_DT_GET_ONE(hzgrow_r502a_led); + + if (led_dev == NULL) { + printk("Error: no device found\n"); + return -ENODEV; + } + + if (!device_is_ready(led_dev)) { + printk("Error: Device %s is not ready\n", led_dev->name); + return -EAGAIN; + } + + ret = led_set_color(led_dev, led_num, led_color_a_inst, &led_color); + if (ret != 0) { + printk("led set color failed %d\n", ret); + return -1; + } + + ret = led_on(led_dev, led_num); + if (ret != 0) { + printk("led on failed %d\n", ret); + return -1; + } + return 0; +} + static void trigger_handler(const struct device *dev, const struct sensor_trigger *trigger) { @@ -106,6 +139,12 @@ int main(void) return 0; } + ret = r502a_led(); + if (ret != 0) { + printk("Error: device led failed to set %d", ret); + return 0; + } + template_count_get(dev); del.val1 = 3; From 890d65125eb90148b03b0fe648d3b62611942095 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0417/1389] drivers: sensor: grow_r502a: modified Tx and Rx data handling improvised uart tx and rx handler functions to handle large chunk of fingerprint data from/to the sensor. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 163 ++++++++++++++++++------- drivers/sensor/grow_r502a/grow_r502a.h | 20 ++- 2 files changed, 130 insertions(+), 53 deletions(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 5a8be3a7fca30f..caffa067ff892c 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -18,35 +18,52 @@ #include LOG_MODULE_REGISTER(GROW_R502A, CONFIG_SENSOR_LOG_LEVEL); -static void transceive_packet(const struct device *dev, union r502a_packet *tx_packet, +static int transceive_packet(const struct device *dev, union r502a_packet *tx_packet, union r502a_packet *rx_packet, char const data_len) { const struct grow_r502a_config *cfg = dev->config; struct grow_r502a_data *drv_data = dev->data; - uint16_t check_sum, pkg_len; - pkg_len = data_len + R502A_CHECKSUM_LEN; - check_sum = (pkg_len >> 8) + (pkg_len & 0xFF) + tx_packet->pid; + if (tx_packet) { + uint16_t check_sum, pkg_len; - sys_put_be16(R502A_STARTCODE, tx_packet->start); - sys_put_be32(cfg->comm_addr, tx_packet->addr); - sys_put_be16(pkg_len, tx_packet->len); - for (int i = 0; i < data_len; i++) { - check_sum += tx_packet->data[i]; - } - sys_put_be16(check_sum, &tx_packet->buf[data_len + R502A_HEADER_LEN]); + pkg_len = data_len + R502A_CHECKSUM_LEN; + check_sum = (pkg_len >> 8) + (pkg_len & 0xFF) + tx_packet->pid; + + tx_packet->start = sys_cpu_to_be16(R502A_STARTCODE); + tx_packet->addr = sys_cpu_to_be32(cfg->comm_addr); + tx_packet->len = sys_cpu_to_be16(pkg_len); - drv_data->tx_buf.len = pkg_len + R502A_HEADER_LEN; - drv_data->tx_buf.data = tx_packet->buf; + for (int i = 0; i < data_len; i++) { + check_sum += tx_packet->data[i]; + } + sys_put_be16(check_sum, &tx_packet->buf[data_len + R502A_HEADER_LEN]); - drv_data->rx_buf.data = rx_packet->buf; + drv_data->tx_buf.len = pkg_len + R502A_HEADER_LEN; + drv_data->tx_buf.data = tx_packet->buf; - LOG_HEXDUMP_DBG(drv_data->tx_buf.data, drv_data->tx_buf.len, "TX"); + LOG_HEXDUMP_DBG(drv_data->tx_buf.data, drv_data->tx_buf.len, "TX"); - uart_irq_rx_disable(cfg->dev); - uart_irq_tx_enable(cfg->dev); + uart_irq_tx_enable(cfg->dev); + + if (k_sem_take(&drv_data->uart_tx_sem, K_MSEC(1500)) != 0) { + LOG_ERR("Tx data timeout"); + return -ETIMEDOUT; + } + } + + if (rx_packet) { + drv_data->rx_buf.data = rx_packet->buf; + drv_data->rx_buf.len = 0; + drv_data->pkt_len = R502A_HEADER_LEN; + uart_irq_rx_enable(cfg->dev); + if (k_sem_take(&drv_data->uart_rx_sem, K_MSEC(1500)) != 0) { + LOG_ERR("Rx data timeout"); + return -ETIMEDOUT; + } + } - k_sem_take(&drv_data->uart_rx_sem, K_FOREVER); + return 0; } static void uart_cb_tx_handler(const struct device *dev) @@ -54,21 +71,18 @@ static void uart_cb_tx_handler(const struct device *dev) const struct grow_r502a_config *config = dev->config; struct grow_r502a_data *drv_data = dev->data; int sent = 0; - uint8_t retries = 3; - while (drv_data->tx_buf.len) { - sent = uart_fifo_fill(config->dev, &drv_data->tx_buf.data[sent], + if (drv_data->tx_buf.len > 0) { + sent = uart_fifo_fill(config->dev, drv_data->tx_buf.data, drv_data->tx_buf.len); + drv_data->tx_buf.data += sent; drv_data->tx_buf.len -= sent; } - while (retries--) { - if (uart_irq_tx_complete(config->dev)) { - uart_irq_tx_disable(config->dev); - drv_data->rx_buf.len = 0; - uart_irq_rx_enable(config->dev); - break; - } + if (!drv_data->tx_buf.len && uart_irq_tx_complete(config->dev) > 0) { + uart_irq_tx_disable(config->dev); + k_sem_give(&drv_data->uart_tx_sem); + return; } } @@ -76,7 +90,7 @@ static void uart_cb_handler(const struct device *dev, void *user_data) { const struct device *uart_dev = user_data; struct grow_r502a_data *drv_data = uart_dev->data; - int len, pkt_sz = 0; + int len = 0; int offset = drv_data->rx_buf.len; if ((uart_irq_update(dev) > 0) && (uart_irq_is_pending(dev) > 0)) { @@ -86,18 +100,24 @@ static void uart_cb_handler(const struct device *dev, void *user_data) while (uart_irq_rx_ready(dev)) { len = uart_fifo_read(dev, &drv_data->rx_buf.data[offset], - R502A_BUF_SIZE - offset); + drv_data->pkt_len); offset += len; drv_data->rx_buf.len = offset; - if (offset >= R502A_HEADER_LEN) { - pkt_sz = R502A_HEADER_LEN + - drv_data->rx_buf.data[R502A_HEADER_LEN-1]; + if (drv_data->pkt_len != len) { + drv_data->pkt_len -= len; + continue; } - if (offset < pkt_sz) { + + if (offset == R502A_HEADER_LEN) { + drv_data->pkt_len = sys_get_be16( + &drv_data->rx_buf.data[R502A_PKG_LEN_IDX] + ); continue; } + LOG_HEXDUMP_DBG(drv_data->rx_buf.data, offset, "RX"); + uart_irq_rx_disable(dev); k_sem_give(&drv_data->uart_rx_sem); break; } @@ -108,6 +128,7 @@ static int fps_led_control(const struct device *dev, struct r502a_led_params *le { union r502a_packet rx_packet = {0}; char const led_ctrl_len = 5; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, @@ -115,7 +136,10 @@ static int fps_led_control(const struct device *dev, struct r502a_led_params *le led_control->speed, led_control->color_idx, led_control->cycle} }; - transceive_packet(dev, &tx_packet, &rx_packet, led_ctrl_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, led_ctrl_len); + if (ret != 0) { + return ret; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -137,6 +161,7 @@ static int fps_verify_password(const struct device *dev) { union r502a_packet rx_packet = {0}; char const verify_pwd_len = 5; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, @@ -145,7 +170,10 @@ static int fps_verify_password(const struct device *dev) sys_put_be32(R502A_DEFAULT_PASSWORD, &tx_packet.data[1]); - transceive_packet(dev, &tx_packet, &rx_packet, verify_pwd_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, verify_pwd_len); + if (ret != 0) { + return ret; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -167,13 +195,17 @@ static int fps_get_template_count(const struct device *dev) struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const get_temp_cnt_len = 1; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, .data = {R502A_TEMPLATECOUNT}, }; - transceive_packet(dev, &tx_packet, &rx_packet, get_temp_cnt_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, get_temp_cnt_len); + if (ret != 0) { + return ret; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -206,7 +238,10 @@ static int fps_read_template_table(const struct device *dev, uint32_t *free_idx) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, temp_table_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, temp_table_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -244,6 +279,7 @@ static int fps_get_image(const struct device *dev) { union r502a_packet rx_packet = {0}; char const get_img_len = 1; + int ret = 0; struct r502a_led_params led_ctrl = { .ctrl_code = R502A_LED_CTRL_BREATHING, @@ -257,7 +293,10 @@ static int fps_get_image(const struct device *dev) .data = {R502A_GENIMAGE}, }; - transceive_packet(dev, &tx_packet, &rx_packet, get_img_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, get_img_len); + if (ret != 0) { + return ret; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -282,13 +321,17 @@ static int fps_image_to_char(const struct device *dev, uint8_t char_buf_idx) { union r502a_packet rx_packet = {0}; char const img_to_char_len = 2; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, .data = {R502A_IMAGE2TZ, char_buf_idx} }; - transceive_packet(dev, &tx_packet, &rx_packet, img_to_char_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, img_to_char_len); + if (ret != 0) { + return ret; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -309,13 +352,17 @@ static int fps_create_model(const struct device *dev) { union r502a_packet rx_packet = {0}; char const create_model_len = 1; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, .data = {R502A_REGMODEL} }; - transceive_packet(dev, &tx_packet, &rx_packet, create_model_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, create_model_len); + if (ret != 0) { + return ret; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -354,7 +401,10 @@ static int fps_store_model(const struct device *dev, uint16_t id) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, store_model_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, store_model_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -393,7 +443,10 @@ static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t coun k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, delete_model_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, delete_model_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -426,7 +479,10 @@ static int fps_empty_db(const struct device *dev) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, empty_db_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, empty_db_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -470,7 +526,10 @@ static int fps_search(const struct device *dev, struct sensor_value *val) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, search_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, search_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -520,7 +579,10 @@ static int fps_load_template(const struct device *dev, uint16_t id) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, load_tmp_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, load_tmp_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -562,7 +624,10 @@ static int fps_match_templates(const struct device *dev, struct sensor_value *va k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, match_templates_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, match_templates_len); + if (ret != 0) { + goto unlock; + } if (rx_packet.pid != R502A_ACK_PACKET) { LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); @@ -784,9 +849,13 @@ static int grow_r502a_init(const struct device *dev) k_mutex_init(&drv_data->lock); k_sem_init(&drv_data->uart_rx_sem, 0, 1); + k_sem_init(&drv_data->uart_tx_sem, 0, 1); uart_irq_callback_user_data_set(cfg->dev, uart_cb_handler, (void *)dev); + uart_irq_rx_disable(cfg->dev); + uart_irq_tx_disable(cfg->dev); + #ifdef CONFIG_GROW_R502A_TRIGGER ret = grow_r502a_init_interrupt(dev); diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index 9e26f863601297..78db4913fc1293 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -112,6 +112,8 @@ #define R502A_PKG_LEN_IDX 7 #define R502A_CC_IDX 9 /* Confirmation code index*/ +#define R502A_COMMON_ACK_LEN 12 + #define R502A_STARTCODE_LEN 2 #define R502A_ADDRESS_LEN 4 #define R502A_PKG_LEN 2 @@ -120,10 +122,14 @@ #define R502A_CHAR_BUF_1 1 #define R502A_CHAR_BUF_2 2 +#define R502A_CHAR_BUF_TOTAL 2 + #define R502A_CHAR_BUF_SIZE 384 /* Maximum size of characteristic value buffer*/ #define R502A_TEMPLATE_SIZE 768 /* Maximum size of template, twice of CHAR_BUF*/ -#define R502A_MAX_BUF_SIZE 779 /*sum of checksum, header and template sizes*/ #define R502A_BUF_SIZE 64 + +#define R502A_MAX_BUF_SIZE R502A_BUF_SIZE + R502A_COMMON_ACK_LEN + #define R502A_TEMPLATES_PER_PAGE 256 #define R502A_TEMP_TABLE_BUF_SIZE 32 #define R502A_DELETE_COUNT_OFFSET 1 @@ -173,14 +179,14 @@ struct r502a_led_params { union r502a_packet { struct { - uint8_t start[R502A_STARTCODE_LEN]; - uint8_t addr[R502A_ADDRESS_LEN]; + uint16_t start; + uint32_t addr; uint8_t pid; - uint8_t len[R502A_PKG_LEN]; + uint16_t len; uint8_t data[R502A_BUF_SIZE]; - }; + } __packed; - uint8_t buf[R502A_BUF_SIZE]; + uint8_t buf[R502A_MAX_BUF_SIZE]; }; struct r502a_buf { @@ -206,8 +212,10 @@ struct grow_r502a_data { struct r502a_buf tx_buf; struct r502a_buf rx_buf; + uint16_t pkt_len; struct k_mutex lock; + struct k_sem uart_tx_sem; struct k_sem uart_rx_sem; uint16_t template_count; From fd1f7d7cae79fd25566deb7226031de6d4b62972 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0418/1389] drivers: sensor: grow_r502a: add set/read system parameter Add functionality for read and set system parameter of sensor device. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/Kconfig | 9 ++ drivers/sensor/grow_r502a/grow_r502a.c | 122 +++++++++++++++++++++ drivers/sensor/grow_r502a/grow_r502a.h | 5 +- include/zephyr/drivers/sensor/grow_r502a.h | 48 ++++++++ samples/sensor/grow_r502a/prj.conf | 3 + samples/sensor/grow_r502a/src/main.c | 21 +++- 6 files changed, 204 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/grow_r502a/Kconfig b/drivers/sensor/grow_r502a/Kconfig index 53c31f3c80407b..35297b90b655f6 100644 --- a/drivers/sensor/grow_r502a/Kconfig +++ b/drivers/sensor/grow_r502a/Kconfig @@ -13,6 +13,15 @@ menuconfig GROW_R502A if GROW_R502A +config R502A_DATA_PKT_SIZE + int "Template data packet size" + default 128 + help + Template data packet size for upload and download + to the sensor device. + valid values are: + 32, 64, 128, 256. + choice prompt "Trigger mode" default GROW_R502A_TRIGGER_NONE diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index caffa067ff892c..a92477d2d98c52 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "grow_r502a.h" @@ -124,6 +125,103 @@ static void uart_cb_handler(const struct device *dev, void *user_data) } } +/** + * @brief Set sensor device's basic parameters like baud rate, security level + * and data package length. + */ +static int fps_set_sys_param(const struct device *dev, const struct sensor_value *val) +{ + union r502a_packet rx_packet = {0}; + int ret = 0; + char const set_sys_param_len = 3; + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = { R502A_SETSYSPARAM, val->val1, val->val2} + }; + + ret = transceive_packet(dev, &tx_packet, &rx_packet, set_sys_param_len); + if (ret != 0) { + return ret; + } + + if (rx_packet.pid != R502A_ACK_PACKET) { + LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); + return -EIO; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("R502A set system parameter success"); + } else { + LOG_ERR("R502A set system parameter error %d", rx_packet.buf[R502A_CC_IDX]); + return -EIO; + } + + return 0; +} + +int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val) +{ + struct grow_r502a_data *drv_data = dev->data; + + union r502a_packet rx_packet = {0}; + int offset = 0, ret = 0; + char const read_sys_param_len = 1; + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_READSYSPARAM} + }; + + k_mutex_lock(&drv_data->lock, K_FOREVER); + + ret = transceive_packet(dev, &tx_packet, &rx_packet, read_sys_param_len); + if (ret != 0) { + goto unlock; + } + + if (rx_packet.pid != R502A_ACK_PACKET) { + LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); + ret = -EIO; + goto unlock; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("R502A read system parameter success"); + } else { + LOG_ERR("R502A read system parameter error %d", rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + goto unlock; + } + + val->status_reg = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, status_reg) + 1] + ); + val->system_id = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, system_id) + 1] + ); + val->lib_size = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, lib_size) + 1] + ); + val->sec_level = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, sec_level) + 1] + ); + val->addr = sys_get_be32( + &rx_packet.data[offsetof(struct r502a_sys_param, addr) + 1] + ); + offset = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, data_pkt_size) + 1] + ); + val->data_pkt_size = 32 * (1 << offset); + val->baud = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, baud) + 1] + ) * 9600; + +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; +} + static int fps_led_control(const struct device *dev, struct r502a_led_params *led_control) { union r502a_packet rx_packet = {0}; @@ -689,6 +787,7 @@ static int fps_capture(const struct device *dev) static int fps_init(const struct device *dev) { struct grow_r502a_data *drv_data = dev->data; + struct sensor_value val; int ret; struct r502a_led_params led_ctrl = { @@ -705,6 +804,13 @@ static int fps_init(const struct device *dev) goto unlock; } + val.val1 = R502A_DATA_PKG_LEN; + val.val2 = LOG2(CONFIG_R502A_DATA_PKT_SIZE >> 5); + ret = fps_set_sys_param(dev, &val); + if (ret != 0) { + goto unlock; + } + ret = fps_led_control(dev, &led_ctrl); unlock: @@ -762,6 +868,22 @@ static int grow_r502a_attr_set(const struct device *dev, enum sensor_channel cha return fps_empty_db(dev); case SENSOR_ATTR_R502A_RECORD_LOAD: return fps_load_template(dev, val->val1); + case SENSOR_ATTR_R502A_SYS_PARAM: { + int ret = 0; + + if (val->val1 == R502A_DATA_PKG_LEN) { + LOG_ERR("Data package length should not be runtime configurable"); + return -EINVAL; + }; + k_mutex_lock(&drv_data->lock, K_FOREVER); + ret = fps_set_sys_param(dev, val); + if (ret != 0) { + k_mutex_unlock(&drv_data->lock); + return ret; + } + k_mutex_unlock(&drv_data->lock); + return 0; + } default: LOG_ERR("Sensor attribute not supported"); return -ENOTSUP; diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index 78db4913fc1293..72130525ce1367 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -126,9 +126,8 @@ #define R502A_CHAR_BUF_SIZE 384 /* Maximum size of characteristic value buffer*/ #define R502A_TEMPLATE_SIZE 768 /* Maximum size of template, twice of CHAR_BUF*/ -#define R502A_BUF_SIZE 64 -#define R502A_MAX_BUF_SIZE R502A_BUF_SIZE + R502A_COMMON_ACK_LEN +#define R502A_MAX_BUF_SIZE (CONFIG_R502A_DATA_PKT_SIZE + R502A_COMMON_ACK_LEN) #define R502A_TEMPLATES_PER_PAGE 256 #define R502A_TEMP_TABLE_BUF_SIZE 32 @@ -183,7 +182,7 @@ union r502a_packet { uint32_t addr; uint8_t pid; uint16_t len; - uint8_t data[R502A_BUF_SIZE]; + uint8_t data[CONFIG_R502A_DATA_PKT_SIZE]; } __packed; uint8_t buf[R502A_MAX_BUF_SIZE]; diff --git a/include/zephyr/drivers/sensor/grow_r502a.h b/include/zephyr/drivers/sensor/grow_r502a.h index 37bbeb486b42cc..4a9cd7fc372d16 100644 --- a/include/zephyr/drivers/sensor/grow_r502a.h +++ b/include/zephyr/drivers/sensor/grow_r502a.h @@ -20,6 +20,43 @@ enum r502a_led_color_idx { R502A_LED_COLOR_PURPLE, }; +#define R502A_BAUD_9600 1 +#define R502A_BAUD_19200 2 +#define R502A_BAUD_38400 4 +#define R502A_BAUD_57600 6 +#define R502A_BAUD_115200 12 + +enum r502a_sec_level { + R502A_SEC_LEVEL_1 = 1, + R502A_SEC_LEVEL_2, + R502A_SEC_LEVEL_3, + R502A_SEC_LEVEL_4, + R502A_SEC_LEVEL_5 +}; + +enum r502a_data_len { + R502A_PKG_LEN_32, + R502A_PKG_LEN_64, + R502A_PKG_LEN_128, + R502A_PKG_LEN_256 +}; + +enum r502a_sys_param_set { + R502A_BAUD_RATE = 4, + R502A_SECURITY_LEVEL, + R502A_DATA_PKG_LEN +}; + +struct r502a_sys_param { + uint16_t status_reg; + uint16_t system_id; + uint16_t lib_size; + uint16_t sec_level; + uint32_t addr; + uint16_t data_pkt_size; + uint32_t baud; +} __packed; + enum sensor_channel_grow_r502a { /** Fingerprint template count, ID number for enrolling and searching*/ SENSOR_CHAN_FINGERPRINT = SENSOR_CHAN_PRIV_START, @@ -78,8 +115,19 @@ enum sensor_attribute_grow_r502a { * val->val2 matching score. */ SENSOR_ATTR_R502A_COMPARE, + /** To read and write device's system parameters */ + /** sensor_attr_set + * @param val->val1 parameter number from enum r502a_sys_param_set. + * @param val->val2 content to be written for the respective parameter. + */ + /** sensor_attr_get + * @result val->ex.data buffer holds the system parameter values. + */ + SENSOR_ATTR_R502A_SYS_PARAM, }; +int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val); + #ifdef __cplusplus } #endif diff --git a/samples/sensor/grow_r502a/prj.conf b/samples/sensor/grow_r502a/prj.conf index 360ccc6182a250..5727d4c0ceb78e 100644 --- a/samples/sensor/grow_r502a/prj.conf +++ b/samples/sensor/grow_r502a/prj.conf @@ -4,3 +4,6 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_SENSOR=y CONFIG_LED=y CONFIG_GROW_R502A_TRIGGER_OWN_THREAD=y + +# Minimum stack size needed +CONFIG_GROW_R502A_THREAD_STACK_SIZE=1536 diff --git a/samples/sensor/grow_r502a/src/main.c b/samples/sensor/grow_r502a/src/main.c index a11332b469eff8..da8923e1fc27bc 100644 --- a/samples/sensor/grow_r502a/src/main.c +++ b/samples/sensor/grow_r502a/src/main.c @@ -12,7 +12,7 @@ #include static bool enroll; -static struct sensor_value fid_get, count, find, del; +static struct sensor_value fid_get, count, find, del, param; static void finger_find(const struct device *dev) { @@ -123,6 +123,23 @@ static void trigger_handler(const struct device *dev, } } +static void read_fps_param(const struct device *dev) +{ + int ret = 0; + struct r502a_sys_param res; + + ret = r502a_read_sys_param(dev, &res); + if (ret != 0) { + printk("r502a read system parameter failed %d\n", ret); + return; + } + + printk("baud %d\n", res.baud); + printk("addr 0x%x\n", res.addr); + printk("lib_size %d\n", res.lib_size); + printk("data_pkt_size %d\n", res.data_pkt_size); +} + int main(void) { int ret; @@ -147,6 +164,8 @@ int main(void) template_count_get(dev); + read_fps_param(dev); + del.val1 = 3; ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, SENSOR_ATTR_R502A_RECORD_DEL, &del); if (ret != 0) { From 339f986d6de88cb20a526b484cf0792f2e9c6bdd Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0419/1389] drivers: sensor: grow_r502a: add upload and download template 1. Add functionality for upload and download fingerprint template data of the R502A fingerprint sensor device. 2. change data type for data_len parameter of transceive_packet function to uint16_t as it may hold value 256 for dowload template data to sensor. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 131 ++++++++++++++++++++- drivers/sensor/grow_r502a/grow_r502a.h | 1 + include/zephyr/drivers/sensor/grow_r502a.h | 7 ++ 3 files changed, 138 insertions(+), 1 deletion(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index a92477d2d98c52..8bd073655bab09 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -20,7 +20,7 @@ LOG_MODULE_REGISTER(GROW_R502A, CONFIG_SENSOR_LOG_LEVEL); static int transceive_packet(const struct device *dev, union r502a_packet *tx_packet, - union r502a_packet *rx_packet, char const data_len) + union r502a_packet *rx_packet, uint16_t data_len) { const struct grow_r502a_config *cfg = dev->config; struct grow_r502a_data *drv_data = dev->data; @@ -784,6 +784,135 @@ static int fps_capture(const struct device *dev) return ret; } +/** + * @brief upload template from sensor device's RAM buffer 1 to controller. + * + * @result temp->data holds the template to be uploaded to controller. + * temp->len holds the length of the template. + */ +int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp) +{ + struct grow_r502a_data *drv_data = dev->data; + union r502a_packet rx_packet = {0}; + char const upload_temp_len = 2; + int ret = 0, idx = 0; + + if (!temp->data || (temp->len < R502A_TEMPLATE_MAX_SIZE)) { + LOG_ERR("Invalid temp data"); + return -EINVAL; + } + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_UPCHAR, R502A_CHAR_BUF_1} + }; + + k_mutex_lock(&drv_data->lock, K_FOREVER); + + ret = transceive_packet(dev, &tx_packet, &rx_packet, upload_temp_len); + if (ret != 0) { + goto unlock; + } + + if (rx_packet.pid != R502A_ACK_PACKET) { + LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); + ret = -EIO; + goto unlock; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("Upload to host controller"); + } else { + LOG_ERR("Error uploading template 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + goto unlock; + } + + do { + ret = transceive_packet(dev, NULL, &rx_packet, 0); + if (ret != 0) { + goto unlock; + } + + memcpy(&temp->data[idx], &rx_packet.data, + sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN); + idx += sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN; + } while (rx_packet.pid != R502A_END_DATA_PACKET); + + temp->len = idx; + +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; +} + +/** + * @brief download template from controller to sensor device's RAM buffer. + * @Notes char_buf_id - other than value 1 will be considered as value 2 + * by R502A sensor. + */ +int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id, + const struct r502a_template *temp) +{ + struct grow_r502a_data *drv_data = dev->data; + union r502a_packet rx_packet = {0}; + char const down_temp_len = 2; + int ret = 0, i = 0; + + if (!temp->data || (temp->len < R502A_TEMPLATE_MAX_SIZE)) { + LOG_ERR("Invalid temp data"); + return -EINVAL; + } + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_DOWNCHAR, char_buf_id} + }; + + k_mutex_lock(&drv_data->lock, K_FOREVER); + + ret = transceive_packet(dev, &tx_packet, &rx_packet, down_temp_len); + if (ret != 0) { + goto unlock; + } + + if (rx_packet.pid != R502A_ACK_PACKET) { + LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); + ret = -EIO; + goto unlock; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("Download to R502A sensor"); + } else { + LOG_ERR("Error downloading template 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + goto unlock; + } + + while (i < (R502A_TEMPLATE_MAX_SIZE - CONFIG_R502A_DATA_PKT_SIZE)) { + tx_packet.pid = R502A_DATA_PACKET; + memcpy(tx_packet.data, &temp->data[i], CONFIG_R502A_DATA_PKT_SIZE); + + ret = transceive_packet(dev, &tx_packet, NULL, CONFIG_R502A_DATA_PKT_SIZE); + if (ret != 0) { + goto unlock; + } + + i += CONFIG_R502A_DATA_PKT_SIZE; + } + + memcpy(tx_packet.data, &temp->data[i], (R502A_TEMPLATE_MAX_SIZE - i)); + tx_packet.pid = R502A_END_DATA_PACKET; + ret = transceive_packet(dev, &tx_packet, NULL, (R502A_TEMPLATE_MAX_SIZE - i)); + +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; +} + static int fps_init(const struct device *dev) { struct grow_r502a_data *drv_data = dev->data; diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index 72130525ce1367..154693f5701bfd 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -126,6 +126,7 @@ #define R502A_CHAR_BUF_SIZE 384 /* Maximum size of characteristic value buffer*/ #define R502A_TEMPLATE_SIZE 768 /* Maximum size of template, twice of CHAR_BUF*/ +#define R502A_TEMPLATE_MAX_SIZE (R502A_CHAR_BUF_TOTAL * R502A_TEMPLATE_SIZE) #define R502A_MAX_BUF_SIZE (CONFIG_R502A_DATA_PKT_SIZE + R502A_COMMON_ACK_LEN) diff --git a/include/zephyr/drivers/sensor/grow_r502a.h b/include/zephyr/drivers/sensor/grow_r502a.h index 4a9cd7fc372d16..81ee68ca714648 100644 --- a/include/zephyr/drivers/sensor/grow_r502a.h +++ b/include/zephyr/drivers/sensor/grow_r502a.h @@ -57,6 +57,10 @@ struct r502a_sys_param { uint32_t baud; } __packed; +struct r502a_template { + uint8_t *data; + size_t len; +}; enum sensor_channel_grow_r502a { /** Fingerprint template count, ID number for enrolling and searching*/ SENSOR_CHAN_FINGERPRINT = SENSOR_CHAN_PRIV_START, @@ -127,6 +131,9 @@ enum sensor_attribute_grow_r502a { }; int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val); +int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp); +int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id, + const struct r502a_template *temp); #ifdef __cplusplus } From ee38e156e5011ac3c107325ecf49ae6dffcc3b0d Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0420/1389] drivers: sensor: grow_r502a: add RX packet validation Add RX packet validator where header, address, pid and checksum bytes are verified and validated on every functions. Signed-off-by: Dinesh Kumar K --- drivers/sensor/grow_r502a/grow_r502a.c | 155 ++++++++++++++++--------- 1 file changed, 102 insertions(+), 53 deletions(-) diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 8bd073655bab09..15714314b95f4c 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -67,6 +67,61 @@ static int transceive_packet(const struct device *dev, union r502a_packet *tx_pa return 0; } +static int r502a_validate_rx_packet(union r502a_packet *rx_packet) +{ + uint16_t recv_cks = 0, calc_cks = 0; + uint8_t cks_start_idx; + + if (sys_be16_to_cpu(rx_packet->start) == R502A_STARTCODE) { + LOG_DBG("startcode matched 0x%X", sys_be16_to_cpu(rx_packet->start)); + } else { + LOG_ERR("startcode didn't match 0x%X", sys_be16_to_cpu(rx_packet->start)); + return -EINVAL; + } + + if (sys_be32_to_cpu(rx_packet->addr) == R502A_DEFAULT_ADDRESS) { + LOG_DBG("Address matched 0x%X", sys_be32_to_cpu(rx_packet->addr)); + } else { + LOG_ERR("Address didn't match 0x%X", sys_be32_to_cpu(rx_packet->addr)); + return -EINVAL; + } + + switch (rx_packet->pid) { + case R502A_DATA_PACKET: + LOG_DBG("Data Packet Received 0x%X", rx_packet->pid); + break; + case R502A_END_DATA_PACKET: + LOG_DBG("End of Data Packet Received 0x%X", rx_packet->pid); + break; + case R502A_ACK_PACKET: + LOG_DBG("Acknowledgment Packet Received 0x%X", rx_packet->pid); + break; + default: + LOG_ERR("Error Package ID 0x%X", rx_packet->pid); + return -EINVAL; + } + + cks_start_idx = sys_be16_to_cpu(rx_packet->len) - R502A_CHECKSUM_LEN; + + recv_cks = sys_get_be16(&rx_packet->data[cks_start_idx]); + + calc_cks += rx_packet->pid + (sys_be16_to_cpu(rx_packet->len) >> 8) + + (sys_be16_to_cpu(rx_packet->len) & 0xFF); + + for (int i = 0; i < cks_start_idx; i++) { + calc_cks += rx_packet->data[i]; + } + + if (recv_cks == calc_cks) { + LOG_DBG("Checksum matched calculated 0x%x received 0x%x", calc_cks, recv_cks); + } else { + LOG_ERR("Checksum mismatch calculated 0x%x received 0x%x", calc_cks, recv_cks); + return -EINVAL; + } + + return 0; +} + static void uart_cb_tx_handler(const struct device *dev) { const struct grow_r502a_config *config = dev->config; @@ -145,9 +200,9 @@ static int fps_set_sys_param(const struct device *dev, const struct sensor_value return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -180,9 +235,8 @@ int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -239,9 +293,9 @@ static int fps_led_control(const struct device *dev, struct r502a_led_params *le return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -273,15 +327,15 @@ static int fps_verify_password(const struct device *dev) return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { LOG_DBG("Correct password, R502A verified"); } else { - LOG_ERR("Package receive error 0x%X", rx_packet.buf[R502A_CC_IDX]); + LOG_ERR("Password verification error 0x%X", rx_packet.buf[R502A_CC_IDX]); return -EIO; } @@ -305,9 +359,9 @@ static int fps_get_template_count(const struct device *dev) return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -341,11 +395,9 @@ static int fps_read_template_table(const struct device *dev, uint32_t *free_idx) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; - } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -396,9 +448,9 @@ static int fps_get_image(const struct device *dev) return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -431,9 +483,9 @@ static int fps_image_to_char(const struct device *dev, uint8_t char_buf_idx) return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -462,9 +514,9 @@ static int fps_create_model(const struct device *dev) return ret; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -504,9 +556,8 @@ static int fps_store_model(const struct device *dev, uint16_t id) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -546,9 +597,8 @@ static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t coun goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -582,9 +632,8 @@ static int fps_empty_db(const struct device *dev) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -629,9 +678,8 @@ static int fps_search(const struct device *dev, struct sensor_value *val) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -682,9 +730,8 @@ static int fps_load_template(const struct device *dev, uint16_t id) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -727,9 +774,8 @@ static int fps_match_templates(const struct device *dev, struct sensor_value *va goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -814,9 +860,8 @@ int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp) goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -835,6 +880,11 @@ int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp) goto unlock; } + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; + } + memcpy(&temp->data[idx], &rx_packet.data, sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN); idx += sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN; @@ -877,9 +927,8 @@ int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id, goto unlock; } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } From 7652eac3dda5ccd84ca0dabf896d811ea63a88a5 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0421/1389] samples: sensor: Modified Readme for grow_r502a Modified readme for grow_r502a sample w.r.t latest changes on driver like attributes and LED controlling via zephyr LED subsystem APIs. Signed-off-by: Dinesh Kumar K --- samples/sensor/grow_r502a/README.rst | 37 ++++++++++++---------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/samples/sensor/grow_r502a/README.rst b/samples/sensor/grow_r502a/README.rst index 032be38bfff67e..06de5aabec5750 100644 --- a/samples/sensor/grow_r502a/README.rst +++ b/samples/sensor/grow_r502a/README.rst @@ -8,18 +8,15 @@ Overview This sample has the below functionalities: +#. Sensor LED is controlled using led APIs from zephyr subsystem. #. Shows the number of fingerprints stored in the sensor. +#. Shows the sensor device's configurations like baud rate, library size, address and data packet size in UART frame. #. When SENSOR_ATTR_RECORD_FREE_IDX is set then it search for free index in sensor library. #. When SENSOR_ATTR_RECORD_ADD is set then it adds a new fingerprint to the sensor. #. When SENSOR_ATTR_RECORD_FIND is set then it tries to find a match for the input fingerprint. On finding a match it returns ID and confidence. #. When SENSOR_ATTR_RECORD_DEL is set then it deletes a fingerprint from the sensor. -Note: Fingerprint add & delete functionalities work only when SENSOR_TRIG_TOUCH is set. -Tricolored LED in the sensor hardware will, flash on the below conditions: - -#. On successful addition or deletion of fingerprint it will flash in blue three times. -#. On finding a match for the input fingerprint it will flash in purple. -#. In all other cases it will flash in red. +Note: Fingerprint add functionality work only when SENSOR_TRIG_TOUCH is set. Wiring ******* @@ -42,7 +39,7 @@ build this sample app using: .. zephyr-app-commands:: :zephyr-app: samples/sensor/grow_r502a - :board: nrf52840dk/nrf52840 + :board: esp32_devkitc_wroom/esp32/procpu :goals: build flash Sample Output @@ -50,20 +47,18 @@ Sample Output .. code-block:: console - *** Booting Zephyr OS build zephyr-v3.1.0-2640-g328bb73113d4 *** - template count : 0 + *** Booting Zephyr OS build v3.6.0-3147-g8ae1a2e2718e *** + template count : 4 + baud 57600 + addr 0xffffffff + lib_size 200 + data_pkt_size 128 Fingerprint Deleted at ID #3 - Fingerprint template free idx at ID #0 - Waiting for valid finger to enroll as ID #0 + Fingerprint template free idx at ID #3 + Waiting for valid finger to enroll as ID #3 Place your finger - Fingerprint successfully stored at #0 - template count : 1 - Matched ID : 0 - confidence : 170 - template count : 1 - Matched ID : 0 - confidence : 136 - template count : 1 - Matched ID : 0 - confidence : 318 + Fingerprint successfully stored at #3 + template count : 4 + Matched ID : 2 + confidence : 110 From c17b3f45428b46d5c05852e20896398b2b3a3cdb Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0422/1389] MAINTAINERS: Update Ambiq maintainers Correct maintainer name to make it the same as github username. Signed-off-by: Hao Luo --- MAINTAINERS.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 147df7d96088dd..0fdc29b6485d49 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -244,7 +244,7 @@ Ambiq Platforms: status: odd fixes collaborators: - aaronyegx - - HaoLuo + - AlessandroLuo - RichardSWheatley files: - soc/ambiq/ @@ -4203,6 +4203,7 @@ West: status: odd fixes collaborators: - aaronyegx + - AlessandroLuo - RichardSWheatley files: - modules/hal_ambiq/ From 29685a5884d371c447d6f5abd08202517ed27c71 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0423/1389] riscv: FPU trap: test case thread typo fix Need to wait for both threads. Signed-off-by: Nicolas Pitre --- tests/arch/riscv/fpu_sharing/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/arch/riscv/fpu_sharing/src/main.c b/tests/arch/riscv/fpu_sharing/src/main.c index 55ab1a2e4a047f..12bf20f5685b75 100644 --- a/tests/arch/riscv/fpu_sharing/src/main.c +++ b/tests/arch/riscv/fpu_sharing/src/main.c @@ -245,7 +245,7 @@ ZTEST(riscv_fpu_sharing, test_multi_thread_interaction) thread2_entry, NULL, NULL, NULL, -1, 0, K_NO_WAIT); zassert_true(k_thread_join(&thread1, K_FOREVER) == 0); - zassert_true(k_thread_join(&thread1, K_FOREVER) == 0); + zassert_true(k_thread_join(&thread2, K_FOREVER) == 0); } /* From 465a3ab454a56854752ea41a577e5c2ddf316ed8 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0424/1389] soc: nuvoton: npcx: npcx9: Move non-soc Kconfig to right file Moves a non-SoC Kconfig to the normal Kconfig file, as this symbol has nothing to do with the SoC selection itself Signed-off-by: Jamie McCrae --- soc/nuvoton/npcx/npcx9/Kconfig | 8 ++++++++ soc/nuvoton/npcx/npcx9/Kconfig.soc | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/soc/nuvoton/npcx/npcx9/Kconfig b/soc/nuvoton/npcx/npcx9/Kconfig index 25cee4381b72f4..dd93a355e93331 100644 --- a/soc/nuvoton/npcx/npcx9/Kconfig +++ b/soc/nuvoton/npcx/npcx9/Kconfig @@ -11,3 +11,11 @@ config SOC_SERIES_NPCX9 select CPU_HAS_ARM_MPU select SOC_FAMILY_NPCX select HAS_PM + +config NPCX_VCC1_RST_HANG_WORKAROUND + bool + depends on SOC_NPCX9M7FB + default y + help + Workaround the issue "Possible Hang-Up After VCC1_RST Reset" + in the npcx9m7fb SoC errata. diff --git a/soc/nuvoton/npcx/npcx9/Kconfig.soc b/soc/nuvoton/npcx/npcx9/Kconfig.soc index 274aaddf1ec666..c7abe79ffd4283 100644 --- a/soc/nuvoton/npcx/npcx9/Kconfig.soc +++ b/soc/nuvoton/npcx/npcx9/Kconfig.soc @@ -48,11 +48,3 @@ config SOC default "npcx9m7f" if SOC_NPCX9M7F default "npcx9m7fb" if SOC_NPCX9M7FB default "npcx9mfp" if SOC_NPCX9MFP - -config NPCX_VCC1_RST_HANG_WORKAROUND - bool - depends on SOC_NPCX9M7FB - default y - help - Workaround the issue "Possible Hang-Up After VCC1_RST Reset" - in the npcx9m7fb SoC errata. From 9bdded4de3956d25fbc41a6555bbe3d59a3a1ad6 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0425/1389] scripts: twisterlib: coverage: exclude `LOG_*` branches Disable the branch coverage calculations on the `LOG_*` family of macros. Branch misses are due to the implementation of `Z_LOG2` and cannot be reasonably covered in library code. The internal paths through the `Z_LOG2` macro are not of interest when inspecting files that happen to use the Zephyr logging API. Signed-off-by: Jordan Yates --- scripts/pylib/twister/twisterlib/coverage.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/pylib/twister/twisterlib/coverage.py b/scripts/pylib/twister/twisterlib/coverage.py index 556f5b359baa44..26ffefec997a86 100644 --- a/scripts/pylib/twister/twisterlib/coverage.py +++ b/scripts/pylib/twister/twisterlib/coverage.py @@ -144,6 +144,7 @@ class Lcov(CoverageTool): def __init__(self, jobs=None): super().__init__() self.ignores = [] + self.ignore_branch_patterns = [] self.output_formats = "lcov,html" self.version = self.get_version() self.jobs = jobs @@ -169,6 +170,9 @@ def add_ignore_file(self, pattern): def add_ignore_directory(self, pattern): self.ignores.append('*/' + pattern + '/*') + def add_ignore_branch_pattern(self, pattern): + self.ignore_branch_patterns.append(pattern) + @property def is_lcov_v2(self): return self.version.startswith("2") @@ -252,6 +256,7 @@ class Gcovr(CoverageTool): def __init__(self): super().__init__() self.ignores = [] + self.ignore_branch_patterns = [] self.output_formats = "html" self.version = self.get_version() @@ -278,6 +283,9 @@ def add_ignore_file(self, pattern): def add_ignore_directory(self, pattern): self.ignores.append(".*/" + pattern + '/.*') + def add_ignore_branch_pattern(self, pattern): + self.ignore_branch_patterns.append(pattern) + @staticmethod def _interleave_list(prefix, list): tuple_list = [(prefix, item) for item in list] @@ -292,6 +300,7 @@ def _generate(self, outdir, coveragelog): ztestfile = os.path.join(outdir, "ztest.json") excludes = Gcovr._interleave_list("-e", self.ignores) + excludes += Gcovr._interleave_list("--exclude-branches-by-pattern", self.ignore_branch_patterns) # Different ifdef-ed implementations of the same function should not be # in conflict treated by GCOVR as separate objects for coverage statistics. @@ -383,5 +392,8 @@ def run_coverage(testplan, options): coverage_tool.add_ignore_file('generated') coverage_tool.add_ignore_directory('tests') coverage_tool.add_ignore_directory('samples') + # Ignore branch coverage on LOG_* and LOG_HEXDUMP_* macros + # Branch misses are due to the implementation of Z_LOG2 and cannot be avoided + coverage_tool.add_ignore_branch_pattern(r"^\s*LOG_(?:HEXDUMP_)?(?:DBG|INF|WRN|ERR)\(.*") coverage_completed = coverage_tool.generate(options.outdir) return coverage_completed From 2aee57eae4ca6c568426d437cab3f590d0eca223 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0426/1389] drivers: gpio: Update Numaker driver init function To update Numaker driver to turn on clock in init function. Signed-off-by: cyliang tw --- drivers/gpio/gpio_numaker.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/gpio_numaker.c b/drivers/gpio/gpio_numaker.c index 3a1c8ad8eeefd4..c88e0d498ce5fd 100644 --- a/drivers/gpio/gpio_numaker.c +++ b/drivers/gpio/gpio_numaker.c @@ -52,21 +52,6 @@ static int gpio_numaker_configure(const struct device *dev, gpio_pin_t pin, gpio return -EINVAL; } - SYS_UnlockReg(); - - /* Enable GPIO clock */ - struct numaker_scc_subsys scc_subsys; - - memset(&scc_subsys, 0x00, sizeof(scc_subsys)); - scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; - scc_subsys.pcc.clk_modidx = config->clk_modidx; - - /* Equivalent to CLK_EnableModuleClock(config->clk_modidx) */ - err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys); - if (err != 0) { - goto move_exit; - } - /* Configure GPIO direction */ switch (flags & GPIO_DIR_MASK) { case GPIO_INPUT: @@ -114,7 +99,6 @@ static int gpio_numaker_configure(const struct device *dev, gpio_pin_t pin, gpio } move_exit: - SYS_LockReg(); return err; } @@ -265,8 +249,21 @@ static void gpio_numaker_isr(const struct device *dev) \ static int gpio_numaker_init##n(const struct device *dev) \ { \ - IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), (GPIO_NUMAKER_IRQ_INIT(n);)) \ - return 0; \ + const struct gpio_numaker_config *config = dev->config; \ + struct numaker_scc_subsys scc_subsys; \ + int err; \ + \ + SYS_UnlockReg(); \ + memset(&scc_subsys, 0x00, sizeof(scc_subsys)); \ + scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; \ + scc_subsys.pcc.clk_modidx = config->clk_modidx; \ + err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys); \ + if (err == 0) { \ + IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), (GPIO_NUMAKER_IRQ_INIT(n);)) \ + } \ + \ + SYS_LockReg(); \ + return err; \ } \ DEVICE_DT_INST_DEFINE(n, &gpio_numaker_init##n, NULL, &gpio_numaker_data##n, \ &gpio_numaker_config##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ From b2438ff79838dc98592d1d005856dd0df8df3bb6 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0427/1389] Bluetooth: Assert alignof bt_addr types I got some feedback about confusion as to why the bt_addr types are not packed. This commit adds a note about it. This commit also adds a check for the alignof of the structs to verify the statement 'their members are bytes or byte arrays' to thoroughly prove that the struct is effectively as-if packed. Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/common/dummy.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subsys/bluetooth/common/dummy.c b/subsys/bluetooth/common/dummy.c index 4659f946f92c8b..9d83e1f92764bb 100644 --- a/subsys/bluetooth/common/dummy.c +++ b/subsys/bluetooth/common/dummy.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include #include @@ -18,9 +20,15 @@ * their members are bytes or byte arrays, the size is. They must not be padded * by the compiler, otherwise the on-wire packet will not map the packed * structure correctly. + * + * The bt_addr structs are not marked __packed because it's considered ugly by + * some. But here is a proof that the structs have all the properties of, and + * can be safely used as packed structs. */ BUILD_ASSERT(sizeof(bt_addr_t) == BT_ADDR_SIZE); +BUILD_ASSERT(alignof(bt_addr_t) == 1); BUILD_ASSERT(sizeof(bt_addr_le_t) == BT_ADDR_LE_SIZE); +BUILD_ASSERT(alignof(bt_addr_le_t) == 1); #if defined(CONFIG_BT_HCI_HOST) /* The Bluetooth subsystem requires that higher priority events shall be given From 08e3351a7ce6f177aa16bb8a09e69fd3431c9bdb Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0428/1389] tests: i2c_ram: rtio: Fix sequence to prepare ops to avoid overwriting `rtio_sqe_prep_write()` and `rtio_sqe_prep_read()` memset the sqe struct to zeroes, clearing any configuration previously set. This commit changes this sequence in the test, such that the sqe's are prepared, then additional flags/configs applied. Signed-off-by: Luis Ubieda --- tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c b/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c index 739e9809ff3029..3992897d90f29e 100644 --- a/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c +++ b/tests/drivers/i2c/i2c_ram/src/test_i2c_ram.c @@ -185,8 +185,8 @@ ZTEST(i2c_ram, test_ram_rtio) TC_PRINT("submitting write from thread %p addr %x\n", k_current_get(), addr); wr_sqe = rtio_sqe_acquire(&i2c_rtio); - wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP; rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, tx_data, ARRAY_SIZE(tx_data), tx_data); + wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP; zassert_ok(rtio_submit(&i2c_rtio, 1), "submit should succeed"); wr_cqe = rtio_cqe_consume(&i2c_rtio); @@ -201,11 +201,11 @@ ZTEST(i2c_ram, test_ram_rtio) msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP; wr_sqe = rtio_sqe_acquire(&i2c_rtio); - wr_sqe->flags |= RTIO_SQE_TRANSACTION; rd_sqe = rtio_sqe_acquire(&i2c_rtio); - rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, rx_cmd, ARRAY_SIZE(rx_cmd), rx_cmd); rtio_sqe_prep_read(rd_sqe, &i2c_iodev, 0, rx_data, ARRAY_SIZE(rx_data), rx_data); + wr_sqe->flags |= RTIO_SQE_TRANSACTION; + rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; zassert_ok(rtio_submit(&i2c_rtio, 2), "submit should succeed"); wr_cqe = rtio_cqe_consume(&i2c_rtio); @@ -238,8 +238,8 @@ void ram_rtio_isr(struct k_timer *tid) case INIT: TC_PRINT("timer submitting write, addr %x\n", addr); wr_sqe = rtio_sqe_acquire(&i2c_rtio); - wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP; rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, tx_data, ARRAY_SIZE(tx_data), tx_data); + wr_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP; zassert_ok(rtio_submit(&i2c_rtio, 0), "submit should succeed"); isr_state += 1; break; @@ -258,13 +258,13 @@ void ram_rtio_isr(struct k_timer *tid) msgs[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP; wr_sqe = rtio_sqe_acquire(&i2c_rtio); - wr_sqe->flags |= RTIO_SQE_TRANSACTION; rd_sqe = rtio_sqe_acquire(&i2c_rtio); - rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; rtio_sqe_prep_write(wr_sqe, &i2c_iodev, 0, rx_cmd, ARRAY_SIZE(rx_cmd), rx_cmd); rtio_sqe_prep_read(rd_sqe, &i2c_iodev, 0, rx_data, ARRAY_SIZE(rx_data), rx_data); + wr_sqe->flags |= RTIO_SQE_TRANSACTION; + rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; zassert_ok(rtio_submit(&i2c_rtio, 0), "submit should succeed"); isr_state += 1; } From c9cd84a2f3163c8bb503dd68846325210fc470f0 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0429/1389] net: ipv6: mld: remove addition of unspecified source in MLDv2 report From RFC: * "source list" is an unordered list of zero or more unicast addresses from which multicast reception is desired or not desired [...] It means that there is no need to add any special address to specify "block all" and "allow all" states explicitly. This commit removes the unnecessary addition. Signed-off-by: Konrad Derda --- subsys/net/ip/ipv6_mld.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/subsys/net/ip/ipv6_mld.c b/subsys/net/ip/ipv6_mld.c index 25f7b42bdafb9f..554e0103e02aa2 100644 --- a/subsys/net/ip/ipv6_mld.c +++ b/subsys/net/ip/ipv6_mld.c @@ -48,8 +48,7 @@ struct mcast_route_appending_info { static int mld_create(struct net_pkt *pkt, const struct in6_addr *addr, - uint8_t record_type, - uint16_t num_sources) + uint8_t record_type) { NET_PKT_DATA_ACCESS_DEFINE(mld_access, struct net_icmpv6_mld_mcast_record); @@ -63,7 +62,7 @@ static int mld_create(struct net_pkt *pkt, mld->record_type = record_type; mld->aux_data_len = 0U; - mld->num_sources = htons(num_sources); + mld->num_sources = 0U; net_ipv6_addr_copy_raw(mld->mcast_address, (uint8_t *)addr); @@ -71,15 +70,6 @@ static int mld_create(struct net_pkt *pkt, return -ENOBUFS; } - if (num_sources > 0) { - /* All source addresses, RFC 3810 ch 3 */ - if (net_pkt_write(pkt, - net_ipv6_unspecified_address()->s6_addr, - sizeof(struct in6_addr))) { - return -ENOBUFS; - } - } - return 0; } @@ -181,7 +171,7 @@ static void append_mcast_routes(struct net_route_entry_mcast *entry, void *user_ } } - info->status = mld_create(info->pkt, &entry->group, NET_IPV6_MLDv2_MODE_IS_EXCLUDE, 0); + info->status = mld_create(info->pkt, &entry->group, NET_IPV6_MLDv2_MODE_IS_EXCLUDE); } #endif @@ -201,7 +191,7 @@ int net_ipv6_mld_send_single(struct net_if *iface, const struct in6_addr *addr, } if (mld_create_packet(pkt, 1) || - mld_create(pkt, addr, mode, 1)) { + mld_create(pkt, addr, mode)) { ret = -ENOBUFS; goto drop; } @@ -337,7 +327,7 @@ static int send_mld_report(struct net_if *iface) } ret = mld_create(pkt, &ipv6->mcast[i].address.in6_addr, - NET_IPV6_MLDv2_MODE_IS_EXCLUDE, 0); + NET_IPV6_MLDv2_MODE_IS_EXCLUDE); if (ret < 0) { goto drop; } From 9a005a80c69acde5f189b3632b5f294c0504ab27 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0430/1389] net: ipv6: mld: use proper MLDv2 modes According to the RFC, MODE_IS_INCLUDE/MODE_IS_EXCLUDE codes should be used while sendling Multicast Listener Reports in response to a query. When performing a transition between states (e.g., when joining or leaving a multicast group) CHANGE_TO_INCLUDE_MODE/CHANGE_TO_EXCLUDE_MODE have to be used. Signed-off-by: Konrad Derda --- subsys/net/ip/ipv6_mld.c | 4 ++-- subsys/net/ip/route.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/net/ip/ipv6_mld.c b/subsys/net/ip/ipv6_mld.c index 554e0103e02aa2..75644c2ca5801a 100644 --- a/subsys/net/ip/ipv6_mld.c +++ b/subsys/net/ip/ipv6_mld.c @@ -234,7 +234,7 @@ int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr) return -ENETDOWN; } - ret = net_ipv6_mld_send_single(iface, addr, NET_IPV6_MLDv2_MODE_IS_EXCLUDE); + ret = net_ipv6_mld_send_single(iface, addr, NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE); if (ret < 0) { return ret; } @@ -268,7 +268,7 @@ int net_ipv6_mld_leave(struct net_if *iface, const struct in6_addr *addr) return 0; } - ret = net_ipv6_mld_send_single(iface, addr, NET_IPV6_MLDv2_MODE_IS_INCLUDE); + ret = net_ipv6_mld_send_single(iface, addr, NET_IPV6_MLDv2_CHANGE_TO_INCLUDE_MODE); if (ret < 0) { return ret; } diff --git a/subsys/net/ip/route.c b/subsys/net/ip/route.c index d2012a17b4c494..09f71c5b179bb5 100644 --- a/subsys/net/ip/route.c +++ b/subsys/net/ip/route.c @@ -805,8 +805,8 @@ static void propagate_mld_event(struct net_route_entry_mcast *route, bool route_ /* Apply only for complete addresses */ if (route->prefix_len == 128) { mld_event.addr = &route->group; - mld_event.mode = route_added ? NET_IPV6_MLDv2_MODE_IS_EXCLUDE : - NET_IPV6_MLDv2_MODE_IS_INCLUDE; + mld_event.mode = route_added ? NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE : + NET_IPV6_MLDv2_CHANGE_TO_INCLUDE_MODE; net_if_foreach(send_mld_event, &mld_event); } From 1d1282443173f934d4e835268cdfa300f745ecdd Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0431/1389] tests: net: mld: update MLDv2 tests after changes This commit changes the expectations to checking for state transitions in MLDv2 reports. Signed-off-by: Konrad Derda --- tests/net/mld/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/mld/src/main.c b/tests/net/mld/src/main.c index c780d20d8e516a..abfaca57a30726 100644 --- a/tests/net/mld/src/main.c +++ b/tests/net/mld/src/main.c @@ -708,7 +708,7 @@ static void add_mcast_route_and_verify(struct net_if *iface, struct in6_addr *ad zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report"); zassert_equal(info->records_count, 1, "Invalid number of reported addresses"); - zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_MODE_IS_EXCLUDE, + zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE, "Invalid MLDv2 record type"); zassert_mem_equal(&info->records[0].mcast_addr, addr, sizeof(struct in6_addr), "Invalid reported address"); @@ -731,7 +731,7 @@ static void del_mcast_route_and_verify(struct net_if *iface, struct in6_addr *ad zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), "Timeout while waiting for a report"); zassert_equal(info->records_count, 1, "Invalid number of reported addresses"); - zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_MODE_IS_INCLUDE, + zassert_equal(info->records[0].record_type, NET_IPV6_MLDv2_CHANGE_TO_INCLUDE_MODE, "Invalid MLDv2 record type"); zassert_mem_equal(&info->records[0].mcast_addr, addr, sizeof(struct in6_addr), "Invalid reported address"); From b99dadb9fe4688fc7314af9e2c571f992934251e Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0432/1389] Bluetooth: controller: Prevent invalid compiler code reordering In ull_disable, it is imperative that the callback is set up before a second reference counter check, otherwise it may happen that an LLL done event has already passed when the disable callback and semaphore is assigned. This causes the HCI thread to wait until timeout and assert after ull_ticker_stop_with_mark. For certain compilers, due to compiler optimizations, it can be seen from the assembler code that the callback is assigned after the second reference counter check. By adding memory barriers, the code correctly reorders code to the expected sequence. Signed-off-by: Morten Priess --- subsys/bluetooth/controller/ll_sw/ull.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index f4133b9af8de15..b5bbec9af84dd2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1953,12 +1953,15 @@ int ull_disable(void *lll) if (!ull_ref_get(hdr)) { return -EALREADY; } + cpu_dmb(); /* Ensure synchronized data access */ k_sem_init(&sem, 0, 1); hdr->disabled_param = &sem; hdr->disabled_cb = disabled_cb; + cpu_dmb(); /* Ensure synchronized data access */ + /* ULL_HIGH can run after we have call `ull_ref_get` and it can * decrement the ref count. Hence, handle this race condition by * ensuring that `disabled_cb` has been set while the ref count is still From 75aec1bee916640db88474ec2e22ce3c6a8b873d Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:47 +0200 Subject: [PATCH 0433/1389] boards: nxp: vmu_rt1170: fix SD card pin control setup Fix SD card pinctrl setup for the VMU RT1170 board. The following changes were made: - use the "cd-gpios" property over detecting the card using the USDHC card detect register. This should be more reliable. - bias the clk pin high. This matches setup for the RT1170 EVK SD pinctrl. - remove the drive strength setting for SD pins to align with the pinctrl settings for low speed SD mode (50 MHz) on the RT1170 EVK. Signed-off-by: Daniel DeGrasse --- boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi | 15 ++------------- .../nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts | 1 + 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi index ac50cfa8b76f36..e7ab7ce896b556 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi @@ -344,20 +344,9 @@ <&iomuxc_gpio_sd_b1_02_usdhc1_data0>, <&iomuxc_gpio_sd_b1_03_usdhc1_data1>, <&iomuxc_gpio_sd_b1_04_usdhc1_data2>, - <&iomuxc_gpio_sd_b1_05_usdhc1_data3>; + <&iomuxc_gpio_sd_b1_05_usdhc1_data3>, + <&iomuxc_gpio_sd_b1_01_usdhc1_clk>; bias-pull-up; - drive-strength = "high"; - slew-rate = "fast"; - input-enable; - }; - group1 { - pinmux = <&iomuxc_gpio_sd_b1_01_usdhc1_clk>; - drive-strength = "high"; - slew-rate = "fast"; - }; - group2 { - pinmux = <&iomuxc_gpio_ad_32_usdhc1_cd_b>; - bias-pull-down; input-enable; }; }; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts index 564164c5ae4143..9c44e8d874e853 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts +++ b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts @@ -402,6 +402,7 @@ status = "okay"; no-1-8-v; pwr-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio3 31 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; sdmmc { compatible = "zephyr,sdmmc-disk"; status = "okay"; From 9e5b3a58aa3f386fed6949a2bf2117b7e9e545a7 Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0434/1389] drivers: regulator: shell: fix strcmp usage bug in cmd_adset Bug in "enable/disable" argument parsing would cause the oppostive of the requested setting to get passed to active discharge API invocation. Signed-off-by: Mike J. Chen --- drivers/regulator/regulator_shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/regulator_shell.c b/drivers/regulator/regulator_shell.c index 508a029790faa3..ba0c29e34b803b 100644 --- a/drivers/regulator/regulator_shell.c +++ b/drivers/regulator/regulator_shell.c @@ -398,9 +398,9 @@ static int cmd_adset(const struct shell *sh, size_t argc, char **argv) return -ENODEV; } - if (strcmp(argv[2], "enable")) { + if (strcmp(argv[2], "enable") == 0) { ad = true; - } else if (strcmp(argv[2], "disable")) { + } else if (strcmp(argv[2], "disable") == 0) { ad = false; } else { shell_error(sh, "Invalid parameter"); From fa2845b79bfc5746e4f0f619384e57cad32615f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0435/1389] tests: drivers: counter: counter_basic_api: Add nrf54h20 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlays for nrf54h20dk cpuapp and cpurad. Signed-off-by: Krzysztof Chruściński --- .../boards/nrf54h20dk_nrf54h20_common.dtsi | 60 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 3 + .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 22 +++++++ 3 files changed, 85 insertions(+) create mode 100644 tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi create mode 100644 tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 00000000000000..d442c112262280 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&timer120 { + status = "okay"; + prescaler = <7>; +}; + +&timer121 { + status = "okay"; + prescaler = <7>; +}; + +&timer130 { + status = "okay"; + prescaler = <4>; +}; + +&timer131 { + status = "okay"; + prescaler = <4>; +}; + +&timer132 { + status = "okay"; + prescaler = <4>; +}; + +&timer133 { + status = "okay"; + prescaler = <4>; +}; + +&timer134 { + status = "okay"; + prescaler = <4>; +}; + +&timer135 { + status = "okay"; + prescaler = <4>; +}; + +&timer136 { + status = "okay"; + prescaler = <4>; +}; + +&timer137 { + status = "okay"; + prescaler = <4>; +}; + +&rtc130 { + status = "okay"; + ppi-wrap; +}; + +&rtc131 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..f65b4dd3b0ba0f --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000000..88c288a4528983 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&timer020 { + status = "okay"; + prescaler = <7>; +}; + +&timer021 { + status = "okay"; + prescaler = <7>; +}; + +&timer022 { + status = "okay"; + prescaler = <7>; +}; + +&rtc { + status = "okay"; +}; From da974d9068974edb93cb253b589c68deadd5b6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0436/1389] tests: drivers: counter: counter_nrf_rtc: Add nrf54h20dk support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlays for nrf54h20dk in fixed_top test. Signed-off-by: Krzysztof Chruściński --- .../fixed_top/boards/nrf54h20dk_nrf54h20_common.dtsi | 11 +++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 3 +++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 8 ++++++++ 3 files changed, 22 insertions(+) create mode 100644 tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_common.dtsi create mode 100644 tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 00000000000000..181611f712d298 --- /dev/null +++ b/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,11 @@ + /* SPDX-License-Identifier: Apache-2.0 */ + +&rtc130 { + status = "okay"; + fixed-top; +}; + +&rtc131 { + status = "okay"; + fixed-top; +}; diff --git a/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..f65b4dd3b0ba0f --- /dev/null +++ b/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000000..f7f44e2dc43630 --- /dev/null +++ b/tests/drivers/counter/counter_nrf_rtc/fixed_top/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&rtc { + status = "okay"; + fixed-top; +}; From c097856a52dc37eab9eeb250663f907a83f54292 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0437/1389] subsys/testsuite/ztest: create stub headers at CMake configure time Create unittest stub headers at CMake configure time. Signed-off-by: Yong Cong Sin --- cmake/modules/unittest.cmake | 21 +++++++++++++++++++ .../testsuite/ztest/include/zephyr/offsets.h | 17 --------------- .../ztest/include/zephyr/syscall_list.h | 3 --- .../ztest/include/zephyr/syscall_macros.h | 3 --- .../ztest/include/zephyr/syscalls/kernel.h | 3 --- .../ztest/include/zephyr/syscalls/kobject.h | 5 ----- .../ztest/include/zephyr/syscalls/log_core.h | 5 ----- .../ztest/include/zephyr/syscalls/log_ctrl.h | 5 ----- .../ztest/include/zephyr/syscalls/log_msg.h | 5 ----- .../ztest/include/zephyr/syscalls/sys_clock.h | 3 --- 10 files changed, 21 insertions(+), 49 deletions(-) delete mode 100644 subsys/testsuite/ztest/include/zephyr/offsets.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscall_list.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscall_macros.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscalls/kernel.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscalls/kobject.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscalls/log_core.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscalls/log_ctrl.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscalls/log_msg.h delete mode 100644 subsys/testsuite/ztest/include/zephyr/syscalls/sys_clock.h diff --git a/cmake/modules/unittest.cmake b/cmake/modules/unittest.cmake index 79e6c269c7ce6b..e9b767f5877202 100644 --- a/cmake/modules/unittest.cmake +++ b/cmake/modules/unittest.cmake @@ -58,6 +58,27 @@ include(${ZEPHYR_BASE}/cmake/kobj.cmake) add_dependencies(test_interface ${KOBJ_TYPES_H_TARGET}) gen_kobj(KOBJ_GEN_DIR) +# Generates empty header files to build +set(INCL_GENERATED_DIR ${APPLICATION_BINARY_DIR}/zephyr/include/generated) +set(INCL_GENERATED_SYSCALL_DIR ${INCL_GENERATED_DIR}/syscalls) +list(APPEND INCL_GENERATED_HEADERS + ${INCL_GENERATED_DIR}/devicetree_generated.h + ${INCL_GENERATED_DIR}/offsets.h + ${INCL_GENERATED_DIR}/syscall_list.h + ${INCL_GENERATED_DIR}/syscall_macros.h + ${INCL_GENERATED_SYSCALL_DIR}/kernel.h + ${INCL_GENERATED_SYSCALL_DIR}/kobject.h + ${INCL_GENERATED_SYSCALL_DIR}/log_core.h + ${INCL_GENERATED_SYSCALL_DIR}/log_ctrl.h + ${INCL_GENERATED_SYSCALL_DIR}/log_msg.h + ${INCL_GENERATED_SYSCALL_DIR}/sys_clock.h +) + +file(MAKE_DIRECTORY ${INCL_GENERATED_SYSCALL_DIR}) +foreach(header ${INCL_GENERATED_HEADERS}) + file(TOUCH ${header}) +endforeach() + list(APPEND INCLUDE subsys/testsuite/ztest/include/zephyr subsys/testsuite/include/zephyr diff --git a/subsys/testsuite/ztest/include/zephyr/offsets.h b/subsys/testsuite/ztest/include/zephyr/offsets.h deleted file mode 100644 index 7c7c8ee57a6ff7..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/offsets.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __GEN_OFFSETS_H__ -#define __GEN_OFFSETS_H__ - -/* - * This file is a fake replacement for - * $build_dir/zephyr/include/generated/offsets.h - * - * The unittest infrastructure does not know how to generate - * offsets.h, so until this is supported we fake it with this - * file. This allows us to test source files that include offsets.h, - * but don't actually use anything from it when unit testing. - */ - -#endif diff --git a/subsys/testsuite/ztest/include/zephyr/syscall_list.h b/subsys/testsuite/ztest/include/zephyr/syscall_list.h deleted file mode 100644 index 1cfdde31e137d1..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscall_list.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscall_macros.h b/subsys/testsuite/ztest/include/zephyr/syscall_macros.h deleted file mode 100644 index 1cfdde31e137d1..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscall_macros.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscalls/kernel.h b/subsys/testsuite/ztest/include/zephyr/syscalls/kernel.h deleted file mode 100644 index 1cfdde31e137d1..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/kernel.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscalls/kobject.h b/subsys/testsuite/ztest/include/zephyr/syscalls/kobject.h deleted file mode 100644 index 49281301178ac9..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/kobject.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscalls/log_core.h b/subsys/testsuite/ztest/include/zephyr/syscalls/log_core.h deleted file mode 100644 index ff9e44d289f2bf..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/log_core.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscalls/log_ctrl.h b/subsys/testsuite/ztest/include/zephyr/syscalls/log_ctrl.h deleted file mode 100644 index ff9e44d289f2bf..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/log_ctrl.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscalls/log_msg.h b/subsys/testsuite/ztest/include/zephyr/syscalls/log_msg.h deleted file mode 100644 index bb6a719084b570..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/log_msg.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ diff --git a/subsys/testsuite/ztest/include/zephyr/syscalls/sys_clock.h b/subsys/testsuite/ztest/include/zephyr/syscalls/sys_clock.h deleted file mode 100644 index 1cfdde31e137d1..00000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/sys_clock.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ From cf4d46faec3affde638e93aaab74c9521fb68128 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0438/1389] ztest: include: unittest: relocate cpu.h and include only if unit-test The `cpu.h` is meant to be a hack around Zephyr's dependencies for unit-test, relocate it to a folder that's included only by unit-test. Signed-off-by: Yong Cong Sin --- cmake/modules/unittest.cmake | 1 + subsys/testsuite/ztest/{ => unittest}/include/zephyr/arch/cpu.h | 0 2 files changed, 1 insertion(+) rename subsys/testsuite/ztest/{ => unittest}/include/zephyr/arch/cpu.h (100%) diff --git a/cmake/modules/unittest.cmake b/cmake/modules/unittest.cmake index e9b767f5877202..892358999cfc40 100644 --- a/cmake/modules/unittest.cmake +++ b/cmake/modules/unittest.cmake @@ -81,6 +81,7 @@ endforeach() list(APPEND INCLUDE subsys/testsuite/ztest/include/zephyr + subsys/testsuite/ztest/unittest/include subsys/testsuite/include/zephyr subsys/testsuite/ztest/include subsys/testsuite/include diff --git a/subsys/testsuite/ztest/include/zephyr/arch/cpu.h b/subsys/testsuite/ztest/unittest/include/zephyr/arch/cpu.h similarity index 100% rename from subsys/testsuite/ztest/include/zephyr/arch/cpu.h rename to subsys/testsuite/ztest/unittest/include/zephyr/arch/cpu.h From 414eab1217f40358a89a4ca30ebb60f555a23dc7 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0439/1389] drivers: hwinfo: Adds Ambiq hwinfo support This commit adds support for the hwinfo for Apollo4P SoCs Signed-off-by: Richard Wheatley --- boards/ambiq/apollo4p_evb/apollo4p_evb.yaml | 1 + drivers/hwinfo/CMakeLists.txt | 1 + drivers/hwinfo/Kconfig | 9 ++ drivers/hwinfo/hwinfo_ambiq.c | 137 ++++++++++++++++++++ modules/hal_ambiq/Kconfig | 5 + west.yml | 2 +- 6 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 drivers/hwinfo/hwinfo_ambiq.c diff --git a/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml b/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml index 1aa0fbf75d4b24..205da184346bff 100644 --- a/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml +++ b/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml @@ -14,6 +14,7 @@ supported: - gpio - spi - i2c + - hwinfo testing: ignore_tags: - net diff --git a/drivers/hwinfo/CMakeLists.txt b/drivers/hwinfo/CMakeLists.txt index 2e7d91141be9ca..60707d59a6199c 100644 --- a/drivers/hwinfo/CMakeLists.txt +++ b/drivers/hwinfo/CMakeLists.txt @@ -29,3 +29,4 @@ zephyr_library_sources_ifdef(CONFIG_HWINFO_SMARTBOND hwinfo_smartbond.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_STM32 hwinfo_stm32.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_ANDES hwinfo_andes.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_RW61X hwinfo_rw61x.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_AMBIQ hwinfo_ambiq.c) diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index 703201410dec53..b3bab9c82afb0c 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -200,4 +200,13 @@ config HWINFO_RW61X help Enable RW61X hwinfo driver +config HWINFO_AMBIQ + bool "AMBIQ hwinfo" + default y + depends on SOC_SERIES_APOLLO4X + select AMBIQ_HAL + select AMBIQ_HAL_USE_HWINFO + help + Enable AMBIQ hwinfo driver + endif diff --git a/drivers/hwinfo/hwinfo_ambiq.c b/drivers/hwinfo/hwinfo_ambiq.c new file mode 100644 index 00000000000000..80bcf62763ad5f --- /dev/null +++ b/drivers/hwinfo/hwinfo_ambiq.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 Ambiq + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) +{ + + struct ambiq_hwinfo { + /* Ambiq Chip ID0 */ + uint32_t chip_id_0; + /* Ambiq Chip ID1 */ + uint32_t chip_id_1; + /* Ambiq Factory Trim Revision */ + /* Can be used in Ambiq HAL for additional code support */ + uint32_t factory_trim_version; + }; + + struct ambiq_hwinfo dev_hw_info = {0}; + + /* Contains the HAL hardware information about the device. */ + am_hal_mcuctrl_device_t mcu_ctrl_device; + + am_hal_mram_info_read(1, AM_REG_INFO1_TRIM_REV_O / 4, 1, &dev_hw_info.factory_trim_version); + am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_DEVICEID, &mcu_ctrl_device); + + dev_hw_info.chip_id_0 = mcu_ctrl_device.ui32ChipID0; + dev_hw_info.chip_id_1 = mcu_ctrl_device.ui32ChipID1; + + if (length > sizeof(dev_hw_info)) { + length = sizeof(dev_hw_info); + } + + dev_hw_info.chip_id_0 = BSWAP_32(dev_hw_info.chip_id_0); + dev_hw_info.chip_id_1 = BSWAP_32(dev_hw_info.chip_id_1); + dev_hw_info.factory_trim_version = BSWAP_32(dev_hw_info.factory_trim_version); + memcpy(buffer, &dev_hw_info, length); + + return length; +} + +int z_impl_hwinfo_get_reset_cause(uint32_t *cause) +{ + uint32_t flags = 0; + uint32_t reset_status = 0; + am_hal_reset_status_t status = {0}; + + /* Print out reset status register upon entry */ + am_hal_reset_status_get(&status); + reset_status = status.eStatus; + + /* EXTERNAL PIN */ + if (reset_status & AM_HAL_RESET_STATUS_EXTERNAL) { + flags |= RESET_PIN; + } + + /* POWER CYCLE */ + if (reset_status & AM_HAL_RESET_STATUS_POR) { + flags |= RESET_POR; + } + + /* BROWNOUT DETECTOR */ + if (reset_status & AM_HAL_RESET_STATUS_BOD) { + flags |= RESET_BROWNOUT; + } + + /* SOFTWARE POR */ + if (reset_status & AM_HAL_RESET_STATUS_SWPOR) { + flags |= RESET_SOFTWARE; + } + + /* SOFTWARE POI */ + if (reset_status & AM_HAL_RESET_STATUS_SWPOI) { + flags |= RESET_SOFTWARE; + } + + /* DEBUGGER */ + if (reset_status & AM_HAL_RESET_STATUS_DEBUGGER) { + flags |= RESET_DEBUG; + } + + /* WATCHDOG */ + if (reset_status & AM_HAL_RESET_STATUS_WDT) { + flags |= RESET_WATCHDOG; + } + + /* BOUNREG */ + if (reset_status & AM_HAL_RESET_STATUS_BOUNREG) { + flags |= RESET_HARDWARE; + } + + /* BOCORE */ + if (reset_status & AM_HAL_RESET_STATUS_BOCORE) { + flags |= RESET_HARDWARE; + } + + /* BOMEM */ + if (reset_status & AM_HAL_RESET_STATUS_BOMEM) { + flags |= RESET_HARDWARE; + } + + /* BOHPMEM */ + if (reset_status & AM_HAL_RESET_STATUS_BOHPMEM) { + flags |= RESET_HARDWARE; + } + + *cause = flags; + return 0; +} + +int z_impl_hwinfo_clear_reset_cause(void) +{ + /* SBL maintains the RSTGEN->STAT register in + * INFO1 space even upon clearing RSTGEN->STAT + * register. + * - INFO1_RESETSTATUS + */ + + return -ENOSYS; +} + +int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) +{ + *supported = RESET_PIN + | RESET_SOFTWARE + | RESET_POR + | RESET_WATCHDOG + | RESET_HARDWARE + | RESET_BROWNOUT; + return 0; +} diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index 24aaf1189cd758..b329d117c89794 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -45,4 +45,9 @@ config AMBIQ_HAL_USE_MSPI help Use the MSPI driver from Ambiq HAL +config AMBIQ_HAL_USE_HWINFO + bool + help + Use the HWINFO driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/west.yml b/west.yml index 94d555e9f169cb..55bfac7ae334cc 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: 705f1cbb1ccbdaac7613eb7b27c208c8f592e0c4 + revision: f6858cb3fe3d44945a23d114b7feeeac22ce71cf path: modules/hal/ambiq groups: - hal From be8e9ac6ff6f62258cc0c231bda6471057251b1c Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0440/1389] drivers: flash: flash_ambiq: add Apollo3 SOC support This commit adapts the Ambiq flash controller to support the Apollo3 SOC (e.g. Apollo3 Blue, Apollo3 Blue Plus). Also uses the Zephyr common IRQ API to replace the Ambiq HAL ones. Signed-off-by: Aaron Ye --- drivers/flash/Kconfig.ambiq | 5 ++-- drivers/flash/flash_ambiq.c | 58 ++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/flash/Kconfig.ambiq b/drivers/flash/Kconfig.ambiq index cc84c0faf39f13..5ce028bba9664d 100644 --- a/drivers/flash/Kconfig.ambiq +++ b/drivers/flash/Kconfig.ambiq @@ -2,11 +2,12 @@ # SPDX-License-Identifier: Apache-2.0 config FLASH_AMBIQ - bool "Ambiq flash driver on MRAM" + bool "Ambiq flash driver on MRAM or flash" default y depends on DT_HAS_AMBIQ_FLASH_CONTROLLER_ENABLED select AMBIQ_HAL select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED help - Enables Ambiq flash driver on MRAM. + 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 fdc852c04ca8cf..30ce8524045104 100644 --- a/drivers/flash/flash_ambiq.c +++ b/drivers/flash/flash_ambiq.c @@ -15,15 +15,19 @@ LOG_MODULE_REGISTER(flash_ambiq, CONFIG_FLASH_LOG_LEVEL); -#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) -#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE) -#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE) -#define MIN_WRITE_SIZE 16 +#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE) +#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE) +#if (CONFIG_SOC_SERIES_APOLLO4X) +#define MIN_WRITE_SIZE 16 +#else +#define MIN_WRITE_SIZE 4 +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ #define FLASH_WRITE_BLOCK_SIZE MAX(DT_PROP(SOC_NV_FLASH_NODE, write_block_size), MIN_WRITE_SIZE) #define FLASH_ERASE_BLOCK_SIZE DT_PROP(SOC_NV_FLASH_NODE, erase_block_size) BUILD_ASSERT((FLASH_WRITE_BLOCK_SIZE & (MIN_WRITE_SIZE - 1)) == 0, - "The flash write block size must be a multiple of 16!"); + "The flash write block size must be a multiple of MIN_WRITE_SIZE!"); #define FLASH_ERASE_BYTE 0xFF #define FLASH_ERASE_WORD \ @@ -77,7 +81,7 @@ static int flash_ambiq_write(const struct device *dev, off_t offset, const void ARG_UNUSED(dev); int ret = 0; - uint32_t critical = 0; + unsigned int key = 0; uint32_t aligned[FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)] = {0}; uint32_t *src = (uint32_t *)data; @@ -96,22 +100,31 @@ static int flash_ambiq_write(const struct device *dev, off_t offset, const void FLASH_SEM_TAKE(); - critical = am_hal_interrupt_master_disable(); + key = irq_lock(); + for (int i = 0; i < len / FLASH_WRITE_BLOCK_SIZE; i++) { for (int j = 0; j < FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t); j++) { /* Make sure the source data is 4-byte aligned. */ aligned[j] = UNALIGNED_GET((uint32_t *)src); src++; } +#if (CONFIG_SOC_SERIES_APOLLO4X) ret = am_hal_mram_main_program( AM_HAL_MRAM_PROGRAM_KEY, aligned, (uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE), FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + ret = am_hal_flash_program_main( + AM_HAL_FLASH_PROGRAM_KEY, aligned, + (uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE), + FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ if (ret) { break; } } - am_hal_interrupt_master_set(critical); + + irq_unlock(key); FLASH_SEM_GIVE(); @@ -128,17 +141,42 @@ static int flash_ambiq_erase(const struct device *dev, off_t offset, size_t len) return -EINVAL; } - /* The erase address and length alignment check will be done in HAL.*/ - if (len == 0) { return 0; } +#if (CONFIG_SOC_SERIES_APOLLO4X) + /* The erase address and length alignment check will be done in HAL.*/ +#elif (CONFIG_SOC_SERIES_APOLLO3X) + if ((offset % FLASH_ERASE_BLOCK_SIZE) != 0) { + LOG_ERR("offset 0x%lx is not on a page boundary", (long)offset); + return -EINVAL; + } + + if ((len % FLASH_ERASE_BLOCK_SIZE) != 0) { + LOG_ERR("len %zu is not multiple of a page size", len); + return -EINVAL; + } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ + FLASH_SEM_TAKE(); +#if (CONFIG_SOC_SERIES_APOLLO4X) ret = am_hal_mram_main_fill(AM_HAL_MRAM_PROGRAM_KEY, FLASH_ERASE_WORD, (uint32_t *)(SOC_NV_FLASH_ADDR + offset), (len / sizeof(uint32_t))); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + unsigned int key = 0; + + key = irq_lock(); + + ret = am_hal_flash_page_erase( + AM_HAL_FLASH_PROGRAM_KEY, + AM_HAL_FLASH_ADDR2INST(((uint32_t)SOC_NV_FLASH_ADDR + offset)), + AM_HAL_FLASH_ADDR2PAGE(((uint32_t)SOC_NV_FLASH_ADDR + offset))); + + irq_unlock(key); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ FLASH_SEM_GIVE(); From b81c3c9c5b7f31b1b57573e19ce73f2257f4fb77 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0441/1389] dts: arm: ambiq: add flash controller instance for Apollo3 Blue SOC This commit adds flash controller instance for Ambiq Apollo3 Blue SOC and Apollo3 Blue Plus SOC. Also create the partitions on this flash controller node for apollo3_evb and apollo3p_evb. Signed-off-by: Aaron Ye --- boards/ambiq/apollo3_evb/apollo3_evb.dts | 18 ++++++++++++++++++ boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 18 ++++++++++++++++++ dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 20 ++++++++++++++------ dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 20 ++++++++++++++------ 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index 181495a303825c..78bba84b8524a5 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -14,6 +14,7 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; }; aliases { @@ -21,6 +22,23 @@ }; }; +&flash0 { + erase-block-size = <8192>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 976KB of flash */ + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 0x4000>; + }; + }; +}; + &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index 46894814dbe420..910fca95567f92 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -14,6 +14,7 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; }; aliases { @@ -21,6 +22,23 @@ }; }; +&flash0 { + erase-block-size = <8192>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 2000KB of flash */ + storage_partition: partition@1f0000 { + label = "storage"; + reg = <0x001f0000 0x4000>; + }; + }; +}; + &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index 1f151efc9a1abc..f863ee14ba81c6 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -25,12 +25,6 @@ }; }; - /* Flash region */ - flash0: flash@C000 { - compatible = "soc-nv-flash"; - reg = <0x0000C000 0xF4000>; - }; - /* TCM */ tcm: tcm@10000000 { compatible = "zephyr,memory-region"; @@ -47,6 +41,20 @@ soc { compatible = "ambiq,apollo3-blue", "ambiq,apollo3x", "simple-bus"; + flash: flash-controller@c000 { + compatible = "ambiq,flash-controller"; + reg = <0x0000c000 0xf4000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* Flash region */ + flash0: flash@c000 { + compatible = "soc-nv-flash"; + reg = <0x0000c000 0xf4000>; + }; + }; + pwrcfg: pwrcfg@40021000 { compatible = "ambiq,pwrctrl"; reg = <0x40021000 0x400>; diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index a95b7e6945b35d..988e5b48a7fa0e 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -25,12 +25,6 @@ }; }; - /* Flash region */ - flash0: flash@C000 { - compatible = "soc-nv-flash"; - reg = <0x0000C000 0x1F4000>; - }; - /* TCM */ tcm: tcm@10000000 { compatible = "zephyr,memory-region"; @@ -47,6 +41,20 @@ soc { compatible = "ambiq,apollo3p-blue", "ambiq,apollo3x", "simple-bus"; + flash: flash-controller@c000 { + compatible = "ambiq,flash-controller"; + reg = <0x0000c000 0x1f4000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* Flash region */ + flash0: flash@c000 { + compatible = "soc-nv-flash"; + reg = <0x0000c000 0x1f4000>; + }; + }; + pwrcfg: pwrcfg@40021000 { compatible = "ambiq,pwrctrl"; reg = <0x40021000 0x400>; From 369d51fe7617570b34b61109c3d8c5a48174ae5e Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0442/1389] Bluetooth: HCI: Rename to bt_hci_iso_sdu_hdr and bt_hci_iso_sdu_ts_hdr Rename struct bt_hci_iso_data_hdr to bt_hci_iso_sdu_hdr, and struct bt_hci_iso_ts_data_hdr to bt_hci_iso_sdu_ts_hdr. Signed-off-by: Vinayak Kariappa Chettimada --- include/zephyr/bluetooth/buf.h | 2 +- include/zephyr/bluetooth/hci_types.h | 10 +++++----- subsys/bluetooth/Kconfig.iso | 4 ++-- subsys/bluetooth/controller/hci/hci.c | 12 ++++++------ subsys/bluetooth/controller/hci/hci_driver.c | 14 +++++++------- subsys/bluetooth/host/iso.c | 20 ++++++++++---------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/zephyr/bluetooth/buf.h b/include/zephyr/bluetooth/buf.h index 7429547ee410d8..b373ab5bd911c9 100644 --- a/include/zephyr/bluetooth/buf.h +++ b/include/zephyr/bluetooth/buf.h @@ -68,7 +68,7 @@ struct bt_buf_data { /** Helper to calculate needed buffer size for HCI ISO packets. */ #define BT_BUF_ISO_SIZE(size) BT_BUF_SIZE(BT_HCI_ISO_HDR_SIZE + \ - BT_HCI_ISO_TS_DATA_HDR_SIZE + \ + BT_HCI_ISO_SDU_TS_HDR_SIZE + \ (size)) /** Data size needed for HCI ACL RX buffers */ diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index f1ebf0c7d3eb76..cbcbf4ea503be7 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -108,17 +108,17 @@ struct bt_hci_acl_hdr { #define bt_iso_pkt_flags(h) ((h) >> 14) #define bt_iso_pkt_len_pack(h, f) (((h) & BIT_MASK(12)) | ((f) << 14)) -struct bt_hci_iso_data_hdr { +struct bt_hci_iso_sdu_hdr { uint16_t sn; uint16_t slen; /* 12 bit len, 2 bit RFU, 2 bit packet status */ } __packed; -#define BT_HCI_ISO_DATA_HDR_SIZE 4 +#define BT_HCI_ISO_SDU_HDR_SIZE 4 -struct bt_hci_iso_ts_data_hdr { +struct bt_hci_iso_sdu_ts_hdr { uint32_t ts; - struct bt_hci_iso_data_hdr data; + struct bt_hci_iso_sdu_hdr sdu; } __packed; -#define BT_HCI_ISO_TS_DATA_HDR_SIZE 8 +#define BT_HCI_ISO_SDU_TS_HDR_SIZE 8 /* Bluetooth spec v5.4 Vol 4, Part E - 5.4.5 HCI ISO Data Packets */ struct bt_hci_iso_hdr { diff --git a/subsys/bluetooth/Kconfig.iso b/subsys/bluetooth/Kconfig.iso index 89955b7061487f..68119724f18939 100644 --- a/subsys/bluetooth/Kconfig.iso +++ b/subsys/bluetooth/Kconfig.iso @@ -110,7 +110,7 @@ config BT_ISO_TX_MTU help Maximum MTU for Isochronous channels TX buffers. This is the actual data payload. It doesn't include the optional - HCI ISO Data packet fields (e.g. `struct bt_hci_iso_ts_data_hdr`). + HCI ISO Data packet fields (e.g. `struct bt_hci_iso_sdu_ts_hdr`). Set this value to 247 to fit 247 bytes of data within a single HCI ISO Data packet with a size of 255, without utilizing timestamps. @@ -128,7 +128,7 @@ config BT_ISO_RX_MTU help Maximum MTU for Isochronous channels RX buffers. This is the actual data payload. It doesn't include the optional - HCI ISO Data packet fields (e.g. `struct bt_hci_iso_ts_data_hdr`) + HCI ISO Data packet fields (e.g. `struct bt_hci_iso_sdu_ts_hdr`) config BT_ISO_TEST_PARAMS bool "ISO test parameters support" diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 36e062a0ad9151..4fecb50de1a00e 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5709,7 +5709,7 @@ int hci_acl_handle(struct net_buf *buf, struct net_buf **evt) #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) { - struct bt_hci_iso_data_hdr *iso_data_hdr; + struct bt_hci_iso_sdu_hdr *iso_sdu_hdr; struct isoal_sdu_tx sdu_frag_tx; struct bt_hci_iso_hdr *iso_hdr; uint32_t *time_stamp; @@ -5719,7 +5719,7 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) uint8_t flags; uint16_t len; - iso_data_hdr = NULL; + iso_sdu_hdr = NULL; *evt = NULL; if (buf->len < sizeof(*iso_hdr)) { @@ -5770,11 +5770,11 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) /* Extract ISO data header if included (PB_Flag 0b00 or 0b10) */ if ((pb_flag & 0x01) == 0) { - iso_data_hdr = net_buf_pull_mem(buf, sizeof(*iso_data_hdr)); - len -= sizeof(*iso_data_hdr); - sdu_frag_tx.packet_sn = sys_le16_to_cpu(iso_data_hdr->sn); + iso_sdu_hdr = net_buf_pull_mem(buf, sizeof(*iso_sdu_hdr)); + len -= sizeof(*iso_sdu_hdr); + sdu_frag_tx.packet_sn = sys_le16_to_cpu(iso_sdu_hdr->sn); sdu_frag_tx.iso_sdu_length = - sys_le16_to_cpu(bt_iso_pkt_len(iso_data_hdr->slen)); + sys_le16_to_cpu(bt_iso_pkt_len(iso_sdu_hdr->slen)); } else { sdu_frag_tx.packet_sn = 0; sdu_frag_tx.iso_sdu_length = 0; diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 20b73b5b1d6708..a7251748cca3ae 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -138,7 +138,7 @@ static int bt_recv_prio(struct net_buf *buf) #if defined(CONFIG_BT_CTLR_ISO) -#define SDU_HCI_HDR_SIZE (BT_HCI_ISO_HDR_SIZE + BT_HCI_ISO_TS_DATA_HDR_SIZE) +#define SDU_HCI_HDR_SIZE (BT_HCI_ISO_HDR_SIZE + BT_HCI_ISO_SDU_TS_HDR_SIZE) isoal_status_t sink_sdu_alloc_hci(const struct isoal_sink *sink_ctx, const struct isoal_pdu_rx *valid_pdu, @@ -167,7 +167,7 @@ isoal_status_t sink_sdu_emit_hci(const struct isoal_sink *sink_ctx, const struct isoal_emitted_sdu_frag *sdu_frag, const struct isoal_emitted_sdu *sdu) { - struct bt_hci_iso_ts_data_hdr *data_hdr; + struct bt_hci_iso_sdu_ts_hdr *sdu_hdr; uint16_t packet_status_flag; struct bt_hci_iso_hdr *hdr; uint16_t handle_packed; @@ -230,14 +230,14 @@ isoal_status_t sink_sdu_emit_hci(const struct isoal_sink *sink_ctx, ts = (pb & 0x1) == 0x0; if (ts) { - data_hdr = net_buf_push(buf, BT_HCI_ISO_TS_DATA_HDR_SIZE); + sdu_hdr = net_buf_push(buf, BT_HCI_ISO_SDU_TS_HDR_SIZE); slen_packed = bt_iso_pkt_len_pack(total_len, packet_status_flag); - data_hdr->ts = sys_cpu_to_le32((uint32_t) sdu_frag->sdu.timestamp); - data_hdr->data.sn = sys_cpu_to_le16((uint16_t) sdu_frag->sdu.sn); - data_hdr->data.slen = sys_cpu_to_le16(slen_packed); + sdu_hdr->ts = sys_cpu_to_le32((uint32_t) sdu_frag->sdu.timestamp); + sdu_hdr->sdu.sn = sys_cpu_to_le16((uint16_t) sdu_frag->sdu.sn); + sdu_hdr->sdu.slen = sys_cpu_to_le16(slen_packed); - len += BT_HCI_ISO_TS_DATA_HDR_SIZE; + len += BT_HCI_ISO_SDU_TS_HDR_SIZE; } hdr = net_buf_push(buf, BT_HCI_ISO_HDR_SIZE); diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index 7f1e0d01f70569..ec0a5e8ceabbbc 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -168,7 +168,7 @@ struct net_buf *bt_iso_create_pdu_timeout(struct net_buf_pool *pool, pool = &iso_tx_pool; } - reserve += sizeof(struct bt_hci_iso_data_hdr); + reserve += sizeof(struct bt_hci_iso_sdu_hdr); #if defined(CONFIG_NET_BUF_LOG) return bt_conn_create_pdu_timeout_debug(pool, reserve, timeout, func, @@ -585,7 +585,7 @@ struct net_buf *bt_iso_get_rx(k_timeout_t timeout) void bt_iso_recv(struct bt_conn *iso, struct net_buf *buf, uint8_t flags) { - struct bt_hci_iso_data_hdr *hdr; + struct bt_hci_iso_sdu_hdr *hdr; struct bt_iso_chan *chan; uint8_t pb, ts; uint16_t len, pkt_seq_no; @@ -609,12 +609,12 @@ void bt_iso_recv(struct bt_conn *iso, struct net_buf *buf, uint8_t flags) * of an SDU or a complete SDU. */ if (ts) { - struct bt_hci_iso_ts_data_hdr *ts_hdr; + struct bt_hci_iso_sdu_ts_hdr *ts_hdr; ts_hdr = net_buf_pull_mem(buf, sizeof(*ts_hdr)); iso_info(buf)->ts = sys_le32_to_cpu(ts_hdr->ts); - hdr = &ts_hdr->data; + hdr = &ts_hdr->sdu; iso_info(buf)->flags |= BT_ISO_FLAGS_TS; } else { hdr = net_buf_pull_mem(buf, sizeof(*hdr)); @@ -791,11 +791,11 @@ static int validate_send(const struct bt_iso_chan *chan, const struct net_buf *b int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq_num) { - struct bt_hci_iso_data_hdr *hdr; + struct bt_hci_iso_sdu_hdr *hdr; struct bt_conn *iso_conn; int err; - err = validate_send(chan, buf, BT_HCI_ISO_DATA_HDR_SIZE); + err = validate_send(chan, buf, BT_HCI_ISO_SDU_HDR_SIZE); if (err != 0) { return err; } @@ -815,11 +815,11 @@ int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq int bt_iso_chan_send_ts(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq_num, uint32_t ts) { - struct bt_hci_iso_ts_data_hdr *hdr; + struct bt_hci_iso_sdu_ts_hdr *hdr; struct bt_conn *iso_conn; int err; - err = validate_send(chan, buf, BT_HCI_ISO_TS_DATA_HDR_SIZE); + err = validate_send(chan, buf, BT_HCI_ISO_SDU_TS_HDR_SIZE); if (err != 0) { return err; } @@ -828,8 +828,8 @@ int bt_iso_chan_send_ts(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t hdr = net_buf_push(buf, sizeof(*hdr)); hdr->ts = ts; - hdr->data.sn = sys_cpu_to_le16(seq_num); - hdr->data.slen = sys_cpu_to_le16( + hdr->sdu.sn = sys_cpu_to_le16(seq_num); + hdr->sdu.slen = sys_cpu_to_le16( bt_iso_pkt_len_pack(net_buf_frags_len(buf) - sizeof(*hdr), BT_ISO_DATA_VALID)); iso_conn = chan->iso; From 2a3ae96c2d13e8792f9168277c12d471484fae7d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0443/1389] Bluetooth: Controller: BT_CTLR_ISO_TX_BUFFER_SIZE from BT_ISO_TX_MTU Derive BT_CTLR_ISO_TX_BUFFER_SIZE from BT_ISO_TX_MTU to have optimal Controller memory allocations. BT_CTLR_ISO_TX_BUFFER_SIZE can be set lower than BT_ISO_TX_MTU in which case upper layer can send fragmented SDU to the Controller. Signed-off-by: Vinayak Kariappa Chettimada --- .../overlay-bt_ll_sw_split.conf | 10 ++---- .../central_iso/overlay-bt_ll_sw_split.conf | 33 +++++++++++++++++++ samples/bluetooth/central_iso/sample.yaml | 11 +++++++ .../nrf5340_cpunet_bis-bt_ll_sw_split.conf | 4 +-- .../nrf5340_cpunet_cis-bt_ll_sw_split.conf | 4 +-- .../nrf5340_cpunet_iso-bt_ll_sw_split.conf | 6 ++-- ...0_cpunet_iso_broadcast-bt_ll_sw_split.conf | 4 +-- ...340_cpunet_iso_central-bt_ll_sw_split.conf | 4 +-- ..._cpunet_iso_peripheral-bt_ll_sw_split.conf | 4 +-- .../hci_uart/overlay-all-bt_ll_sw_split.conf | 6 ++-- .../iso_broadcast/overlay-bt_ll_sw_split.conf | 21 ++++++++---- samples/bluetooth/iso_broadcast/sample.yaml | 4 +-- .../overlay-bt_ll_sw_split.conf | 10 ++---- .../tmap_bmr/boards/nrf52840dk_nrf52840.conf | 4 --- .../tmap_bms/boards/nrf52840dk_nrf52840.conf | 4 --- .../boards/nrf52840dk_nrf52840.conf | 4 --- .../boards/nrf52840dk_nrf52840.conf | 4 --- .../boards/nrf52840dk_nrf52840.conf | 4 --- .../overlay-bt_ll_sw_split.conf | 7 +++- .../boards/nrf52840dk_nrf52840.conf | 4 --- .../overlay-bt_ll_sw_split.conf | 6 +++- subsys/bluetooth/Kconfig.iso | 5 +-- subsys/bluetooth/controller/Kconfig | 15 ++++++--- subsys/bluetooth/controller/hci/hci.c | 2 +- subsys/bluetooth/controller/include/ll_feat.h | 18 ++++++++-- tests/bsim/bluetooth/audio/prj.conf | 2 +- tests/bsim/bluetooth/host/iso/cis/prj.conf | 4 +-- tests/bsim/bluetooth/ll/bis/prj.conf | 6 ++-- tests/bsim/bluetooth/ll/bis/prj_vs_dp.conf | 2 +- tests/bsim/bluetooth/ll/cis/prj.conf | 4 +-- ...0_cpunet_iso_acl_group-bt_ll_sw_split.conf | 6 ++-- 31 files changed, 136 insertions(+), 86 deletions(-) create mode 100644 samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf delete mode 100644 samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf delete mode 100644 samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf delete mode 100644 samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf delete mode 100644 samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf delete mode 100644 samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf delete mode 100644 samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf diff --git a/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf index c73ff9c3ea9b88..3711a34921368d 100644 --- a/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf @@ -14,11 +14,7 @@ CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 CONFIG_BT_CTLR_ISOAL_SOURCES=2 -# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and optionally -# additional + 4 bytes for timestamp when not using BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), -# otherwise Host tries to fragment ISO data. -# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the -# CONFIG_BT_ISO_TX_MTU value. -# -# Supports the highest SDU size required by any BAP LC3 presets (155) +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf b/samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf new file mode 100644 index 00000000000000..320c5c352b116d --- /dev/null +++ b/samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf @@ -0,0 +1,33 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Bluetooth LE Controller needs 16 event buffers to generate Extended +# Advertising Report for receiving the complete 1650 bytes of data +CONFIG_BT_BUF_EVT_RX_COUNT=16 + +# Set maximum scan data length for Extended Scanning in Bluetooth LE Controller +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 + +# Increase Zephyr Bluetooth LE Controller Rx buffer to receive complete chain +# of PDUs +CONFIG_BT_CTLR_RX_BUFFERS=9 + +# Sufficient ISO SDU and PDU length for this sample with ISO_TX_MTU of 247 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 +CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 + +# Number of supported streami sources and sinks +CONFIG_BT_CTLR_ISOAL_SOURCES=2 +CONFIG_BT_CTLR_ISOAL_SINKS=1 + +# Support the highest SDU size required by this sample 247 + 8 bytes of HCI ISO Data +# packet overhead (timestamp and HCI ISO Data packet header) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 + +# Use Low Latency Connected ISO policy +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y + +# Use the below if the sample is sending stale packet sequence number +# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/central_iso/sample.yaml b/samples/bluetooth/central_iso/sample.yaml index 0cdbb7a501cd1c..455ff8fcb00013 100644 --- a/samples/bluetooth/central_iso/sample.yaml +++ b/samples/bluetooth/central_iso/sample.yaml @@ -8,3 +8,14 @@ tests: integration_platforms: - qemu_x86 tags: bluetooth + sample.bluetooth.central_iso.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf52_bsim + - nrf52833dk/nrf52833 + integration_platforms: + - nrf52833dk/nrf52833 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf index 7fd4d377b1d76b..27f7b9b80ea20c 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf @@ -77,7 +77,7 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -89,7 +89,7 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf index 18606ee3a67f20..040e1db6b4f173 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf @@ -77,12 +77,12 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 823343bc3f65df..3377273dd9ab63 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -82,7 +82,7 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -95,12 +95,12 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf index 22d7f2e726dbb1..05645663bc4425 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf @@ -31,8 +31,8 @@ CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 CONFIG_BT_CTLR_ADV_ISO=y CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 CONFIG_BT_CTLR_ISOAL_SOURCES=2 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf index c6e0172b69460f..56e80860f326bf 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf @@ -44,12 +44,12 @@ CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=n -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf index 3272d896ca62c2..b72aaa624f1a77 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf @@ -44,12 +44,12 @@ CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=n CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf index 3774532c424156..8d6dbdd87b016d 100644 --- a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf @@ -80,7 +80,7 @@ CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -93,12 +93,12 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf b/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf index a5f8b3cc1c5bf2..19264a9d041afa 100644 --- a/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf @@ -1,13 +1,20 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 + +# Enable support for Broadcast ISO in Zephyr Bluetooth Controller CONFIG_BT_CTLR_ADV_ISO=y + +# Sufficient ISO PDU length for this sample CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=4 -CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 +# Number of supported streams +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 CONFIG_BT_CTLR_ISOAL_SOURCES=2 -# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and -# optionally additional + 4 bytes for timestamp when not using -# BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), otherwise Host tries to fragment -# ISO data. -# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the -# CONFIG_BT_ISO_TX_MTU value. +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=12 diff --git a/samples/bluetooth/iso_broadcast/sample.yaml b/samples/bluetooth/iso_broadcast/sample.yaml index 10fb481688c628..92bde54d7a0c7a 100644 --- a/samples/bluetooth/iso_broadcast/sample.yaml +++ b/samples/bluetooth/iso_broadcast/sample.yaml @@ -17,8 +17,8 @@ tests: - qemu_cortex_m3 - qemu_x86 - nrf52_bsim - - nrf52dk/nrf52832 + - nrf52833dk/nrf52833 integration_platforms: - - nrf52dk/nrf52832 + - nrf52833dk/nrf52833 extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf tags: bluetooth diff --git a/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf index c73ff9c3ea9b88..3711a34921368d 100644 --- a/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf @@ -14,11 +14,7 @@ CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 CONFIG_BT_CTLR_ISOAL_SOURCES=2 -# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and optionally -# additional + 4 bytes for timestamp when not using BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), -# otherwise Host tries to fragment ISO data. -# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the -# CONFIG_BT_ISO_TX_MTU value. -# -# Supports the highest SDU size required by any BAP LC3 presets (155) +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 3c7c698c48b8c0..00000000000000 --- a/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_PERIPHERAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 57d674179ff93b..00000000000000 --- a/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_CENTRAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 57d674179ff93b..00000000000000 --- a/samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_CENTRAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 3c7c698c48b8c0..00000000000000 --- a/samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_PERIPHERAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 57d674179ff93b..00000000000000 --- a/samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_CENTRAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf b/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf index 1c29b28e2ddaf4..755e7fafa786ff 100644 --- a/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf @@ -1,9 +1,14 @@ CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 CONFIG_BT_CTLR_ISOAL_SOURCES=2 CONFIG_BT_CTLR_ISOAL_SINKS=1 + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 + CONFIG_BT_CTLR_ADVANCED_FEATURES=y CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 3c7c698c48b8c0..00000000000000 --- a/samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_PERIPHERAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf b/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf index 1499e379d4e22b..8c6d99253a6b88 100644 --- a/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf @@ -1,10 +1,14 @@ CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 CONFIG_BT_CTLR_ISO_TX_BUFFERS=2 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 CONFIG_BT_CTLR_ISOAL_SOURCES=1 CONFIG_BT_CTLR_ISOAL_SINKS=2 +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 + # Use the below if the sample is sending stale packet sequence number # CONFIG_BT_CTLR_ADVANCED_FEATURES=y # CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/subsys/bluetooth/Kconfig.iso b/subsys/bluetooth/Kconfig.iso index 68119724f18939..cce7208b48cf08 100644 --- a/subsys/bluetooth/Kconfig.iso +++ b/subsys/bluetooth/Kconfig.iso @@ -105,14 +105,15 @@ config BT_ISO_TX_FRAG_COUNT config BT_ISO_TX_MTU int "Maximum supported MTU for Isochronous TX buffers" - default 251 range 1 4095 + default 247 help Maximum MTU for Isochronous channels TX buffers. This is the actual data payload. It doesn't include the optional HCI ISO Data packet fields (e.g. `struct bt_hci_iso_sdu_ts_hdr`). Set this value to 247 to fit 247 bytes of data within a single - HCI ISO Data packet with a size of 255, without utilizing timestamps. + HCI ISO Data packet with Data_Total_Length of 255, utilizing + timestamps. config BT_ISO_RX_BUF_COUNT int "Number of Isochronous RX buffers" diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 4a966987bd1bac..6d031c446224ab 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -202,12 +202,19 @@ config BT_CTLR_ISO_TX_BUFFERS config BT_CTLR_ISO_TX_BUFFER_SIZE int "Isochronous Tx buffer size" depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO - range 1 4095 - default BT_ISO_TX_MTU if BT_ISO + range 9 4103 if BT_LL_SW_SPLIT + range 1 65535 + default 9 if BT_LL_SW_SPLIT default 1 help Size of the Isochronous Tx buffers and the value returned in HCI LE - Read Buffer Size V2 command response. + Read Buffer Size V2 command response. This is the data portion of the + HCI ISO Data packet, corresponding to the Data_Total_Length field. + + Currently the maximum SDU length is 4095 bytes, hence add HCI ISO + Data packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, + Packet_Status_Flag fields; and the optional Time_Stamp field, if + supplied) of 8 bytes. config BT_CTLR_ISOAL_SOURCES int "Number of Isochronous Adaptation Layer sources" @@ -929,7 +936,7 @@ config BT_CTLR_CONN_ISO_PDU_LEN_MAX config BT_CTLR_CONN_ISO_SDU_LEN_MAX int "Maximum Connected Isochronous Channel SDU Length" depends on BT_CTLR_CONN_ISO - range BT_CTLR_CONN_ISO_PDU_LEN_MAX 4095 + range 1 4095 default 251 help Maximum Connected Isochronous Channel SDU Length. diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 4fecb50de1a00e..d051150a26b648 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -1398,7 +1398,7 @@ static void le_read_buffer_size_v2(struct net_buf *buf, struct net_buf **evt) rp->acl_max_len = sys_cpu_to_le16(LL_LENGTH_OCTETS_TX_MAX); rp->acl_max_num = CONFIG_BT_BUF_ACL_TX_COUNT; - rp->iso_max_len = sys_cpu_to_le16(CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE); + rp->iso_max_len = sys_cpu_to_le16(BT_CTLR_ISO_TX_BUFFER_SIZE); rp->iso_max_num = CONFIG_BT_CTLR_ISO_TX_BUFFERS; } #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */ diff --git a/subsys/bluetooth/controller/include/ll_feat.h b/subsys/bluetooth/controller/include/ll_feat.h index 1eb2d86a1c3d1a..15e4eacd966d89 100644 --- a/subsys/bluetooth/controller/include/ll_feat.h +++ b/subsys/bluetooth/controller/include/ll_feat.h @@ -189,10 +189,23 @@ #define LL_FEAT_BIT_CIS_PERIPHERAL 0 #endif /* !CONFIG_BT_CTLR_PERIPHERAL_ISO */ +#if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) +#if defined(CONFIG_BT_ISO_TX_MTU) +#define BT_CTLR_ISO_TX_BUFFER_SIZE MIN((CONFIG_BT_ISO_TX_MTU + \ + BT_HCI_ISO_SDU_TS_HDR_SIZE), \ + MAX(CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE, \ + (BT_HCI_ISO_SDU_TS_HDR_SIZE + 1U))) +#else +#define BT_CTLR_ISO_TX_BUFFER_SIZE MAX(CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE, \ + (BT_HCI_ISO_SDU_TS_HDR_SIZE + 1U)) +#endif /* CONFIG_BT_ISO_TX_MTU */ +#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */ + #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \ defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) #define LL_CIS_OCTETS_TX_MAX MIN(CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX, \ - CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE) + (BT_CTLR_ISO_TX_BUFFER_SIZE - \ + BT_HCI_ISO_SDU_TS_HDR_SIZE)) #define LL_CIS_OCTETS_RX_MAX CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX #else /* !CONFIG_BT_CTLR_CENTRAL_ISO && !CONFIG_BT_CTLR_PERIPHERAL_ISO */ #define LL_CIS_OCTETS_TX_MAX 0 @@ -202,7 +215,8 @@ #if defined(CONFIG_BT_CTLR_ADV_ISO) #define LL_FEAT_BIT_ISO_BROADCASTER BIT64(BT_LE_FEAT_BIT_ISO_BROADCASTER) #define LL_BIS_OCTETS_TX_MAX MIN(CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX, \ - CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE) + (BT_CTLR_ISO_TX_BUFFER_SIZE - \ + BT_HCI_ISO_SDU_TS_HDR_SIZE)) #else /* !CONFIG_BT_CTLR_ADV_ISO */ #define LL_FEAT_BIT_ISO_BROADCASTER 0 #define LL_BIS_OCTETS_TX_MAX 0 diff --git a/tests/bsim/bluetooth/audio/prj.conf b/tests/bsim/bluetooth/audio/prj.conf index 1afbca08502e08..90e5924bf6cb50 100644 --- a/tests/bsim/bluetooth/audio/prj.conf +++ b/tests/bsim/bluetooth/audio/prj.conf @@ -206,7 +206,7 @@ CONFIG_LOG_MODE_IMMEDIATE=y CONFIG_BT_CTLR_ADV_ISO=y CONFIG_BT_CTLR_SYNC_ISO=y CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=255 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 # Controller ISO Broadcast Settings diff --git a/tests/bsim/bluetooth/host/iso/cis/prj.conf b/tests/bsim/bluetooth/host/iso/cis/prj.conf index d1a1b8cd161185..78ef925ce07c47 100644 --- a/tests/bsim/bluetooth/host/iso/cis/prj.conf +++ b/tests/bsim/bluetooth/host/iso/cis/prj.conf @@ -17,7 +17,7 @@ CONFIG_BT_ISO_LOG_LEVEL_DBG=y # Controller Connected ISO configs CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=208 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 CONFIG_BT_CTLR_ISOAL_SOURCES=2 CONFIG_BT_CTLR_ISOAL_SINKS=2 - -CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 diff --git a/tests/bsim/bluetooth/ll/bis/prj.conf b/tests/bsim/bluetooth/ll/bis/prj.conf index 02e2f3168db975..afa1f5958614c3 100644 --- a/tests/bsim/bluetooth/ll/bis/prj.conf +++ b/tests/bsim/bluetooth/ll/bis/prj.conf @@ -8,7 +8,7 @@ CONFIG_BT_PER_ADV_SYNC=y CONFIG_BT_ISO_BROADCASTER=y CONFIG_BT_ISO_SYNC_RECEIVER=y -CONFIG_BT_ISO_TX_MTU=251 +CONFIG_BT_ISO_TX_MTU=247 CONFIG_BT_ISO_RX_MTU=251 CONFIG_BT_CTLR_ADV_EXT=y @@ -16,8 +16,8 @@ CONFIG_BT_CTLR_ADV_ISO=y CONFIG_BT_CTLR_SYNC_ISO=y CONFIG_BT_CTLR_ISO_TX_BUFFERS=2 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=251 CONFIG_BT_CTLR_TEST=y diff --git a/tests/bsim/bluetooth/ll/bis/prj_vs_dp.conf b/tests/bsim/bluetooth/ll/bis/prj_vs_dp.conf index 9cf785bc92595c..2f0f9ccc86d338 100644 --- a/tests/bsim/bluetooth/ll/bis/prj_vs_dp.conf +++ b/tests/bsim/bluetooth/ll/bis/prj_vs_dp.conf @@ -15,7 +15,7 @@ CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_ISO=y CONFIG_BT_CTLR_SYNC_ISO=y -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=251 diff --git a/tests/bsim/bluetooth/ll/cis/prj.conf b/tests/bsim/bluetooth/ll/cis/prj.conf index a4d3c3e8c5f8e2..c124cbd223eb9a 100644 --- a/tests/bsim/bluetooth/ll/cis/prj.conf +++ b/tests/bsim/bluetooth/ll/cis/prj.conf @@ -28,7 +28,7 @@ CONFIG_LOG=y CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 CONFIG_BT_CTLR_CONN_ISO_STREAMS=9 CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP=9 @@ -36,7 +36,7 @@ CONFIG_BT_CTLR_ISOAL_SOURCES=9 CONFIG_BT_CTLR_ISOAL_SINKS=9 CONFIG_BT_CTLR_ISO_TX_BUFFERS=18 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISO_RX_BUFFERS=1 CONFIG_BT_CTLR_PHY_CODED=n diff --git a/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf b/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf index d410216659ac4b..5119ac0d3eddb6 100644 --- a/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf +++ b/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf @@ -84,7 +84,7 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=9 CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -97,14 +97,14 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 CONFIG_BT_CTLR_CONN_ISO_STREAMS=4 CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP=4 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=18 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=4 # ISO Receptions From 2e6264efb5976ac1754ba67d0f7b12983e4e667f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0444/1389] Bluetooth: Host: Map HCI cmd disallowed to errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make `bt_hci_cmd_send_sync` return `-EACCES` when receiving `BT_HCI_ERR_CMD_DISALLOWED`. Update some tests that were expecting `-EIO` when getting `BT_HCI_ERR_CMD_DISALLOWED`. Add a warning in `set_random_address` when getting that new error. This is done in case someone try to set a new random address while legacy advertising, scanning or initiating is enabled. This is illegal behavior according to the Core Spec (see Vol 4, Part E 7.8.4). Signed-off-by: Théo Battrel --- subsys/bluetooth/host/hci_core.c | 2 ++ subsys/bluetooth/host/id.c | 9 +++++++++ .../df/connection_cte_req/src/test_cte_req_enable.c | 4 ++-- .../src/test_set_cl_cte_tx_enable.c | 6 +++--- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index d0737cd85fd4c8..b0429fe3b6d649 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -344,6 +344,8 @@ int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf, return -ENOMEM; case BT_HCI_ERR_INVALID_PARAM: return -EINVAL; + case BT_HCI_ERR_CMD_DISALLOWED: + return -EACCES; default: return -EIO; } diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index 69cdadd9c4d31e..618dc6b758606b 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -141,6 +141,15 @@ static int set_random_address(const bt_addr_t *addr) err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf, NULL); if (err) { + if (err == -EACCES) { + /* If we are here we probably tried to set a random + * address while a legacy advertising, scanning or + * initiating is enabled, this is illegal. + * + * See Core Spec @ Vol 4, Part E 7.8.4 + */ + LOG_WRN("cmd disallowed"); + } return err; } diff --git a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c index e518903cba2c3f..f9f10d5ccabeef 100644 --- a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c +++ b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c @@ -97,7 +97,7 @@ ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set, int err; err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); - zassert_equal(err, -EIO, + zassert_equal(err, -EACCES, "Unexpected error value for CTE request enable before set rx params"); } @@ -109,7 +109,7 @@ ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, g_data.cte_request_interval = REQUEST_INTERVAL_TOO_LOW; err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); - zassert_equal(err, -EIO, + zassert_equal(err, -EACCES, "Unexpected error value for CTE request enable with too short request" " interval"); } diff --git a/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c b/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c index 313f94e7762812..35267739edd16c 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c +++ b/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c @@ -71,7 +71,7 @@ ZTEST(test_set_cl_cte_tx_enable, test_set_cl_cte_tx_enable_cte_params_not_set) /* test logic */ err = send_set_cl_cte_tx_enable(g_adv->handle, g_adv->flags, true); - zassert_equal(err, -EIO, "Unexpected error value for enable CTE before " + zassert_equal(err, -EACCES, "Unexpected error value for enable CTE before " "CTE params set"); /* clean up */ @@ -90,7 +90,7 @@ ZTEST(test_set_cl_cte_tx_enable, test_set_cl_cte_tx_enable_per_adv_coded_phy) /* test logic */ err = send_set_cl_cte_tx_enable(g_adv->handle, g_adv->flags, true); - zassert_equal(err, -EIO, "Unexpected error value for enable CTE for " + zassert_equal(err, -EACCES, "Unexpected error value for enable CTE for " "coded PHY"); /* clean up */ @@ -151,7 +151,7 @@ ZTEST(test_set_cl_cte_tx_enable, test_set_cl_cte_tx_disable_when_no_CTE_enabled) /* test logic */ err = send_set_cl_cte_tx_enable(g_adv->handle, g_adv->flags, false); - zassert_equal(err, -EIO, "Unexpected error value for disable CTE " + zassert_equal(err, -EACCES, "Unexpected error value for disable CTE " "before CTE enable"); /* clean up */ From de9a0d75ce01d4d6b7a0c3e9e1bf465afdf6f9da Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0445/1389] Bluetooth: samples: hci_uart_async: Use existing H4 defines Use existing H4 defines from hci_types.h instead of redefining them. Signed-off-by: Johan Hedberg --- .../hci_uart_async/src/hci_uart_async.c | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/samples/bluetooth/hci_uart_async/src/hci_uart_async.c b/samples/bluetooth/hci_uart_async/src/hci_uart_async.c index cf9cc600d5cf5f..e3e32eba4af1f8 100644 --- a/samples/bluetooth/hci_uart_async/src/hci_uart_async.c +++ b/samples/bluetooth/hci_uart_async/src/hci_uart_async.c @@ -37,14 +37,6 @@ static const struct device *const hci_uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_ static K_THREAD_STACK_DEFINE(h2c_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); static struct k_thread h2c_thread; -enum h4_type { - H4_CMD = 0x01, - H4_ACL = 0x02, - H4_SCO = 0x03, - H4_EVT = 0x04, - H4_ISO = 0x05, -}; - struct k_poll_signal uart_h2c_rx_sig; struct k_poll_signal uart_c2h_tx_sig; @@ -82,33 +74,33 @@ static int uart_c2h_tx(const uint8_t *data, size_t size) } /* Function expects that type is validated and only CMD, ISO or ACL will be used. */ -static uint32_t hci_payload_size(const uint8_t *hdr_buf, enum h4_type type) +static uint32_t hci_payload_size(const uint8_t *hdr_buf, uint8_t h4_type) { - switch (type) { - case H4_CMD: + switch (h4_type) { + case BT_HCI_H4_CMD: return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len; - case H4_ACL: + case BT_HCI_H4_ACL: return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len); - case H4_ISO: + case BT_HCI_H4_ISO: return bt_iso_hdr_len( sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len)); default: - LOG_ERR("Invalid type: %u", type); + LOG_ERR("Invalid type: %u", h4_type); return 0; } } -static uint8_t hci_hdr_size(enum h4_type type) +static uint8_t hci_hdr_size(uint8_t h4_type) { - switch (type) { - case H4_CMD: + switch (h4_type) { + case BT_HCI_H4_CMD: return sizeof(struct bt_hci_cmd_hdr); - case H4_ACL: + case BT_HCI_H4_ACL: return sizeof(struct bt_hci_acl_hdr); - case H4_ISO: + case BT_HCI_H4_ISO: return sizeof(struct bt_hci_iso_hdr); default: - LOG_ERR("Unexpected h4 type: %u", type); + LOG_ERR("Unexpected h4 type: %u", h4_type); return 0; } } @@ -171,7 +163,7 @@ static void send_hw_error(void) static void recover_sync_by_reset_pattern(void) { - /* { H4_CMD, le_16(HCI_CMD_OP_RESET), len=0 } */ + /* { BT_HCI_H4_CMD, le_16(HCI_CMD_OP_RESET), len=0 } */ const uint8_t h4_cmd_reset[] = {0x01, 0x03, 0x0C, 0x00}; const uint32_t reset_pattern = sys_get_be32(h4_cmd_reset); int err; @@ -367,7 +359,7 @@ const struct { struct bt_hci_evt_hdr hdr; struct bt_hci_evt_cmd_complete cc; } __packed cc_evt = { - .h4 = H4_EVT, + .h4 = BT_HCI_H4_EVT, .hdr = {.evt = BT_HCI_EVT_CMD_COMPLETE, .len = sizeof(struct bt_hci_evt_cmd_complete)}, .cc = {.ncmd = 1, .opcode = sys_cpu_to_le16(BT_OP_NOP)}, }; From 30ba0127130aa685a55796e03f8fe7251d345970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0446/1389] soc: nordic: nrf54h20: Add default ARM MPU regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 149df6b61b6b ("soc: nordic: nrf54h20: Disable USBHS core cache") inadvertedly removed default MPU regions defined in arm_mpu_regions.c. Without the SRAM_0 region defined all builds with asserts enabled result in failed assertion even before the kernel inits. The failed assertion is the very last step of arch_kernel_init() when MPU areas are marked for dynamic regions. Because the failure occurs so early, the device appears completely dead. Fix the issue by bringing the default regions to nrf54h20 custom regions file. Signed-off-by: Tomasz Moń --- soc/nordic/nrf54h/mpu_regions.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/soc/nordic/nrf54h/mpu_regions.c b/soc/nordic/nrf54h/mpu_regions.c index d4ffa23706447a..a19d2d33f10f94 100644 --- a/soc/nordic/nrf54h/mpu_regions.c +++ b/soc/nordic/nrf54h/mpu_regions.c @@ -11,6 +11,15 @@ #define USBHS_SIZE DT_REG_SIZE_BY_NAME(DT_NODELABEL(usbhs), core) static struct arm_mpu_region mpu_regions[] = { + MPU_REGION_ENTRY("FLASH_0", + CONFIG_FLASH_BASE_ADDRESS, + REGION_FLASH_ATTR(CONFIG_FLASH_BASE_ADDRESS, + CONFIG_FLASH_SIZE * 1024)), + MPU_REGION_ENTRY("SRAM_0", + CONFIG_SRAM_BASE_ADDRESS, + REGION_RAM_ATTR(CONFIG_SRAM_BASE_ADDRESS, + CONFIG_SRAM_SIZE * 1024)), + #if DT_NODE_HAS_STATUS(DT_NODELABEL(usbhs), okay) MPU_REGION_ENTRY("USBHS_CORE", USBHS_BASE, REGION_RAM_NOCACHE_ATTR(USBHS_BASE, USBHS_SIZE)), From 0bc9f10fcff5f7a4862599df3631d32f13e20acd Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0447/1389] MAINTAINERS: add nRF platform second maintainer Add myself as a second maintainer for nRF platform. Signed-off-by: Marcin Szymczyk --- MAINTAINERS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 0fdc29b6485d49..42e70bdb0b607f 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3467,11 +3467,11 @@ nRF Platforms: status: maintained maintainers: - anangl + - masz-nordic collaborators: - jaz1-nordic - kl-cruz - magp-nordic - - masz-nordic - nika-nordic files: - boards/nordic/ From 9e68a8204c0e629f7cb0aa8e6d95e4764a57b3d3 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Sun, 26 May 2024 22:38:48 +0200 Subject: [PATCH 0448/1389] tests: dma: loop transfer: Modernize zassert usage zassert_ok() is a more descriptive way to check for errors. Signed-off-by: Reto Schneider --- tests/drivers/dma/loop_transfer/src/test_dma_loop.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/drivers/dma/loop_transfer/src/test_dma_loop.c b/tests/drivers/dma/loop_transfer/src/test_dma_loop.c index c938ff18385a31..31cd058f60fbf8 100644 --- a/tests/drivers/dma/loop_transfer/src/test_dma_loop.c +++ b/tests/drivers/dma/loop_transfer/src/test_dma_loop.c @@ -55,12 +55,10 @@ static void test_transfer(const struct device *dev, uint32_t id) dma_block_cfg.dest_address = (uint32_t)rx_data[transfer_count]; #endif - zassert_false(dma_config(dev, id, &dma_cfg), - "Not able to config transfer %d", - transfer_count + 1); - zassert_false(dma_start(dev, id), - "Not able to start next transfer %d", - transfer_count + 1); + zassert_ok(dma_config(dev, id, &dma_cfg), "Not able to config transfer %d", + transfer_count + 1); + zassert_ok(dma_start(dev, id), "Not able to start next transfer %d", + transfer_count + 1); } } From 6815fc5ad060fe2216cf77e4f2db0d0a6ecf5b18 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0449/1389] drivers: i2c: rtio: Remove extra clear of RTIO_SQE_TRANSACTION Already handled within `i2c_rtio_copy()`. Not needed. Signed-off-by: Luis Ubieda --- drivers/i2c/i2c_rtio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/i2c/i2c_rtio.c b/drivers/i2c/i2c_rtio.c index 0a43acc4f62425..7fd90c3b89da1c 100644 --- a/drivers/i2c/i2c_rtio.c +++ b/drivers/i2c/i2c_rtio.c @@ -142,8 +142,6 @@ int i2c_rtio_transfer(struct i2c_rtio *ctx, struct i2c_msg *msgs, uint8_t num_ms goto out; } - sqe->flags &= ~RTIO_SQE_TRANSACTION; - rtio_submit(r, 1); cqe = rtio_cqe_consume(r); From aa439ec6fb3074a74d906cf49d7453d6220eaa71 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0450/1389] net: sockets: Move TLS sockets out of experimental TLS socket have now been in Zephyr for a few years already and are widely adopted across the codebase. Given above, they should no longer be considered an experimental feature. Signed-off-by: Robert Lubos --- subsys/net/lib/sockets/Kconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 8f7996a93bdb22..b93369e62ce337 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -147,10 +147,9 @@ config NET_SOCKETS_SERVICE_INIT_PRIO depends on NET_SOCKETS_SERVICE config NET_SOCKETS_SOCKOPT_TLS - bool "TCP TLS socket option support [EXPERIMENTAL]" + bool "TCP TLS socket option support" imply TLS_CREDENTIALS select MBEDTLS if NET_NATIVE - select EXPERIMENTAL help Enable TLS socket option support which automatically establishes a TLS connection to the remote host. @@ -180,10 +179,9 @@ config NET_SOCKETS_TLS_SET_MAX_FRAGMENT_LENGTH the maximum supported receive record length. config NET_SOCKETS_ENABLE_DTLS - bool "DTLS socket support [EXPERIMENTAL]" + bool "DTLS socket support" depends on NET_SOCKETS_SOCKOPT_TLS select MBEDTLS_DTLS if NET_NATIVE - select EXPERIMENTAL help Enable DTLS socket support. By default only TLS over TCP is supported. From 927006e4ec5db409fa0278d1b7323d8f35cccd1a Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0451/1389] net: lib: http_server: Add missing extern C in headers and were missing "extern C" statement. Signed-off-by: Robert Lubos --- include/zephyr/net/http/frame.h | 8 ++++++++ include/zephyr/net/http/server.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/include/zephyr/net/http/frame.h b/include/zephyr/net/http/frame.h index efdd78edf6ee5d..3e51539b4b7eb0 100644 --- a/include/zephyr/net/http/frame.h +++ b/include/zephyr/net/http/frame.h @@ -9,6 +9,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + enum http_frame_type { HTTP_SERVER_DATA_FRAME = 0x00, HTTP_SERVER_HEADERS_FRAME = 0x01, @@ -49,4 +53,8 @@ enum http_settings { HTTP_SETTINGS_MAX_HEADER_LIST_SIZE = 6, }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 60cab000fe0e15..9ebcb48404348a 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -15,6 +15,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define HTTP_SERVER_CLIENT_BUFFER_SIZE CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE #define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS #define HTTP_SERVER_MAX_CONTENT_TYPE_LEN CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH @@ -213,4 +217,8 @@ int http_server_start(void); /* Stops the HTTP2 server */ int http_server_stop(void); +#ifdef __cplusplus +} +#endif + #endif From 50b8117bac5da3a546f3530d6b733228a2dd3c54 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0452/1389] net: lib: http_server: Remove unused struct JSON support was dropped in the initial server implementation, so remove a leftover struct representing it. Signed-off-by: Robert Lubos --- include/zephyr/net/http/server.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 9ebcb48404348a..5731ae622c7d10 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -98,10 +98,6 @@ struct http_resource_detail_dynamic { }; BUILD_ASSERT(offsetof(struct http_resource_detail_dynamic, common) == 0); -struct http_resource_detail_rest { - struct http_resource_detail common; -}; - /** * @typedef http_resource_websocket_cb_t * @brief Callback used when a Websocket connection is setup. The application From 4568176cf41a2fdee2625fdc9f74bf51f3e5d412 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0453/1389] net: lib: http_server: Improve doxygen documentation Add missing doxygen groups for HTTP service and server APIs. Improve doxygen API documentation when missing. Signed-off-by: Robert Lubos --- include/zephyr/net/http/server.h | 177 +++++++++++++++++++++++++++--- include/zephyr/net/http/service.h | 11 ++ 2 files changed, 175 insertions(+), 13 deletions(-) diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 5731ae622c7d10..c11dc8b2caa434 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -8,6 +8,13 @@ #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVER_H_ #define ZEPHYR_INCLUDE_NET_HTTP_SERVER_H_ +/** + * @brief HTTP server API + * @defgroup http_server HTTP server API + * @ingroup networking + * @{ + */ + #include #include @@ -19,6 +26,8 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + #define HTTP_SERVER_CLIENT_BUFFER_SIZE CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE #define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS #define HTTP_SERVER_MAX_CONTENT_TYPE_LEN CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH @@ -30,29 +39,67 @@ extern "C" { #define HTTP2_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" +/** @endcond */ + +/** + * @brief HTTP server resource type. + */ enum http_resource_type { + /** Static resource, cannot be modified on runtime. */ HTTP_RESOURCE_TYPE_STATIC, + + /** Dynamic resource, server interacts with the application via registered + * @ref http_resource_dynamic_cb_t. + */ HTTP_RESOURCE_TYPE_DYNAMIC, + + /** Websocket resource, application takes control over Websocket connection + * after and upgrade. + */ HTTP_RESOURCE_TYPE_WEBSOCKET, }; +/** + * @brief Representation of a server resource, common for all resource types. + */ struct http_resource_detail { + /** Bitmask of supported HTTP methods (@ref http_method). */ uint32_t bitmask_of_supported_http_methods; + + /** Resource type. */ enum http_resource_type type; - int path_len; /* length of the URL path */ + + /** Length of the URL path. */ + int path_len; + + /** Content encoding of the resource. */ const char *content_encoding; }; + +/** @cond INTERNAL_HIDDEN */ BUILD_ASSERT(NUM_BITS( sizeof(((struct http_resource_detail *)0)->bitmask_of_supported_http_methods)) >= (HTTP_METHOD_END_VALUE - 1)); +/** @endcond */ +/** + * @brief Representation of a static server resource. + */ struct http_resource_detail_static { + /** Common resource details. */ struct http_resource_detail common; + + /** Content of the static resource. */ const void *static_data; + + /** Size of the static resource. */ size_t static_data_len; }; + +/** @cond INTERNAL_HIDDEN */ /* Make sure that the common is the first in the struct. */ BUILD_ASSERT(offsetof(struct http_resource_detail_static, common) == 0); +/** @endcond */ struct http_client_ctx; @@ -88,15 +135,38 @@ typedef int (*http_resource_dynamic_cb_t)(struct http_client_ctx *client, size_t data_len, void *user_data); +/** + * @brief Representation of a dynamic server resource. + */ struct http_resource_detail_dynamic { + /** Common resource details. */ struct http_resource_detail common; + + /** Resource callback used by the server to interact with the + * application. + */ http_resource_dynamic_cb_t cb; + + /** Data buffer used to exchanged data between server and the, + * application. + */ uint8_t *data_buffer; + + /** Length of the data in the data buffer. */ size_t data_buffer_len; + + /** A pointer to the client currently processing resource, used to + * prevent concurrent access to the resource from multiple clients. + */ struct http_client_ctx *holder; + + /** A pointer to the user data registered by the application. */ void *user_data; }; + +/** @cond INTERNAL_HIDDEN */ BUILD_ASSERT(offsetof(struct http_resource_detail_dynamic, common) == 0); +/** @endcond */ /** * @typedef http_resource_websocket_cb_t @@ -123,7 +193,12 @@ struct http_resource_detail_websocket { size_t data_buffer_len; void *user_data; }; + +/** @cond INTERNAL_HIDDEN */ BUILD_ASSERT(offsetof(struct http_resource_detail_websocket, common) == 0); +/** @endcond */ + +/** @cond INTERNAL_HIDDEN */ enum http_stream_state { HTTP_SERVER_STREAM_IDLE, @@ -163,58 +238,134 @@ enum http1_parser_state { #define HTTP_SERVER_INITIAL_WINDOW_SIZE 65536 #define HTTP_SERVER_WS_MAX_SEC_KEY_LEN 32 +/** @endcond */ + +/** @brief HTTP/2 stream representation. */ struct http_stream_ctx { - int stream_id; - enum http_stream_state stream_state; + int stream_id; /**< Stream identifier. */ + enum http_stream_state stream_state; /**< Stream state. */ int window_size; /**< Stream-level window size. */ }; +/** @brief HTTP/2 frame representation. */ struct http_frame { - uint32_t length; - uint32_t stream_identifier; - uint8_t type; - uint8_t flags; - uint8_t *payload; + uint32_t length; /**< Frame payload length. */ + uint32_t stream_identifier; /**< Stream ID the frame belongs to. */ + uint8_t type; /**< Frame type. */ + uint8_t flags; /**< Frame flags. */ + uint8_t *payload; /**< A pointer to the frame payload. */ }; +/** + * @brief Representation of an HTTP client connected to the server. + */ struct http_client_ctx { + /** Socket descriptor associated with the server. */ int fd; + + /** Client data buffer. */ unsigned char buffer[HTTP_SERVER_CLIENT_BUFFER_SIZE]; - unsigned char *cursor; /**< Cursor indicating currently processed byte. */ - size_t data_len; /**< Data left to process in the buffer. */ - int window_size; /**< Connection-level window size. */ + + /** Cursor indicating currently processed byte. */ + unsigned char *cursor; + + /** Data left to process in the buffer. */ + size_t data_len; + + /** Connection-level window size. */ + int window_size; + + /** Server state for the associated client. */ enum http_server_state server_state; + + /** Currently processed HTTP/2 frame. */ struct http_frame current_frame; + + /** Currently processed resource detail. */ struct http_resource_detail *current_detail; + + /** HTTP/2 header parser context. */ struct http_hpack_header_buf header_field; + + /** HTTP/2 streams context. */ struct http_stream_ctx streams[HTTP_SERVER_MAX_STREAMS]; + + /** HTTP/1 parser configuration. */ struct http_parser_settings parser_settings; + + /** HTTP/1 parser context. */ struct http_parser parser; + + /** Request URL. */ unsigned char url_buffer[CONFIG_HTTP_SERVER_MAX_URL_LENGTH]; + + /** Request content type. */ unsigned char content_type[CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH]; + + /** Temp buffer for currently processed header (HTTP/1 only). */ unsigned char header_buffer[HTTP_SERVER_MAX_HEADER_LEN]; + + /** Request content length. */ size_t content_len; + + /** Request method. */ enum http_method method; + + /** HTTP/1 parser state. */ enum http1_parser_state parser_state; + + /** Length of the payload length in the currently processed request + * fragment (HTTP/1 only). + */ int http1_frag_data_len; + + /** Client inactivity timer. The client connection is closed by the + * server when it expires. + */ struct k_work_delayable inactivity_timer; + + /* Websocket security key. */ IF_ENABLED(CONFIG_WEBSOCKET, (uint8_t ws_sec_key[HTTP_SERVER_WS_MAX_SEC_KEY_LEN])); + + /** Flag indicating that headers were sent in the reply. */ bool headers_sent : 1; + + /** Flag indicating that HTTP2 preface was sent. */ bool preface_sent : 1; + + /** Flag indicating that upgrade header was present in the request. */ bool has_upgrade_header : 1; + + /** Flag indicating HTTP/2 upgrade takes place. */ bool http2_upgrade : 1; + + /** Flag indicating Websocket upgrade takes place. */ bool websocket_upgrade : 1; + + /** Flag indicating Websocket key is being processed. */ bool websocket_sec_key_next : 1; }; -/* Starts the HTTP2 server */ +/** @brief Start the HTTP2 server. + * + * The server runs in a background thread. Once started, the server will create + * a server socket for all HTTP services registered in the system and accept + * connections from clients (see @ref HTTP_SERVICE_DEFINE). + */ int http_server_start(void); -/* Stops the HTTP2 server */ +/** @brief Stop the HTTP2 server. + * + * All server sockets are closed and the server thread is suspended. + */ int http_server_stop(void); #ifdef __cplusplus } #endif +/** + * @} + */ + #endif diff --git a/include/zephyr/net/http/service.h b/include/zephyr/net/http/service.h index 2f17b5022f7cd4..334444420b983b 100644 --- a/include/zephyr/net/http/service.h +++ b/include/zephyr/net/http/service.h @@ -7,6 +7,13 @@ #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ #define ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ +/** + * @brief HTTP service API + * @defgroup http_service HTTP service API + * @ingroup networking + * @{ + */ + #include #include @@ -235,4 +242,8 @@ struct http_service_desc { } #endif +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ */ From 0b3f92e5d803c835c7e16886baf345bc0bcaf972 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0454/1389] doc: net: Add HTTP server documentation Add documentation page for HTTP server functionality. Rename existing HTTP documentation to HTTP client, as it only covers the client library. Signed-off-by: Robert Lubos --- .../api/{http.rst => http_client.rst} | 4 +- .../networking/api/http_server.rst | 303 ++++++++++++++++++ doc/connectivity/networking/api/protocols.rst | 3 +- doc/connectivity/networking/overview.rst | 13 + samples/net/sockets/http_client/README.rst | 2 +- samples/net/sockets/http_server/README.rst | 7 +- 6 files changed, 326 insertions(+), 6 deletions(-) rename doc/connectivity/networking/api/{http.rst => http_client.rst} (98%) create mode 100644 doc/connectivity/networking/api/http_server.rst diff --git a/doc/connectivity/networking/api/http.rst b/doc/connectivity/networking/api/http_client.rst similarity index 98% rename from doc/connectivity/networking/api/http.rst rename to doc/connectivity/networking/api/http_client.rst index d32748e77fae5b..fa7876d8411155 100644 --- a/doc/connectivity/networking/api/http.rst +++ b/doc/connectivity/networking/api/http_client.rst @@ -1,6 +1,6 @@ -.. _http_interface: +.. _http_client_interface: -HTTP client +HTTP Client ########### .. contents:: diff --git a/doc/connectivity/networking/api/http_server.rst b/doc/connectivity/networking/api/http_server.rst new file mode 100644 index 00000000000000..362d19ac374860 --- /dev/null +++ b/doc/connectivity/networking/api/http_server.rst @@ -0,0 +1,303 @@ +.. _http_server_interface: + +HTTP Server +########### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +Zephyr provides an HTTP server library, which allows to register HTTP services +and HTTP resources associated with those services. The server creates a listening +socket for every registered service, and handles incoming client connections. +It's possible to communicate over a plain TCP socket (HTTP) or a TLS socket (HTTPS). +Both, HTTP/1.1 (RFC 2616) and HTTP/2 (RFC 9113) protocol versions are supported. + +The server operation is generally transparent for the application, running in a +background thread. The application can control the server activity with +respective API functions. + +Certain resource types (for example dynamic resource) provide resource-specific +application callbacks, allowing the server to interact with the application (for +instance provide resource content, or process request payload). + +Currently, the following resource types are supported: + +* Static resources - content defined compile-time, cannot be modified at runtime + (:c:enumerator:`HTTP_RESOURCE_TYPE_STATIC`). + +* Dynamic resources - content provided at runtime by respective application + callback (:c:enumerator:`HTTP_RESOURCE_TYPE_DYNAMIC`). + +* Websocket resources - allowing to establish Websocket connections with the + server (:c:enumerator:`HTTP_RESOURCE_TYPE_WEBSOCKET`). + +Zephyr provides a sample demonstrating HTTP(s) server operation and various +resource types usage. See :zephyr:code-sample:`sockets-http-server` for more +information. + +Server Setup +************ + +A few prerequisites are needed in order to enable HTTP server functionality in +the application. + +First of all, the HTTP server has to be enabled in applications configuration file +with :kconfig:option:`CONFIG_HTTP_SERVER` Kconfig option: + +.. code-block:: cfg + :caption: ``prj.conf`` + + CONFIG_HTTP_SERVER=y + +All HTTP services and HTTP resources are placed in a dedicated linker section. +The linker section for services is predefined locally, however the application +is responsible for defining linker sections for resources associated with +respective services. Linker section names for resources should be prefixed with +``http_resource_desc_``, appended with the service name. + +Linker sections for resources should be defined in a linker file. For example, +for a service named ``my_service``, the linker section shall be defined as follows: + +.. code-block:: c + :caption: ``sections-rom.ld`` + + #include + + ITERABLE_SECTION_ROM(http_resource_desc_my_service, Z_LINK_ITERABLE_SUBALIGN) + +Finally, the linker file and linker section have to be added to your application +using CMake: + +.. code-block:: cmake + :caption: ``CMakeLists.txt`` + + zephyr_linker_sources(SECTIONS sections-rom.ld) + zephyr_linker_section(NAME http_resource_desc_my_service + KVMA RAM_REGION GROUP RODATA_REGION + SUBALIGN Z_LINK_ITERABLE_SUBALIGN) + +.. note:: + + You need to define a separate linker section for each HTTP service + registered in the system. + +Sample Usage +************ + +Services +======== + +The application needs to define an HTTP service (or multiple services), with +the same name as used for the linker section with :c:macro:`HTTP_SERVICE_DEFINE` +macro: + +.. code-block:: c + + #include + + static uint16_t http_service_port = 80; + + HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL); + +Alternatively, an HTTPS service can be defined with with +:c:macro:`HTTPS_SERVICE_DEFINE`: + +.. code-block:: c + + #include + #include + + #define HTTP_SERVER_CERTIFICATE_TAG 1 + + static uint16_t https_service_port = 443; + static const sec_tag_t sec_tag_list[] = { + HTTP_SERVER_CERTIFICATE_TAG, + }; + + HTTPS_SERVICE_DEFINE(my_service, "0.0.0.0", &https_service_port, 1, 10, + NULL, sec_tag_list, sizeof(sec_tag_list)); + +.. note:: + + HTTPS services rely on TLS credentials being registered in the system. + See :ref:`sockets_tls_credentials_subsys` for information on how to + configure TLS credentials in the system. + +Once HTTP(s) service is defined, resources can be registered for it with +:c:macro:`HTTP_RESOURCE_DEFINE` macro. + +Static resources +================ + +Static resource content is defined build-time and is immutable. The following +example shows how gzip compressed webpage can be defined as a static resource +in the application: + +.. code-block:: c + + static const uint8_t index_html_gz[] = { + #include "index.html.gz.inc" + }; + + struct http_resource_detail_static index_html_gz_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_STATIC, + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + .content_encoding = "gzip", + }, + .static_data = index_html_gz, + .static_data_len = sizeof(index_html_gz), + }; + + HTTP_RESOURCE_DEFINE(index_html_gz_resource, my_service, "/", + &index_html_gz_resource_detail); + +The resource content and content encoding is application specific. For the above +example, a gzip compressed webpage can be generated during build, by adding the +following code to the application's ``CMakeLists.txt`` file: + +.. code-block:: cmake + :caption: ``CMakeLists.txt`` + + set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) + set(source_file_index src/index.html) + generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.inc --gzip) + +where ``src/index.html`` is the location of the webpage to be compressed. + +Dynamic resources +================= + +For dynamic resource, a resource callback is registered to exchange data between +the server and the application. The application defines a resource buffer used +to pass the request payload data from the server, and to provide response payload +to the server. The following example code shows how to register a dynamic resource +with a simple resource handler, which echoes received data back to the client: + +.. code-block:: c + + static uint8_t recv_buffer[1024]; + + static int dyn_handler(struct http_client_ctx *client, + enum http_data_status status, uint8_t *buffer, + size_t len, void *user_data) + { + #define MAX_TEMP_PRINT_LEN 32 + static char print_str[MAX_TEMP_PRINT_LEN]; + enum http_method method = client->method; + static size_t processed; + + __ASSERT_NO_MSG(buffer != NULL); + + if (status == HTTP_SERVER_DATA_ABORTED) { + LOG_DBG("Transaction aborted after %zd bytes.", processed); + processed = 0; + return 0; + } + + processed += len; + + snprintf(print_str, sizeof(print_str), "%s received (%zd bytes)", + http_method_str(method), len); + LOG_HEXDUMP_DBG(buffer, len, print_str); + + if (status == HTTP_SERVER_DATA_FINAL) { + LOG_DBG("All data received (%zd bytes).", processed); + processed = 0; + } + + /* This will echo data back to client as the buffer and recv_buffer + * point to same area. + */ + return len; + } + + struct http_resource_detail_dynamic dyn_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_DYNAMIC, + .bitmask_of_supported_http_methods = + BIT(HTTP_GET) | BIT(HTTP_POST), + }, + .cb = dyn_handler, + .data_buffer = recv_buffer, + .data_buffer_len = sizeof(recv_buffer), + .user_data = NULL, + }; + + HTTP_RESOURCE_DEFINE(dyn_resource, my_service, "/dynamic", + &dyn_resource_detail); + + +The resource callback may be called multiple times for a single request, hence +the application should be able to keep track of the received data progress. + +The ``status`` field informs the application about the progress in passing +request payload from the server to the application. As long as the status +reports :c:enumerator:`HTTP_SERVER_DATA_MORE`, the application should expect +more data to be provided in a consecutive callback calls. +Once all request payload has been passed to the application, the server reports +:c:enumerator:`HTTP_SERVER_DATA_FINAL` status. In case of communication errors +during request processing (for example client closed the connection before +complete payload has been received), the server reports +:c:enumerator:`HTTP_SERVER_DATA_ABORTED`. Either of the two events indicate that +the application shall reset any progress recorded for the resource, and await +a new request to come. The server guarantees that the resource can only be +accessed by single client at a time. + +The resource callback returns the number of bytes to be replied in the response +payload to the server (provided in the resource data buffer). In case there is +no more data to be included in the response, the callback should return 0. + +The server will call the resource callback until it provided all request data +to the application, and the application reports there is no more data to include +in the reply. + +Websocket resources +=================== + +Websocket resources register an application callback, which is is called when a +Websocket connection upgrade takes place. The callback is provided with a socket +descriptor corresponding to the underlying TCP/TLS connection. Once called, +the application takes full control over the socket, i. e. is responsible to +release it when done. + +.. code-block:: c + + static int ws_socket; + static uint8_t ws_recv_buffer[1024]; + + int ws_setup(int sock, void *user_data) + { + ws_socket = sock; + return 0; + } + + struct http_resource_detail_websocket ws_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_WEBSOCKET, + /* We need HTTP/1.1 Get method for upgrading */ + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + }, + .cb = ws_setup, + .data_buffer = ws_recv_buffer, + .data_buffer_len = sizeof(ws_recv_buffer), + .user_data = NULL, /* Fill this for any user specific data */ + }; + + HTTP_RESOURCE_DEFINE(ws_resource, my_service, "/", &ws_resource_detail); + +The above minimalistic example shows how to register a Websocket resource with +a simple callback, used only to store the socket descriptor provided. Further +processing of the Websocket connection is application-specific, hence outside +of scope of this guide. See :zephyr:code-sample:`sockets-http-server` for an +example Websocket-based echo service implementation. + +API Reference +************* + +.. doxygengroup:: http_service +.. doxygengroup:: http_server diff --git a/doc/connectivity/networking/api/protocols.rst b/doc/connectivity/networking/api/protocols.rst index aea485b74aa6d0..57aeaae8d021a3 100644 --- a/doc/connectivity/networking/api/protocols.rst +++ b/doc/connectivity/networking/api/protocols.rst @@ -10,7 +10,8 @@ Protocols coap coap_client coap_server - http + http_client + http_server lwm2m mqtt mqtt_sn diff --git a/doc/connectivity/networking/overview.rst b/doc/connectivity/networking/overview.rst index fdcc73753a280d..73876449c88fa4 100644 --- a/doc/connectivity/networking/overview.rst +++ b/doc/connectivity/networking/overview.rst @@ -84,6 +84,13 @@ can be disabled if not needed. supported in similar manner when enabled with a Kconfig option. :zephyr:code-sample:`lwm2m-client` sample implements the library as an example. +* **HTTP** Hypertext Transfer Protocol client and server are supported. + :ref:`http_client_interface` library supports HTTP/1.1 (`RFC 2616`_). + :ref:`http_server_interface` library supports HTTP/1.1 (`RFC 2616`_) and + HTTP/2 (`RFC 9113`_). + :zephyr:code-sample:`sockets-http-client` and + :zephyr:code-sample:`sockets-http-server` samples are provided. + * **DNS** Domain Name Service (`RFC 1035 `_) client functionality is supported. @@ -177,3 +184,9 @@ The networking stack source code tree is organized as follows: .. _LwM2M specification 1.1.1: http://openmobilealliance.org/release/LightweightM2M/V1_1_1-20190617-A/ + +.. _RFC 2616: + https://tools.ietf.org/html/rfc2616 + +.. _RFC 9113: + https://tools.ietf.org/html/rfc9113 diff --git a/samples/net/sockets/http_client/README.rst b/samples/net/sockets/http_client/README.rst index 855c36d068a29b..d360ae45edfaef 100644 --- a/samples/net/sockets/http_client/README.rst +++ b/samples/net/sockets/http_client/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: sockets-http-client - :name: HTTP client + :name: HTTP Client :relevant-api: bsd_sockets http_client tls_credentials secure_sockets_options Implement an HTTP(S) client that issues a variety of HTTP requests. diff --git a/samples/net/sockets/http_server/README.rst b/samples/net/sockets/http_server/README.rst index 739635cf8a1910..8e6740a6348d7d 100644 --- a/samples/net/sockets/http_server/README.rst +++ b/samples/net/sockets/http_server/README.rst @@ -1,5 +1,8 @@ -Zephyr HTTP Server -================== +.. zephyr:code-sample:: sockets-http-server + :name: HTTP Server + :relevant-api: http_service http_server tls_credentials + + Implement an HTTP(s) Server demonstrating various resource types. Overview -------- From 231b37e747026634e9dfd1d78fb93414c78f724d Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0455/1389] twister: Fix platform report generation called multiple times Fix Twister to generate platform reports (`--platform-reports`) only once for each platform instead of repeating it multiple times for each instance executed. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/reports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index e03d754ee8c296..254f2497d74343 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -549,8 +549,8 @@ def save_reports(self, name, suffix, report_dir, no_update, platform_reports): def target_report(self, json_file, outdir, suffix): - platforms = {inst.platform for _, inst in self.instances.items()} - for platform in platforms: + platforms = {repr(inst.platform):inst.platform for _, inst in self.instances.items()} + for platform in platforms.values(): if suffix: filename = os.path.join(outdir,"{}_{}.xml".format(platform.normalized_name, suffix)) json_platform_file = os.path.join(outdir,"{}_{}.json".format(platform.normalized_name, suffix)) From 3275a396d2d3a065caa0085d11c2c1705a537913 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0456/1389] coding guidelines: comply with MISRA Rule 11.8 - modified parameter types to receive a const pointer when a non-const pointer is not needed - avoided redundant casts Signed-off-by: Hess Nathan --- kernel/device.c | 2 +- kernel/include/mmu.h | 2 +- kernel/pipes.c | 8 ++++---- kernel/sem.c | 2 +- kernel/stack.c | 2 +- kernel/thread.c | 2 +- kernel/userspace.c | 4 ++-- kernel/userspace_handler.c | 5 ++--- 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/kernel/device.c b/kernel/device.c index 6124ada5140f81..4b19d247c0099d 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -59,7 +59,7 @@ static inline const struct device *z_vrfy_device_get_binding(const char *name) { char name_copy[Z_DEVICE_MAX_NAME_LEN]; - if (k_usermode_string_copy(name_copy, (char *)name, sizeof(name_copy)) + if (k_usermode_string_copy(name_copy, name, sizeof(name_copy)) != 0) { return NULL; } diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index 590852e4e37068..4afb828f4a7fcc 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -26,7 +26,7 @@ * core kernel. */ #define Z_PHYS_RAM_START ((uintptr_t)CONFIG_SRAM_BASE_ADDRESS) -#define Z_PHYS_RAM_SIZE ((size_t)KB(CONFIG_SRAM_SIZE)) +#define Z_PHYS_RAM_SIZE (KB(CONFIG_SRAM_SIZE)) #define Z_PHYS_RAM_END (Z_PHYS_RAM_START + Z_PHYS_RAM_SIZE) #define Z_NUM_PAGE_FRAMES (Z_PHYS_RAM_SIZE / (size_t)CONFIG_MMU_PAGE_SIZE) diff --git a/kernel/pipes.c b/kernel/pipes.c index de5c6656165a64..7ef2c1fa022873 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -519,9 +519,9 @@ int z_vrfy_k_pipe_put(struct k_pipe *pipe, const void *data, { K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); K_OOPS(K_SYSCALL_MEMORY_WRITE(bytes_written, sizeof(*bytes_written))); - K_OOPS(K_SYSCALL_MEMORY_READ((void *)data, bytes_to_write)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, bytes_to_write)); - return z_impl_k_pipe_put((struct k_pipe *)pipe, data, + return z_impl_k_pipe_put(pipe, data, bytes_to_write, bytes_written, min_xfer, timeout); } @@ -727,9 +727,9 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, { K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); K_OOPS(K_SYSCALL_MEMORY_WRITE(bytes_read, sizeof(*bytes_read))); - K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)data, bytes_to_read)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, bytes_to_read)); - return z_impl_k_pipe_get((struct k_pipe *)pipe, (void *)data, + return z_impl_k_pipe_get(pipe, data, bytes_to_read, bytes_read, min_xfer, timeout); } diff --git a/kernel/sem.c b/kernel/sem.c index 52f1e0c1b0ab85..0a8b861cfbec56 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -189,7 +189,7 @@ void z_impl_k_sem_reset(struct k_sem *sem) static inline int z_vrfy_k_sem_take(struct k_sem *sem, k_timeout_t timeout) { K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); - return z_impl_k_sem_take((struct k_sem *)sem, timeout); + return z_impl_k_sem_take(sem, timeout); } #include diff --git a/kernel/stack.c b/kernel/stack.c index adebb2d68e80f5..5ddc4178f89dfc 100644 --- a/kernel/stack.c +++ b/kernel/stack.c @@ -51,7 +51,7 @@ int32_t z_impl_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries) if (buffer != NULL) { k_stack_init(stack, buffer, num_entries); stack->flags = K_STACK_FLAG_ALLOC; - ret = (int32_t)0; + ret = 0; } else { ret = -ENOMEM; } diff --git a/kernel/thread.c b/kernel/thread.c index e11e53087d0dce..dfd5eb7bdd698d 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -174,7 +174,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * * the current z_vrfy / z_impl split does not provide a * means of doing so. */ - if (k_usermode_string_copy(name, (char *)str, sizeof(name)) != 0) { + if (k_usermode_string_copy(name, str, sizeof(name)) != 0) { return -EFAULT; } diff --git a/kernel/userspace.c b/kernel/userspace.c index a60f2c76dad7df..fed8f3a983c5f4 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -221,7 +221,7 @@ static size_t obj_align_get(enum k_objects otype) return ret; } -static struct dyn_obj *dyn_object_find(void *obj) +static struct dyn_obj *dyn_object_find(const void *obj) { struct dyn_obj *node; k_spinlock_key_t key; @@ -490,7 +490,7 @@ struct k_object *k_object_find(const void *obj) * 11.8 but is justified since we know dynamic objects * were not declared with a const qualifier. */ - dyn = dyn_object_find((void *)obj); + dyn = dyn_object_find(obj); if (dyn != NULL) { ret = &dyn->kobj; } diff --git a/kernel/userspace_handler.c b/kernel/userspace_handler.c index a26c50828d76ca..da4053b4bdbda9 100644 --- a/kernel/userspace_handler.c +++ b/kernel/userspace_handler.c @@ -70,9 +70,8 @@ static inline void z_vrfy_k_object_release(const void *object) { struct k_object *ko; - ko = validate_any_object((void *)object); - K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", - (void *)object)); + ko = validate_any_object(object); + K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", object)); k_thread_perms_clear(ko, _current); } #include From 0f34db8f1297e98d64b076d0fb87aa0b4f2e445b Mon Sep 17 00:00:00 2001 From: Adam Matus Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0457/1389] net: zperf: Move TCP nodelay socket option TCP nodelay option is part of zperf upload params, but was not being set in common zperf_prepare_upload_sock function. Move it there to align with how other options are set. Signed-off-by: Adam Matus --- subsys/net/lib/zperf/zperf_common.c | 10 +++++++++- subsys/net/lib/zperf/zperf_internal.h | 2 +- subsys/net/lib/zperf/zperf_tcp_uploader.c | 11 ++--------- subsys/net/lib/zperf/zperf_udp_uploader.c | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/subsys/net/lib/zperf/zperf_common.c b/subsys/net/lib/zperf/zperf_common.c index 3c39008965c47f..61a49bde39af75 100644 --- a/subsys/net/lib/zperf/zperf_common.c +++ b/subsys/net/lib/zperf/zperf_common.c @@ -110,7 +110,7 @@ int zperf_get_ipv4_addr(char *host, struct in_addr *addr) } int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, uint8_t tos, - int priority, int proto) + int priority, int tcp_nodelay, int proto) { socklen_t addrlen = peer_addr->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : @@ -189,6 +189,14 @@ int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, uint8_t tos, } } + if (proto == IPPROTO_TCP && tcp_nodelay && + zsock_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + &tcp_nodelay, + sizeof(tcp_nodelay)) != 0) { + NET_WARN("Failed to set IPPROTO_TCP - TCP_NODELAY socket option."); + return -EINVAL; + } + ret = zsock_connect(sock, peer_addr, addrlen); if (ret < 0) { NET_ERR("Connect failed (%d)", errno); diff --git a/subsys/net/lib/zperf/zperf_internal.h b/subsys/net/lib/zperf/zperf_internal.h index 21392e734547cc..a798edd8537755 100644 --- a/subsys/net/lib/zperf/zperf_internal.h +++ b/subsys/net/lib/zperf/zperf_internal.h @@ -104,7 +104,7 @@ struct sockaddr_in *zperf_get_sin(void); extern void connect_ap(char *ssid); int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, uint8_t tos, - int priority, int proto); + int priority, int tcp_nodelay, int proto); uint32_t zperf_packet_duration(uint32_t packet_size, uint32_t rate_in_kbps); diff --git a/subsys/net/lib/zperf/zperf_tcp_uploader.c b/subsys/net/lib/zperf/zperf_tcp_uploader.c index 7958f80b37306f..659107df16438e 100644 --- a/subsys/net/lib/zperf/zperf_tcp_uploader.c +++ b/subsys/net/lib/zperf/zperf_tcp_uploader.c @@ -133,19 +133,12 @@ int zperf_tcp_upload(const struct zperf_upload_params *param, } sock = zperf_prepare_upload_sock(¶m->peer_addr, param->options.tos, - param->options.priority, IPPROTO_TCP); + param->options.priority, param->options.tcp_nodelay, + IPPROTO_TCP); if (sock < 0) { return sock; } - if (param->options.tcp_nodelay && - zsock_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - ¶m->options.tcp_nodelay, - sizeof(param->options.tcp_nodelay)) != 0) { - NET_WARN("Failed to set IPPROTO_TCP - TCP_NODELAY socket option."); - return -EINVAL; - } - ret = tcp_upload(sock, param->duration_ms, param->packet_size, result); zsock_close(sock); diff --git a/subsys/net/lib/zperf/zperf_udp_uploader.c b/subsys/net/lib/zperf/zperf_udp_uploader.c index 548a0a55f10f2b..daf2cf21d01f11 100644 --- a/subsys/net/lib/zperf/zperf_udp_uploader.c +++ b/subsys/net/lib/zperf/zperf_udp_uploader.c @@ -305,7 +305,7 @@ int zperf_udp_upload(const struct zperf_upload_params *param, } sock = zperf_prepare_upload_sock(¶m->peer_addr, param->options.tos, - param->options.priority, IPPROTO_UDP); + param->options.priority, 0, IPPROTO_UDP); if (sock < 0) { return sock; } From fc3f60c6f46418a9fbd7233c69e415d9459abe03 Mon Sep 17 00:00:00 2001 From: Adam Matus Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0458/1389] net: zperf: Add periodic reporting for upload Add option for zperf tcp upload that will enable periodic result reporting. This is useful for monitoring performance swings during a longer session. Signed-off-by: Adam Matus --- include/zephyr/net/zperf.h | 2 + subsys/net/lib/zperf/zperf_shell.c | 88 ++++++++++++++++++++++- subsys/net/lib/zperf/zperf_tcp_uploader.c | 62 ++++++++++++++-- 3 files changed, 144 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/zperf.h b/include/zephyr/net/zperf.h index a6290483300907..21ce74bb33b7d9 100644 --- a/include/zephyr/net/zperf.h +++ b/include/zephyr/net/zperf.h @@ -26,6 +26,7 @@ extern "C" { enum zperf_status { ZPERF_SESSION_STARTED, + ZPERF_SESSION_PERIODIC_RESULT, ZPERF_SESSION_FINISHED, ZPERF_SESSION_ERROR } __packed; @@ -40,6 +41,7 @@ struct zperf_upload_params { uint8_t tos; int tcp_nodelay; int priority; + uint32_t report_interval_ms; } options; }; diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index 72d406e980296b..1b97bdde7b92c9 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -361,6 +361,9 @@ static void udp_session_cb(enum zperf_status status, case ZPERF_SESSION_ERROR: shell_fprintf(sh, SHELL_ERROR, "UDP session error.\n"); break; + + default: + break; } } @@ -476,7 +479,7 @@ static void shell_udp_upload_print_stats(const struct shell *sh, struct zperf_results *results) { if (IS_ENABLED(CONFIG_NET_UDP)) { - unsigned int rate_in_kbps, client_rate_in_kbps; + uint64_t rate_in_kbps, client_rate_in_kbps; shell_fprintf(sh, SHELL_NORMAL, "-\nUpload completed!\n"); @@ -540,7 +543,7 @@ static void shell_tcp_upload_print_stats(const struct shell *sh, struct zperf_results *results) { if (IS_ENABLED(CONFIG_NET_TCP)) { - unsigned int client_rate_in_kbps; + uint64_t client_rate_in_kbps; shell_fprintf(sh, SHELL_NORMAL, "-\nUpload completed!\n"); @@ -569,6 +572,37 @@ static void shell_tcp_upload_print_stats(const struct shell *sh, } } +static void shell_tcp_upload_print_periodic(const struct shell *sh, + struct zperf_results *results) +{ + if (IS_ENABLED(CONFIG_NET_TCP)) { + uint64_t client_rate_in_kbps; + + if (results->client_time_in_us != 0U) { + client_rate_in_kbps = (uint32_t) + (((uint64_t)results->nb_packets_sent * + (uint64_t)results->packet_size * (uint64_t)8 * + (uint64_t)USEC_PER_SEC) / + (results->client_time_in_us * 1000U)); + } else { + client_rate_in_kbps = 0U; + } + + shell_fprintf(sh, SHELL_NORMAL, "Duration: "); + print_number_64(sh, results->client_time_in_us, + TIME_US, TIME_US_UNIT); + shell_fprintf(sh, SHELL_NORMAL, " | "); + shell_fprintf(sh, SHELL_NORMAL, "Packets: %6u | ", + results->nb_packets_sent); + shell_fprintf(sh, SHELL_NORMAL, + "Errors: %6u | ", + results->nb_packets_errors); + shell_fprintf(sh, SHELL_NORMAL, "Rate: "); + print_number(sh, client_rate_in_kbps, KBPS, KBPS_UNIT); + shell_fprintf(sh, SHELL_NORMAL, "\n"); + } +} + static void udp_upload_cb(enum zperf_status status, struct zperf_results *result, void *user_data) @@ -587,6 +621,9 @@ static void udp_upload_cb(enum zperf_status status, case ZPERF_SESSION_ERROR: shell_fprintf(sh, SHELL_ERROR, "UDP upload failed\n"); break; + + default: + break; } } @@ -600,6 +637,10 @@ static void tcp_upload_cb(enum zperf_status status, case ZPERF_SESSION_STARTED: break; + case ZPERF_SESSION_PERIODIC_RESULT: + shell_tcp_upload_print_periodic(sh, result); + break; + case ZPERF_SESSION_FINISHED: { shell_tcp_upload_print_stats(sh, result); break; @@ -866,6 +907,24 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc, opt_cnt += 2; break; + case 'i': + int seconds = parse_arg(&i, argc, argv); + + if (is_udp) { + shell_fprintf(sh, SHELL_WARNING, + "UDP does not support -i option\n"); + return -ENOEXEC; + } + if (seconds < 0 || seconds > UINT16_MAX) { + shell_fprintf(sh, SHELL_WARNING, + "Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + + param.options.report_interval_ms = seconds * MSEC_PER_SEC; + opt_cnt += 2; + break; + default: shell_fprintf(sh, SHELL_WARNING, "Unrecognized argument: %s\n", argv[i]); @@ -1081,6 +1140,24 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc, opt_cnt += 2; break; + case 'i': + int seconds = parse_arg(&i, argc, argv); + + if (is_udp) { + shell_fprintf(sh, SHELL_WARNING, + "UDP does not support -i option\n"); + return -ENOEXEC; + } + if (seconds < 0 || seconds > UINT16_MAX) { + shell_fprintf(sh, SHELL_WARNING, + "Parse error: %s\n", argv[i]); + return -ENOEXEC; + } + + param.options.report_interval_ms = seconds * MSEC_PER_SEC; + opt_cnt += 2; + break; + default: shell_fprintf(sh, SHELL_WARNING, "Unrecognized argument: %s\n", argv[i]); @@ -1250,6 +1327,9 @@ static void tcp_session_cb(enum zperf_status status, case ZPERF_SESSION_ERROR: shell_fprintf(sh, SHELL_ERROR, "TCP session error.\n"); break; + + default: + break; } } @@ -1390,6 +1470,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp, "Available options:\n" "-S tos: Specify IPv4/6 type of service\n" "-a: Asynchronous call (shell will not block for the upload)\n" + "-i sec: Periodic reporting interval in seconds (async only)\n" "-n: Disable Nagle's algorithm\n" #ifdef CONFIG_NET_CONTEXT_PRIORITY "-p: Specify custom packet priority\n" @@ -1409,12 +1490,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp, "Available options:\n" "-S tos: Specify IPv4/6 type of service\n" "-a: Asynchronous call (shell will not block for the upload)\n" + "-i sec: Periodic reporting interval in seconds (async only)\n" + "-n: Disable Nagle's algorithm\n" #ifdef CONFIG_NET_CONTEXT_PRIORITY "-p: Specify custom packet priority\n" #endif /* CONFIG_NET_CONTEXT_PRIORITY */ "Example: tcp upload2 v6 1 1K\n" "Example: tcp upload2 v4\n" - "-n: Disable Nagle's algorithm\n" #if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR_SET) "Default IPv6 address is " MY_IP6ADDR ", destination [" DST_IP6ADDR "]:" DEF_PORT_STR "\n" diff --git a/subsys/net/lib/zperf/zperf_tcp_uploader.c b/subsys/net/lib/zperf/zperf_tcp_uploader.c index 659107df16438e..6b3fe458347dbf 100644 --- a/subsys/net/lib/zperf/zperf_tcp_uploader.c +++ b/subsys/net/lib/zperf/zperf_tcp_uploader.c @@ -150,20 +150,72 @@ static void tcp_upload_async_work(struct k_work *work) { struct zperf_async_upload_context *upload_ctx = CONTAINER_OF(work, struct zperf_async_upload_context, work); - struct zperf_results result; + struct zperf_results result = { 0 }; int ret; + struct zperf_upload_params param = upload_ctx->param; + int sock; upload_ctx->callback(ZPERF_SESSION_STARTED, NULL, upload_ctx->user_data); - ret = zperf_tcp_upload(&upload_ctx->param, &result); - if (ret < 0) { + sock = zperf_prepare_upload_sock(¶m.peer_addr, param.options.tos, + param.options.priority, param.options.tcp_nodelay, + IPPROTO_TCP); + + if (sock < 0) { upload_ctx->callback(ZPERF_SESSION_ERROR, NULL, upload_ctx->user_data); + return; + } + + if (param.options.report_interval_ms > 0) { + uint32_t report_interval = param.options.report_interval_ms; + uint32_t duration = param.duration_ms; + + /* Compute how many upload rounds will be executed and the duration + * of the last round when total duration isn't divisible by interval + */ + uint32_t rounds = (duration + report_interval - 1) / report_interval; + uint32_t last_round_duration = duration - ((rounds - 1) * report_interval); + + struct zperf_results periodic_result; + + for (; rounds > 0; rounds--) { + uint32_t round_duration; + + if (rounds == 1) { + round_duration = last_round_duration; + } else { + round_duration = report_interval; + } + ret = tcp_upload(sock, round_duration, param.packet_size, &periodic_result); + if (ret < 0) { + upload_ctx->callback(ZPERF_SESSION_ERROR, NULL, + upload_ctx->user_data); + return; + } + upload_ctx->callback(ZPERF_SESSION_PERIODIC_RESULT, &periodic_result, + upload_ctx->user_data); + + result.nb_packets_sent += periodic_result.nb_packets_sent; + result.client_time_in_us += periodic_result.client_time_in_us; + result.nb_packets_errors += periodic_result.nb_packets_errors; + } + + result.packet_size = periodic_result.packet_size; + } else { - upload_ctx->callback(ZPERF_SESSION_FINISHED, &result, - upload_ctx->user_data); + ret = tcp_upload(sock, param.duration_ms, param.packet_size, &result); + if (ret < 0) { + upload_ctx->callback(ZPERF_SESSION_ERROR, NULL, + upload_ctx->user_data); + return; + } } + + upload_ctx->callback(ZPERF_SESSION_FINISHED, &result, + upload_ctx->user_data); + zsock_close(sock); } int zperf_tcp_upload_async(const struct zperf_upload_params *param, From f97d8481d0231bdd241cc925a9c0d61e1899c83b Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0459/1389] boards: nxp: Fix usage of DT_CHOSEN() macro to get chosen Zephyr Flash Used multiple places in the tree. The idea is to determine if this node corresponds to a specific node (e.g: flexspi) so that specific configurations can get done. Without the fix, the macro expansions were defaulting to false. Signed-off-by: Luis Ubieda --- boards/nxp/mimxrt1010_evk/init.c | 2 +- soc/nxp/imxrt/imxrt10xx/lpm_rt1064.c | 16 ++++++++-------- soc/nxp/imxrt/imxrt11xx/soc.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/boards/nxp/mimxrt1010_evk/init.c b/boards/nxp/mimxrt1010_evk/init.c index 1fd4b67e457e85..3e2b49b112e8b1 100644 --- a/boards/nxp/mimxrt1010_evk/init.c +++ b/boards/nxp/mimxrt1010_evk/init.c @@ -7,7 +7,7 @@ void SystemInitHook(void) { -#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(zephyr_flash))) /* AT25SF128A SPI Flash on the RT1010-EVK requires special alignment * considerations, so set the READADDROPT bit in the FlexSPI so it * will fetch more data than each AHB burst requires to meet alignment diff --git a/soc/nxp/imxrt/imxrt10xx/lpm_rt1064.c b/soc/nxp/imxrt/imxrt10xx/lpm_rt1064.c index 9020b9bf809e39..c7cc46d0307375 100644 --- a/soc/nxp/imxrt/imxrt10xx/lpm_rt1064.c +++ b/soc/nxp/imxrt/imxrt10xx/lpm_rt1064.c @@ -117,7 +117,7 @@ static void clock_init_usb1_pll(const clock_usb_pll_config_t *config) static void flexspi_enter_critical(void) { -#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(zephyr_flash))) /* Wait for flexspi to be inactive, and gate the clock */ while (!((FLEXSPI2->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI2->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) { @@ -128,7 +128,7 @@ static void flexspi_enter_critical(void) CCM->CCGR7 &= (~CCM_CCGR7_CG1_MASK); #endif -#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(zephyr_flash))) /* Wait for flexspi to be inactive, and gate the clock */ while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) { @@ -142,7 +142,7 @@ static void flexspi_enter_critical(void) static void flexspi_exit_critical(void) { -#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(zephyr_flash))) /* Enable clock gate of flexspi2. */ CCM->CCGR7 |= (CCM_CCGR7_CG1_MASK); @@ -153,7 +153,7 @@ static void flexspi_exit_critical(void) while (!((FLEXSPI2->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI2->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) { } -#elif DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(flash))) +#elif DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(zephyr_flash))) /* Enable clock of flexspi. */ CCM->CCGR6 |= CCM_CCGR6_CG5_MASK; @@ -211,11 +211,11 @@ void clock_full_power(void) #endif /* Set Flexspi divider before increasing frequency of PLL3 PDF0. */ -#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(zephyr_flash))) clock_set_div(kCLOCK_FlexspiDiv, flexspi_div); clock_set_mux(kCLOCK_FlexspiMux, 3); #endif -#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(zephyr_flash))) clock_set_div(kCLOCK_Flexspi2Div, flexspi_div); clock_set_mux(kCLOCK_Flexspi2Mux, 1); #endif @@ -258,12 +258,12 @@ void clock_low_power(void) CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_ENABLE_MASK; CCM_ANALOG->PFD_480_CLR = CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK; /* Change flexspi to use PLL3 PFD0 with no divisor (24M flexspi clock) */ -#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(zephyr_flash))) clock_set_div(kCLOCK_FlexspiDiv, 0); /* FLEXSPI1 mux to PLL3 PFD0 BYPASS */ clock_set_mux(kCLOCK_FlexspiMux, 3); #endif -#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi2), DT_PARENT(DT_CHOSEN(zephyr_flash))) clock_set_div(kCLOCK_Flexspi2Div, 0); /* FLEXSPI2 mux to PLL3 PFD0 BYPASS */ clock_set_mux(kCLOCK_Flexspi2Mux, 1); diff --git a/soc/nxp/imxrt/imxrt11xx/soc.c b/soc/nxp/imxrt/imxrt11xx/soc.c index 5da3b122e335e2..279a99cc99505b 100644 --- a/soc/nxp/imxrt/imxrt11xx/soc.c +++ b/soc/nxp/imxrt/imxrt11xx/soc.c @@ -527,7 +527,7 @@ static ALWAYS_INLINE void clock_init(void) #endif #endif -#if !(DT_NODE_HAS_COMPAT(DT_CHOSEN(flash), nxp_imx_flexspi)) && \ +#if !(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_flash), nxp_imx_flexspi)) && \ defined(CONFIG_MEMC_MCUX_FLEXSPI) && \ DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay) /* Configure FLEXSPI1 using OSC_RC_48M_DIV2 */ From 67f0d76e70adc65e759d91dba37e5f9abc1afbc2 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0460/1389] drivers: nxp_pit: check if top cb is null check if top cb is null to avoid hard fault top cb is allowed to be null in api so this is required Signed-off-by: Declan Snyder --- drivers/counter/counter_nxp_pit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/counter/counter_nxp_pit.c b/drivers/counter/counter_nxp_pit.c index 5cf192a73c4766..6640b1aa2f2ad1 100644 --- a/drivers/counter/counter_nxp_pit.c +++ b/drivers/counter/counter_nxp_pit.c @@ -187,7 +187,9 @@ static void nxp_pit_isr(const struct device *dev) flags = PIT_GetStatusFlags(config->base, channel); if (flags) { PIT_ClearStatusFlags(config->base, channel, flags); - data->top_callback(dev, data->top_user_data); + if (data->top_callback) { + data->top_callback(dev, data->top_user_data); + } } } #endif /* DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_pit), interrupts) */ From c3c08493b68f004040fc44807e553fedeb5e078d Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0461/1389] drivers: pinctrl: support digital-path-disable for Numaker Add new property digital-path-disable for Nuvoton numaker pinctrl driver. Signed-off-by: cyliang tw --- drivers/pinctrl/pinctrl_numaker.c | 7 +++++-- dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml | 3 +++ soc/nuvoton/numaker/common/pinctrl_soc.h | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl_numaker.c b/drivers/pinctrl/pinctrl_numaker.c index a443f705edf455..e29f214a1833a7 100644 --- a/drivers/pinctrl/pinctrl_numaker.c +++ b/drivers/pinctrl/pinctrl_numaker.c @@ -16,7 +16,9 @@ #define GPIO_SIZE DT_REG_SIZE(DT_NODELABEL(gpioa)) #define SLEWCTL_PIN_SHIFT(pin_idx) ((pin_idx) * 2) -#define SLEWCTL_MASK(pin_idx) (3 << SLEWCTL_PIN_SHIFT(pin_idx)) +#define SLEWCTL_MASK(pin_idx) (3 << SLEWCTL_PIN_SHIFT(pin_idx)) +#define DINOFF_PIN_SHIFT(pin_idx) (pin_idx + GPIO_DINOFF_DINOFF0_Pos) +#define DINOFF_MASK(pin_idx) (1 << DINOFF_PIN_SHIFT(pin_idx)) static void gpio_configure(const pinctrl_soc_pin_t *pin, uint8_t port_idx, uint8_t pin_idx) { @@ -28,7 +30,8 @@ static void gpio_configure(const pinctrl_soc_pin_t *pin, uint8_t port_idx, uint8 ((pin->schmitt_enable ? 1 : 0) << pin_idx); port->SLEWCTL = (port->SLEWCTL & ~SLEWCTL_MASK(pin_idx)) | (pin->slew_rate << SLEWCTL_PIN_SHIFT(pin_idx)); - + port->DINOFF = (port->DINOFF & ~DINOFF_MASK(pin_idx)) | + ((pin->digital_disable ? 1 : 0) << DINOFF_PIN_SHIFT(pin_idx)); } /** * Configure pin multi-function diff --git a/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml b/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml index 4474f9b089faf2..3ff6200ee39193 100644 --- a/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml +++ b/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml @@ -83,3 +83,6 @@ child-binding: Set the speed of a pin. This setting effectively limits the slew rate of the output signal. Hardware default configuration is low. Fast slew rate could support fast speed pins, like as SPI CLK up to 50MHz. + digital-path-disable: + type: boolean + description: disable digital path on a pin. diff --git a/soc/nuvoton/numaker/common/pinctrl_soc.h b/soc/nuvoton/numaker/common/pinctrl_soc.h index 4c12b81c94bc86..53f07b526edb3e 100644 --- a/soc/nuvoton/numaker/common/pinctrl_soc.h +++ b/soc/nuvoton/numaker/common/pinctrl_soc.h @@ -25,6 +25,7 @@ typedef struct pinctrl_soc_pin_t { uint32_t open_drain: 1; uint32_t schmitt_enable: 1; uint32_t slew_rate: 2; + uint32_t digital_disable: 1; } pinctrl_soc_pin_t; #define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ @@ -33,6 +34,7 @@ typedef struct pinctrl_soc_pin_t { .open_drain = DT_PROP(node_id, drive_open_drain), \ .schmitt_enable = DT_PROP(node_id, input_schmitt_enable), \ .slew_rate = DT_ENUM_IDX(node_id, slew_rate), \ + .digital_disable = DT_PROP(node_id, digital_path_disable), \ }, #define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ From ab97d1910128b1f189de6fb8edfdac2d8359cd76 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0462/1389] soc: nxp: imxrt11xx: Enable clock for LPCI2C6 Enable clock for LPCI2C6. This is needed to control some peripherals such as camera sensor. Signed-off-by: Phi Bang Nguyen --- soc/nxp/imxrt/imxrt11xx/soc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/soc/nxp/imxrt/imxrt11xx/soc.c b/soc/nxp/imxrt/imxrt11xx/soc.c index 279a99cc99505b..0a1eecc2cc9210 100644 --- a/soc/nxp/imxrt/imxrt11xx/soc.c +++ b/soc/nxp/imxrt/imxrt11xx/soc.c @@ -398,6 +398,11 @@ static ALWAYS_INLINE void clock_init(void) rootCfg.mux = kCLOCK_LPI2C5_ClockRoot_MuxOscRc48MDiv2; rootCfg.div = 1; CLOCK_SetRootClock(kCLOCK_Root_Lpi2c5, &rootCfg); + + /* Configure Lpi2c6 using Osc24M */ + rootCfg.mux = kCLOCK_LPI2C6_ClockRoot_MuxOsc24MOut; + rootCfg.div = 12; + CLOCK_SetRootClock(kCLOCK_Root_Lpi2c6, &rootCfg); #endif From 939cbafc0b9ca83291fc5fd7a3effe08ea0973ae Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0463/1389] west: linkserver: fix erase error - Fixes linkserver runner "west flash --erase" error: ERRMSG: Exception: Device query can have at most 2 parts (3 found) - There is no need to specify the core with the flash erase command line. Signed-off-by: Andrej Butok --- scripts/west_commands/runners/linkserver.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scripts/west_commands/runners/linkserver.py b/scripts/west_commands/runners/linkserver.py index 1d62840c2e207d..9f15dac313535a 100644 --- a/scripts/west_commands/runners/linkserver.py +++ b/scripts/west_commands/runners/linkserver.py @@ -164,13 +164,8 @@ def do_run(self, command, **kwargs): def do_erase(self, **kwargs): - if self.core is not None: - _cmd_core = ":"+self.core - else: - _cmd_core = "" - linkserver_cmd = ([self.linkserver, "flash"] + ["--probe", str(self.probe)] + - [self.device+_cmd_core] + ["erase"]) + [self.device] + ["erase"]) self.logger.debug("flash erase command = " + str(linkserver_cmd)) self.check_call(linkserver_cmd) From 4a5607138d07ecdadb96f1c6ab094ccb964cfe39 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:38:49 +0200 Subject: [PATCH 0464/1389] test: pwm: add mimxrt1060_evk support for pwm add missing board and overlay support Signed-off-by: Hake Huang --- .../mimxrt1060_evk_mimxrt1062_hyperflash.yaml | 1 + .../nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml | 6 +++--- tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml index 93a7915e6fd9c2..8dbd8533c1c262 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml @@ -25,6 +25,7 @@ supported: - gpio - i2c - netif:eth + - pwm - sdhc - spi - usb_device diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml index 82e15486159187..1cd757e66d5be4 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml @@ -19,17 +19,17 @@ supported: - arduino_i2c - arduino_serial - arduino_spi + - adc + - can - counter - display - dma - gpio - i2c - netif:eth + - pwm - sdhc - spi - usb_device - - dma - - can - watchdog - - adc vendor: nxp diff --git a/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay b/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay index ebd3af9f582a29..ff4a1217720852 100644 --- a/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay +++ b/tests/drivers/pwm/pwm_api/boards/mimxrt1060_evk.overlay @@ -9,6 +9,13 @@ * by the test, but can be tested using the PWM shell. */ +/ { + aliases { + pwm-0 = &flexpwm1_pwm0; + pwm-1 = &flexpwm1_pwm3; + }; +}; + &flexpwm1_pwm3 { status = "okay"; }; From 61c4c96ae8a51ba0cc3956cad2af4d7da1912f7b Mon Sep 17 00:00:00 2001 From: Matthias Alleman Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0465/1389] dts: nxp: rt1060: Fix wrong reg address of enet2 Correction of the reg address of enet2 for nxp_rt1060. Regression introduced at 537d5c310c3e9d22f1df9a6d0bd1e250c84216fb Signed-off-by: Matthias Alleman --- dts/arm/nxp/nxp_rt1060.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/arm/nxp/nxp_rt1060.dtsi b/dts/arm/nxp/nxp_rt1060.dtsi index ccd92ef7e50eff..8d308a27509f44 100644 --- a/dts/arm/nxp/nxp_rt1060.dtsi +++ b/dts/arm/nxp/nxp_rt1060.dtsi @@ -50,7 +50,7 @@ /* i.MX rt1060 has a second Ethernet controller. */ enet2: ethernet@402d4000 { compatible = "nxp,enet"; - reg = <0x402D8000 0x628>; + reg = <0x402d4000 0x628>; clocks = <&ccm IMX_CCM_ENET_CLK 0 0>; enet2_mac: ethernet { compatible = "nxp,enet-mac"; From d283b5ea97d02ae85b5c42d90ae600d513ec24af Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0466/1389] Bluetooth: CAP: Shell: Initiator fix chan_alloc When using the CAP initiator shell AC commands, the channel allocation were not done correctly, leading to cases where we attempted to set e.g. 2 LEFT streams for the same device. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/shell/cap_initiator.c | 163 ++++++++++++------- 1 file changed, 100 insertions(+), 63 deletions(-) diff --git a/subsys/bluetooth/audio/shell/cap_initiator.c b/subsys/bluetooth/audio/shell/cap_initiator.c index ae6e3351e3079b..54d2e7caf53a2c 100644 --- a/subsys/bluetooth/audio/shell/cap_initiator.c +++ b/subsys/bluetooth/audio/shell/cap_initiator.c @@ -623,23 +623,6 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param, snk_stream_cnt++; stream_cnt++; - - /* If we have more than 1 connection or stream in one direction, we set the - * location bit accordingly - */ - if (param->conn_cnt > 1U || param->snk_cnt[i] > 1U) { - const int err = bt_audio_codec_cfg_set_chan_allocation( - stream_param->codec_cfg, (enum bt_audio_location)BIT(i)); - - if (err < 0) { - shell_error(ctx_shell, - "Failed to set channel allocation for " - "snk[%zu][%zu]: %d", - i, j, err); - - return err; - } - } } for (size_t j = 0U; j < param->src_cnt[i]; j++) { @@ -653,31 +636,90 @@ static int cap_ac_unicast_start(const struct bap_unicast_ac_param *param, src_stream_cnt++; stream_cnt++; + } + } - /* If we have more than 1 connection or stream in one direction, we set the - * location bit accordingly - */ - if (param->conn_cnt > 1U || param->src_cnt[i] > 1U) { - const int err = bt_audio_codec_cfg_set_chan_allocation( - stream_param->codec_cfg, (enum bt_audio_location)BIT(i)); + start_param.stream_params = stream_params; + start_param.count = stream_cnt; + start_param.type = BT_CAP_SET_TYPE_AD_HOC; - if (err < 0) { - shell_error(ctx_shell, - "Failed to set channel allocation for " - "src[%zu][%zu]: %d", - i, j, err); + return bt_cap_initiator_unicast_audio_start(&start_param); +} + +static int set_codec_config(const struct shell *sh, struct shell_stream *sh_stream, + struct named_lc3_preset *preset, size_t conn_cnt, size_t ep_cnt, + size_t chan_cnt, size_t conn_index, size_t ep_index) +{ + enum bt_audio_location new_chan_alloc; + enum bt_audio_location chan_alloc; + int err; - return err; + copy_unicast_stream_preset(sh_stream, preset); + + if (chan_cnt == 1U) { + /* - When we have a single channel on a single connection then we make it mono + * - When we have a single channel on a multiple connections then we make it left on + * the first connection and right on the second connection + * - When we have multiple channels streams for a connection, we make them either + * left or right, regardless of the connection count + */ + if (ep_cnt == 1) { + if (conn_cnt == 1) { + new_chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO; + } else if (conn_cnt == 2) { + if (conn_index == 0) { + new_chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT; + } else if (conn_index == 1) { + new_chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT; + } else { + return 0; } + } else { + return 0; } + } else if (ep_cnt == 2) { + if (ep_index == 0) { + new_chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT; + } else if (ep_index == 1) { + new_chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT; + } else { + return 0; + } + } else { + return 0; + } + } else if (chan_cnt == 2U) { + /* Some audio configuration requires multiple sink channels, + * so multiply the SDU based on the channel count + */ + sh_stream->qos.sdu *= chan_cnt; + + /* If a stream has 2 channels, we make it stereo */ + new_chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT; + + } else { + return 0; + } + + err = bt_audio_codec_cfg_get_chan_allocation(&sh_stream->codec_cfg, &chan_alloc); + if (err != 0) { + if (err == -ENODATA) { + chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO; } } - start_param.stream_params = stream_params; - start_param.count = stream_cnt; - start_param.type = BT_CAP_SET_TYPE_AD_HOC; + if (chan_alloc != new_chan_alloc) { + shell_info(sh, + "[%zu][%zu]: Overwriting existing channel allocation 0x%08X with 0x%08X", + conn_index, ep_index, chan_alloc, new_chan_alloc); - return bt_cap_initiator_unicast_audio_start(&start_param); + err = bt_audio_codec_cfg_set_chan_allocation(&sh_stream->codec_cfg, new_chan_alloc); + if (err < 0) { + return err; + } + } + + return 0; } int cap_ac_unicast(const struct shell *sh, const struct bap_unicast_ac_param *param) @@ -735,47 +777,42 @@ int cap_ac_unicast(const struct shell *sh, const struct bap_unicast_ac_param *pa */ for (size_t i = 0U; i < param->conn_cnt; i++) { for (size_t j = 0U; j < param->snk_cnt[i]; j++) { - snk_cnt++; - } + struct shell_stream *snk_uni_stream; - for (size_t j = 0U; j < param->src_cnt[i]; j++) { - src_cnt++; - } - } + snk_uni_stream = snk_uni_streams[snk_cnt] = &unicast_streams[snk_cnt]; - if (!ctx_shell) { - ctx_shell = sh; - } + err = set_codec_config(sh, snk_uni_stream, &default_sink_preset, + param->conn_cnt, param->snk_cnt[i], + param->snk_chan_cnt, i, j); + if (err != 0) { + shell_error(sh, "Failed to set codec configuration: %d", err); - /* Setup arrays of parameters based on the preset for easier access. This also copies the - * preset so that we can modify them (e.g. update the metadata) - */ - for (size_t i = 0U; i < snk_cnt; i++) { - struct shell_stream *snk_uni_stream = snk_uni_streams[i] = &unicast_streams[i]; + return -ENOEXEC; + } - if (snk_uni_stream->stream.bap_stream.conn != NULL) { - shell_error(sh, "unicast_streams[%zu] already in use", i); - return -ENOEXEC; + snk_cnt++; } - copy_unicast_stream_preset(snk_uni_stream, &default_sink_preset); + for (size_t j = 0U; j < param->src_cnt[i]; j++) { + struct shell_stream *src_uni_stream; - /* Some audio configuration requires multiple sink channels, - * so multiply the SDU based on the channel count - */ - snk_uni_stream->qos.sdu *= param->snk_chan_cnt; - } + src_uni_stream = snk_uni_streams[src_cnt] = &unicast_streams[src_cnt]; - for (size_t i = 0U; i < src_cnt; i++) { - struct shell_stream *src_uni_stream = src_uni_streams[i] = - &unicast_streams[i + snk_cnt]; + err = set_codec_config(sh, src_uni_stream, &default_source_preset, + param->conn_cnt, param->src_cnt[i], + param->src_chan_cnt, i, j); + if (err != 0) { + shell_error(sh, "Failed to set codec configuration: %d", err); - if (src_uni_stream->stream.bap_stream.conn != NULL) { - shell_error(sh, "unicast_streams[%zu] already in use", i + snk_cnt); - return -ENOEXEC; + return -ENOEXEC; + } + + src_cnt++; } + } - copy_unicast_stream_preset(src_uni_stream, &default_source_preset); + if (!ctx_shell) { + ctx_shell = sh; } err = bap_ac_create_unicast_group(param, snk_uni_streams, snk_cnt, src_uni_streams, From e2cb2f46e448e8cd5d7c72ea6565530ea77aa780 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0467/1389] modules: mcux: Drop HAS_MCUX_CSI config The HAS_MCUX_CSI (as well as all the HAS_MCUX_XXX) config was obsolete and has been replaced by the DT_HAS_NXP_IMX_CSI_ENABLED (i.e. DT_HAS_XXX_ENABLED). Drop it as well as all the dependencies on it. Signed-off-by: Phi Bang Nguyen --- drivers/video/Kconfig.mcux_csi | 1 - modules/Kconfig.mcux | 5 ----- soc/nxp/imxrt/imxrt10xx/Kconfig | 5 ----- 3 files changed, 11 deletions(-) diff --git a/drivers/video/Kconfig.mcux_csi b/drivers/video/Kconfig.mcux_csi index 18adaab4c50e33..0f1263f041c31a 100644 --- a/drivers/video/Kconfig.mcux_csi +++ b/drivers/video/Kconfig.mcux_csi @@ -6,7 +6,6 @@ config VIDEO_MCUX_CSI bool "NXP MCUX CMOS Sensor Interface (CSI) driver" default y - depends on HAS_MCUX_CSI depends on DT_HAS_NXP_IMX_CSI_ENABLED config VIDEO_MCUX_CSI_INIT_PRIORITY diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 3f20250f58b0a4..0700438661e67e 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -282,11 +282,6 @@ config HAS_MCUX_SMC help Set if the SMC module is present in the SoC. -config HAS_MCUX_CSI - bool - help - Set if the CMOS Sensor Interface module is present in the SoC. - config HAS_MCUX_LPTMR bool help diff --git a/soc/nxp/imxrt/imxrt10xx/Kconfig b/soc/nxp/imxrt/imxrt10xx/Kconfig index 51b894ae304fea..b91fbe0b3ec538 100644 --- a/soc/nxp/imxrt/imxrt10xx/Kconfig +++ b/soc/nxp/imxrt/imxrt10xx/Kconfig @@ -79,7 +79,6 @@ config SOC_MIMXRT1051 select INIT_ARM_PLL select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 - select HAS_MCUX_CSI select HAS_MCUX_FLEXCAN config SOC_MIMXRT1052 @@ -93,7 +92,6 @@ config SOC_MIMXRT1052 select INIT_ENET_PLL if NET_L2_ETHERNET && ETH_DRIVER select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 - select HAS_MCUX_CSI select HAS_MCUX_FLEXCAN select HAS_MCUX_PWM select HAS_MCUX_SRC @@ -107,7 +105,6 @@ config SOC_MIMXRT1061 select INIT_ARM_PLL select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 - select HAS_MCUX_CSI select HAS_MCUX_FLEXCAN config SOC_MIMXRT1062 @@ -124,7 +121,6 @@ config SOC_MIMXRT1062 select INIT_ENET_PLL if NET_L2_ETHERNET && ETH_DRIVER select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 - select HAS_MCUX_CSI select HAS_MCUX_FLEXCAN select HAS_MCUX_I2S select HAS_MCUX_ADC_ETC @@ -146,6 +142,5 @@ config SOC_MIMXRT1064 select INIT_ENET_PLL if NET_L2_ETHERNET && ETH_DRIVER select HAS_MCUX_USDHC1 select HAS_MCUX_USDHC2 - select HAS_MCUX_CSI select HAS_MCUX_FLEXCAN select HAS_SWO From 46bb92b1d57a27d567927a3d72922b2ec961aed0 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0468/1389] drivers: video: csi: Run clang format Run clang format before making any changes Signed-off-by: Phi Bang Nguyen --- drivers/video/video_mcux_csi.c | 61 +++++++++++----------------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index 1e7117c4393e3a..475d18eb1003ee 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -50,8 +50,7 @@ static inline unsigned int video_pix_fmt_bpp(uint32_t pixelformat) } } -static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, - status_t status, void *user_data) +static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, status_t status, void *user_data) { struct video_mcux_csi_data *data = user_data; const struct device *dev = data->dev; @@ -66,8 +65,7 @@ static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, return; } - status = CSI_TransferGetFullBuffer(config->base, &(data->csi_handle), - &buffer_addr); + status = CSI_TransferGetFullBuffer(config->base, &(data->csi_handle), &buffer_addr); if (status != kStatus_Success) { result = VIDEO_BUF_ERROR; goto done; @@ -116,8 +114,7 @@ static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, return; } -static int video_mcux_csi_set_fmt(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_id ep, struct video_format *fmt) { const struct video_mcux_csi_config *config = dev->config; @@ -144,8 +141,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, return -EIO; } - ret = CSI_TransferCreateHandle(config->base, &data->csi_handle, - __frame_done_cb, data); + ret = CSI_TransferCreateHandle(config->base, &data->csi_handle, __frame_done_cb, data); if (ret != kStatus_Success) { return -EIO; } @@ -157,8 +153,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, return 0; } -static int video_mcux_csi_get_fmt(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_id ep, struct video_format *fmt) { struct video_mcux_csi_data *data = dev->data; @@ -173,7 +168,6 @@ static int video_mcux_csi_get_fmt(const struct device *dev, return video_mcux_csi_set_fmt(dev, ep, fmt); } - fmt->pixelformat = data->pixelformat; fmt->height = data->csi_config.height; fmt->width = data->csi_config.width; @@ -218,10 +212,7 @@ static int video_mcux_csi_stream_stop(const struct device *dev) return 0; } - -static int video_mcux_csi_flush(const struct device *dev, - enum video_endpoint_id ep, - bool cancel) +static int video_mcux_csi_flush(const struct device *dev, enum video_endpoint_id ep, bool cancel) { const struct video_mcux_csi_config *config = dev->config; struct video_mcux_csi_data *data = dev->data; @@ -237,16 +228,14 @@ static int video_mcux_csi_flush(const struct device *dev, } else { /* Flush driver output queue */ do { - ret = CSI_TransferGetFullBuffer(config->base, - &(data->csi_handle), + ret = CSI_TransferGetFullBuffer(config->base, &(data->csi_handle), &buffer_addr); } while (ret == kStatus_Success); while ((vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT))) { k_fifo_put(&data->fifo_out, vbuf); if (IS_ENABLED(CONFIG_POLL) && data->signal) { - k_poll_signal_raise(data->signal, - VIDEO_BUF_ABORTED); + k_poll_signal_raise(data->signal, VIDEO_BUF_ABORTED); } } } @@ -254,8 +243,7 @@ static int video_mcux_csi_flush(const struct device *dev, return 0; } -static int video_mcux_csi_enqueue(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_enqueue(const struct device *dev, enum video_endpoint_id ep, struct video_buffer *vbuf) { const struct video_mcux_csi_config *config = dev->config; @@ -281,10 +269,8 @@ static int video_mcux_csi_enqueue(const struct device *dev, return 0; } -static int video_mcux_csi_dequeue(const struct device *dev, - enum video_endpoint_id ep, - struct video_buffer **vbuf, - k_timeout_t timeout) +static int video_mcux_csi_dequeue(const struct device *dev, enum video_endpoint_id ep, + struct video_buffer **vbuf, k_timeout_t timeout) { struct video_mcux_csi_data *data = dev->data; @@ -300,9 +286,7 @@ static int video_mcux_csi_dequeue(const struct device *dev, return 0; } -static inline int video_mcux_csi_set_ctrl(const struct device *dev, - unsigned int cid, - void *value) +static inline int video_mcux_csi_set_ctrl(const struct device *dev, unsigned int cid, void *value) { const struct video_mcux_csi_config *config = dev->config; int ret = -ENOTSUP; @@ -315,9 +299,7 @@ static inline int video_mcux_csi_set_ctrl(const struct device *dev, return ret; } -static inline int video_mcux_csi_get_ctrl(const struct device *dev, - unsigned int cid, - void *value) +static inline int video_mcux_csi_get_ctrl(const struct device *dev, unsigned int cid, void *value) { const struct video_mcux_csi_config *config = dev->config; int ret = -ENOTSUP; @@ -330,8 +312,7 @@ static inline int video_mcux_csi_get_ctrl(const struct device *dev, return ret; } -static int video_mcux_csi_get_caps(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_get_caps(const struct device *dev, enum video_endpoint_id ep, struct video_caps *caps) { const struct video_mcux_csi_config *config = dev->config; @@ -387,8 +368,7 @@ static int video_mcux_csi_init(const struct device *dev) } #ifdef CONFIG_POLL -static int video_mcux_csi_set_signal(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_set_signal(const struct device *dev, enum video_endpoint_id ep, struct k_poll_signal *signal) { struct video_mcux_csi_data *data = dev->data; @@ -434,8 +414,7 @@ static int video_mcux_csi_init_0(const struct device *dev) { struct video_mcux_csi_data *data = dev->data; - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - video_mcux_csi_isr, NULL, 0); + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), video_mcux_csi_isr, NULL, 0); irq_enable(DT_INST_IRQN(0)); @@ -449,9 +428,7 @@ static int video_mcux_csi_init_0(const struct device *dev) * necessary since the clock to the camera is provided by the * CSI peripheral. */ -DEVICE_DT_INST_DEFINE(0, &video_mcux_csi_init_0, - NULL, &video_mcux_csi_data_0, - &video_mcux_csi_config_0, - POST_KERNEL, CONFIG_VIDEO_MCUX_CSI_INIT_PRIORITY, - &video_mcux_csi_driver_api); +DEVICE_DT_INST_DEFINE(0, &video_mcux_csi_init_0, NULL, &video_mcux_csi_data_0, + &video_mcux_csi_config_0, POST_KERNEL, CONFIG_VIDEO_MCUX_CSI_INIT_PRIORITY, + &video_mcux_csi_driver_api); #endif From c599d5727b4dc7af2b79a876f2096cdf34a6a5dc Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0469/1389] drivers: video: csi: Fix get_fmt The CSI should always propagate the get_fmt request down to the sensor. It should not return a format by it own unless it contains a test pattern generator inside it. The problem with the legacy code is that this code snippet is never reached if the sensor could return a format. In case the sensor failed to return a format, these codes are reached but the returned format makes no sense and its value was not initialized. Signed-off-by: Phi Bang Nguyen --- drivers/video/video_mcux_csi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index 475d18eb1003ee..a67d1d2044f628 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -156,7 +156,6 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_ static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_id ep, struct video_format *fmt) { - struct video_mcux_csi_data *data = dev->data; const struct video_mcux_csi_config *config = dev->config; if (fmt == NULL || ep != VIDEO_EP_OUT) { @@ -168,12 +167,7 @@ static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_ return video_mcux_csi_set_fmt(dev, ep, fmt); } - fmt->pixelformat = data->pixelformat; - fmt->height = data->csi_config.height; - fmt->width = data->csi_config.width; - fmt->pitch = data->csi_config.linePitch_Bytes; - - return 0; + return -EIO; } static int video_mcux_csi_stream_start(const struct device *dev) From 4084707b233a484ed36a4816159bffa70dfcb999 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0470/1389] drivers: video: csi: Drop pixel format config The pixel format config is not used in the low level driver. Drop it. Signed-off-by: Phi Bang Nguyen --- drivers/video/video_mcux_csi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index a67d1d2044f628..d267ea7a5ad8f5 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -30,7 +30,6 @@ struct video_mcux_csi_data { csi_handle_t csi_handle; struct k_fifo fifo_in; struct k_fifo fifo_out; - uint32_t pixelformat; struct k_poll_signal *signal; }; @@ -126,7 +125,6 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_ return -EINVAL; } - data->pixelformat = fmt->pixelformat; data->csi_config.bytesPerPixel = bpp; data->csi_config.linePitch_Bytes = fmt->pitch; data->csi_config.polarityFlags = kCSI_HsyncActiveHigh | kCSI_DataLatchOnRisingEdge; From daebf3b9d0587c579c96052550304ebe6756d14e Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0471/1389] Samples: SMF: Add sample for SMF framework This PR adds a sample demonstrating the use of the State Machine Framework (SMF) Instructions are in the README.rst for the sample. Miro Samek was contacted and gave approval to use the state diagram in this demo. Signed-off-by: Glenn Andrews --- samples/subsys/smf/hsm_psicc2/CMakeLists.txt | 12 + samples/subsys/smf/hsm_psicc2/README.rst | 51 +++ samples/subsys/smf/hsm_psicc2/prj.conf | 11 + samples/subsys/smf/hsm_psicc2/sample.yaml | 19 + .../hsm_psicc2/src/hsm_psicc2_console_cmds.c | 91 +++++ .../smf/hsm_psicc2/src/hsm_psicc2_thread.c | 336 ++++++++++++++++++ .../smf/hsm_psicc2/src/hsm_psicc2_thread.h | 52 +++ samples/subsys/smf/hsm_psicc2/src/main.c | 23 ++ samples/subsys/smf/smf.rst | 10 + 9 files changed, 605 insertions(+) create mode 100644 samples/subsys/smf/hsm_psicc2/CMakeLists.txt create mode 100644 samples/subsys/smf/hsm_psicc2/README.rst create mode 100644 samples/subsys/smf/hsm_psicc2/prj.conf create mode 100644 samples/subsys/smf/hsm_psicc2/sample.yaml create mode 100644 samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c create mode 100644 samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c create mode 100644 samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h create mode 100644 samples/subsys/smf/hsm_psicc2/src/main.c create mode 100644 samples/subsys/smf/smf.rst diff --git a/samples/subsys/smf/hsm_psicc2/CMakeLists.txt b/samples/subsys/smf/hsm_psicc2/CMakeLists.txt new file mode 100644 index 00000000000000..86586364114e85 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(smf_hsm_psicc2) + +target_sources(app PRIVATE + src/main.c + src/hsm_psicc2_console_cmds.c + src/hsm_psicc2_thread.c +) diff --git a/samples/subsys/smf/hsm_psicc2/README.rst b/samples/subsys/smf/hsm_psicc2/README.rst new file mode 100644 index 00000000000000..0b79cbb540c2d9 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/README.rst @@ -0,0 +1,51 @@ +.. zephyr:code-sample:: smf_hsm_psicc2 + :name: Hierarchical State Machine Demo based on example from PSiCC2 + :relevant-api: smf + + Implement an event-driven hierarchical state machine using State Machine Framework (SMF). + +Overview +******** + +This sample demonstrates the :ref:`State Machine Framework ` subsystem. + +Building and Running +******************** + +It should be possible to build and run this sample on almost any board or emulator. + +Building and Running for ST Disco L475 IOT01 (B-L475E-IOT01A) +============================================================= +The sample can be built and executed for the :ref:`disco_l475_iot1_board` as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/smf/psicc2 + :board: disco_l475_iot1 + :goals: build flash + :compact: + +For other boards just replace the board name. + +Instructions for Use +==================== +This application implements the statechart shown in Figure 2.11 of +Practical UML Statecharts in C/C++, 2nd Edition, by Miro Samek (PSiCC2). Ebook available from +https://www.state-machine.com/psicc2 This demo was chosen as it contains all possible transition +topologies up to four levels of state nesting and is used with permission of the author. + +For each state, the entry, run, and exit actions are logged to the console, as well as logging +when a state handles an event, or explicitly ignores it and passes it up to the parent state. + +There are two shell commands defined for controlling the operation. + +* ``psicc2 event `` sends the event (from A to I) to the state machine. These correspond to + events A through I in PSiCC2 Figure 2.11 +* ``psicc2 terminate`` sends the ``EVENT_TERMINATE`` event to terminate the state machine. There + is no way to restart the state machine once terminated, and future events are ignored. + +Comparison to PSiCC2 Output +=========================== +Not all transitions modelled in UML may be supported by the :ref:`State Machine Framework `. +Unsupported transitions may lead to results different to the example run of the application in +PSiCC2 Section 2.3.15. The differences will not be listed here as it is hoped :ref:`SMF ` +will support these transitions in the future and the list would become outdated. diff --git a/samples/subsys/smf/hsm_psicc2/prj.conf b/samples/subsys/smf/hsm_psicc2/prj.conf new file mode 100644 index 00000000000000..e2104b03a2762c --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/prj.conf @@ -0,0 +1,11 @@ +CONFIG_LOG=y +CONFIG_SHELL=y + +# Needed for boards that enable RTT backends for logging +# e.g. nrf52840dk/nrf52840 and any others that enable it +CONFIG_LOG_BACKEND_RTT=n + +# Enable the state machine framework +CONFIG_SMF=y +CONFIG_SMF_ANCESTOR_SUPPORT=y +CONFIG_SMF_INITIAL_TRANSITION=y diff --git a/samples/subsys/smf/hsm_psicc2/sample.yaml b/samples/subsys/smf/hsm_psicc2/sample.yaml new file mode 100644 index 00000000000000..ae32b7594af961 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/sample.yaml @@ -0,0 +1,19 @@ +sample: + name: SMF HSM PSiCC2 Demo +common: + tags: + - smf + integration_platforms: + - native_sim + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - ".* hsm_psicc2_thread: initial_entry.*" + - ".* hsm_psicc2_thread: s_entry.*" + - ".* hsm_psicc2_thread: s2_entry.*" + - ".* hsm_psicc2_thread: s21_entry.*" + - ".* hsm_psicc2_thread: s211_entry.*" +tests: + sample.smf.hsm_psicc2: {} diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c new file mode 100644 index 00000000000000..9e5e1ab82b7ecc --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "hsm_psicc2_thread.h" +#include +#include + +static int cmd_hsm_psicc2_event(const struct shell *sh, size_t argc, char **argv) +{ + struct hsm_psicc2_event event; + int event_id = toupper(argv[1][0]); + + switch (event_id) { + case 'A': + event.event_id = EVENT_A; + break; + case 'B': + event.event_id = EVENT_B; + break; + case 'C': + event.event_id = EVENT_C; + break; + case 'D': + event.event_id = EVENT_D; + break; + case 'E': + event.event_id = EVENT_E; + break; + case 'F': + event.event_id = EVENT_F; + break; + case 'G': + event.event_id = EVENT_G; + break; + case 'H': + event.event_id = EVENT_H; + break; + case 'I': + event.event_id = EVENT_I; + break; + default: + shell_error(sh, "Invalid argument %s", argv[1]); + return -1; + } + + int rc = k_msgq_put(&hsm_psicc2_msgq, &event, K_NO_WAIT); + + if (rc == 0) { + shell_print(sh, "Event %c posted", event_id); + } else { + shell_error(sh, "error posting event: %d", rc); + } + return rc; +} + +static int cmd_hsm_psicc2_terminate(const struct shell *sh, size_t argc, char **argv) +{ + struct hsm_psicc2_event event = {.event_id = EVENT_TERMINATE}; + int rc = k_msgq_put(&hsm_psicc2_msgq, &event, K_NO_WAIT); + + if (rc == 0) { + shell_print(sh, "Terminate event posted"); + } else { + shell_error(sh, "error posting terminate event: %d", rc); + } + return rc; +} + +/* Creating subcommands (level 1 command) array for command "demo". */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_hsm_psicc2, + SHELL_CMD_ARG(event, NULL, "Send event to State Machine", + cmd_hsm_psicc2_event, 2, 0), + SHELL_CMD_ARG(terminate, NULL, + "Send terminate event to State Machine", + cmd_hsm_psicc2_terminate, 1, 0), + SHELL_SUBCMD_SET_END); + +/* Creating root (level 0) command "demo" */ +SHELL_CMD_REGISTER(hsm_psicc2, &sub_hsm_psicc2, "PSICC2 demo hierarchical state machine commands", + NULL); diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c new file mode 100644 index 00000000000000..4a1118754d88b7 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2024 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "hsm_psicc2_thread.h" +#include + +LOG_MODULE_REGISTER(hsm_psicc2_thread); + +/* User defined object */ +struct s_object { + /* This must be first */ + struct smf_ctx ctx; + + /* Other state specific data add here */ + struct hsm_psicc2_event event; + int foo; +} s_obj; + +/* Declaration of possible states */ +enum demo_states { + STATE_INITIAL, + STATE_S, + STATE_S1, + STATE_S2, + STATE_S11, + STATE_S21, + STATE_S211, +}; + +/* Forward declaration of state table */ +static const struct smf_state demo_states[]; + +/********* STATE_INITIAL *********/ +static void initial_entry(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + obj->foo = false; +} + +static void initial_run(void *o) +{ + LOG_INF("%s", __func__); +} + +static void initial_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S *********/ +static void s_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_E: + LOG_INF("%s received EVENT_E", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S11]); + break; + case EVENT_I: + if (obj->foo) { + LOG_INF("%s received EVENT_I and set foo false", __func__); + obj->foo = false; + } else { + LOG_INF("%s received EVENT_I and did nothing", __func__); + } + smf_set_handled(SMF_CTX(obj)); + break; + case EVENT_TERMINATE: + LOG_INF("%s received SMF_EVENT_TERMINATE. Terminating", __func__); + smf_set_terminate(SMF_CTX(obj), -1); + } +} + +static void s_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S1 *********/ +static void s1_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s1_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_A: + LOG_INF("%s received EVENT_A", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + break; + case EVENT_B: + LOG_INF("%s received EVENT_B", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S11]); + break; + case EVENT_C: + LOG_INF("%s received EVENT_C", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S2]); + break; + case EVENT_D: + if (!obj->foo) { + LOG_INF("%s received EVENT_D and acted on it", __func__); + obj->foo = true; + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S]); + } else { + LOG_INF("%s received EVENT_D and ignored it", __func__); + } + break; + case EVENT_F: + LOG_INF("%s received EVENT_F", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S211]); + break; + case EVENT_I: + LOG_INF("%s received EVENT_I", __func__); + smf_set_handled(SMF_CTX(obj)); + break; + } +} + +static void s1_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S11 *********/ +static void s11_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s11_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_D: + if (obj->foo) { + LOG_INF("%s received EVENT_D and acted upon it", __func__); + obj->foo = false; + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + } else { + LOG_INF("%s received EVENT_D and ignored it", __func__); + } + break; + case EVENT_G: + LOG_INF("%s received EVENT_G", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S21]); + break; + case EVENT_H: + LOG_INF("%s received EVENT_H", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S]); + break; + } +} + +static void s11_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S2 *********/ +static void s2_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s2_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_C: + LOG_INF("%s received EVENT_C", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + break; + case EVENT_F: + LOG_INF("%s received EVENT_F", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S11]); + break; + case EVENT_I: + if (!obj->foo) { + LOG_INF("%s received EVENT_I and set foo true", __func__); + obj->foo = true; + smf_set_handled(SMF_CTX(obj)); + } else { + LOG_INF("%s received EVENT_I and did nothing", __func__); + } + break; + } +} + +static void s2_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S21 *********/ +static void s21_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s21_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_A: + LOG_INF("%s received EVENT_A", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S21]); + break; + case EVENT_B: + LOG_INF("%s received EVENT_B", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S211]); + break; + case EVENT_G: + LOG_INF("%s received EVENT_G", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + break; + } +} + +static void s21_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S211 *********/ +static void s211_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s211_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_D: + LOG_INF("%s received EVENT_D", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S21]); + break; + case EVENT_H: + LOG_INF("%s received EVENT_H", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S]); + break; + } +} + +static void s211_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/* State storage: handler functions, parent states and initial transition states */ +static const struct smf_state demo_states[] = { + [STATE_INITIAL] = SMF_CREATE_STATE(initial_entry, initial_run, initial_exit, NULL, + &demo_states[STATE_S2]), + [STATE_S] = SMF_CREATE_STATE(s_entry, s_run, s_exit, &demo_states[STATE_INITIAL], + &demo_states[STATE_S11]), + [STATE_S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit, &demo_states[STATE_S], + &demo_states[STATE_S11]), + [STATE_S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit, &demo_states[STATE_S], + &demo_states[STATE_S211]), + [STATE_S11] = SMF_CREATE_STATE(s11_entry, s11_run, s11_exit, &demo_states[STATE_S1], NULL), + [STATE_S21] = SMF_CREATE_STATE(s21_entry, s21_run, s21_exit, &demo_states[STATE_S2], + &demo_states[STATE_S211]), + [STATE_S211] = + SMF_CREATE_STATE(s211_entry, s211_run, s211_exit, &demo_states[STATE_S21], NULL), +}; + +K_THREAD_STACK_DEFINE(hsm_psicc2_thread_stack, HSM_PSICC2_THREAD_STACK_SIZE); +K_MSGQ_DEFINE(hsm_psicc2_msgq, sizeof(struct hsm_psicc2_event), HSM_PSICC2_THREAD_EVENT_QUEUE_SIZE, + 1); + +static struct k_thread hsm_psicc2_thread_data; +static k_tid_t hsm_psicc2_thread_tid; + +static void hsm_psicc2_thread(void *arg1, void *arg2, void *arg3) +{ + smf_set_initial(SMF_CTX(&s_obj), &demo_states[STATE_INITIAL]); + while (1) { + int rc = k_msgq_get(&hsm_psicc2_msgq, &s_obj.event, K_FOREVER); + + if (rc == 0) { + /* Run state machine with given message */ + rc = smf_run_state(SMF_CTX(&s_obj)); + + if (rc) { + /* State machine terminates if a non-zero value is returned */ + LOG_INF("%s terminating state machine thread", __func__); + break; + } + } else { + LOG_ERR("Waiting for event failed, code %d", rc); + } + } +} + +void hsm_psicc2_thread_run(void) +{ + hsm_psicc2_thread_tid = + k_thread_create(&hsm_psicc2_thread_data, hsm_psicc2_thread_stack, + K_THREAD_STACK_SIZEOF(hsm_psicc2_thread_stack), hsm_psicc2_thread, + NULL, NULL, NULL, HSM_PSICC2_THREAD_PRIORITY, 0, K_NO_WAIT); + + k_thread_name_set(hsm_psicc2_thread_tid, "psicc2_thread"); +} diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h new file mode 100644 index 00000000000000..e22588dbd67c64 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _HSM_PSICC2_THREAD_H +#define _HSM_PSICC2_THREAD_H + +#define HSM_PSICC2_THREAD_STACK_SIZE 1024 +#define HSM_PSICC2_THREAD_PRIORITY 7 +#define HSM_PSICC2_THREAD_EVENT_QUEUE_SIZE 10 + +/** + * @brief Event to be sent to an event queue + */ +struct hsm_psicc2_event { + uint32_t event_id; +}; + +/** + * @brief List of events that can be sent to the state machine + */ +enum demo_events { + EVENT_A, + EVENT_B, + EVENT_C, + EVENT_D, + EVENT_E, + EVENT_F, + EVENT_G, + EVENT_H, + EVENT_I, + EVENT_TERMINATE, +}; + +/* event queue to post messages to */ +extern struct k_msgq hsm_psicc2_msgq; + +/** + * @brief Initializes and starts the PSICC2 demo thread + * @param None + */ +void hsm_psicc2_thread_run(void); + +#endif /* _HSM_PSICC2_THREAD_H */ diff --git a/samples/subsys/smf/hsm_psicc2/src/main.c b/samples/subsys/smf/hsm_psicc2/src/main.c new file mode 100644 index 00000000000000..0612e1803427c9 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "hsm_psicc2_thread.h" + +int main(void) +{ + printk("State Machine Framework Demo\n"); + printk("See PSiCC2 Fig 2.11 for the statechart\n"); + printk("https://www.state-machine.com/psicc2\n\n"); + hsm_psicc2_thread_run(); + return 0; +} diff --git a/samples/subsys/smf/smf.rst b/samples/subsys/smf/smf.rst new file mode 100644 index 00000000000000..bc48258b99f8ff --- /dev/null +++ b/samples/subsys/smf/smf.rst @@ -0,0 +1,10 @@ +.. _smf-samples: + +State Machine Framework Samples +############################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* From 669b5f13001b7b0bdd70a486964b36e3ad8e6300 Mon Sep 17 00:00:00 2001 From: Keith Short Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0472/1389] Revert "shell: backends: uart: avoid unnecessary TX IRQs" This reverts commit d2e5eeb51d3364585c2fec13d5f44784e06da53e. PR zephyrproject-rtos/zephyr#71172 is causing the bug reported on issue zephyrproject-rtos/zephyr#72598. Signed-off-by: Keith Short --- subsys/shell/backends/shell_uart.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/subsys/shell/backends/shell_uart.c b/subsys/shell/backends/shell_uart.c index 5384977b614fc1..e80317664b9744 100644 --- a/subsys/shell/backends/shell_uart.c +++ b/subsys/shell/backends/shell_uart.c @@ -166,8 +166,7 @@ static void dtr_timer_handler(struct k_timer *timer) static void uart_tx_handle(const struct device *dev, struct shell_uart_int_driven *sh_uart) { - uint32_t avail; - uint32_t written; + uint32_t len; const uint8_t *data; if (!uart_dtr_check(dev)) { @@ -177,22 +176,16 @@ static void uart_tx_handle(const struct device *dev, struct shell_uart_int_drive return; } - do { - avail = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, - sh_uart->tx_ringbuf.size); - if (avail) { - int err; - - written = uart_fifo_fill(dev, data, avail); - err = ring_buf_get_finish(&sh_uart->tx_ringbuf, written); - __ASSERT_NO_MSG(err == 0); - ARG_UNUSED(err); - } else { - written = 0; - } - } while (avail && written); + len = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, + sh_uart->tx_ringbuf.size); + if (len) { + int err; - if (avail == 0) { + len = uart_fifo_fill(dev, data, len); + err = ring_buf_get_finish(&sh_uart->tx_ringbuf, len); + __ASSERT_NO_MSG(err == 0); + ARG_UNUSED(err); + } else { uart_irq_tx_disable(dev); sh_uart->tx_busy = 0; } From 0050cf554506c470fe93cbc6c201c5c2be43dcdf Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0473/1389] mbedtls: introduce PSA-specific Kconfig file It is meant specifically for configuration of the PSA crypto library. The underlying PSA configuration items are guarded by the condition that a PSA crypto provider must be present, which is the case when either TF-M is in use or MbedTLS's PSA core is built as part of the application image. Signed-off-by: Tomi Fontanilles --- modules/mbedtls/Kconfig.tls-generic | 3 ++- modules/mbedtls/configs/config-tls-generic.h | 11 ++++------- subsys/net/l2/openthread/Kconfig | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 5087213bb27ecf..d377bb46b8d1d9 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -494,8 +494,9 @@ config MBEDTLS_USE_PSA_CRYPTO config MBEDTLS_LMS bool "Support LMS signature schemes" - depends on MBEDTLS_PSA_CRYPTO_C + depends on MBEDTLS_PSA_CRYPTO_CLIENT depends on MBEDTLS_HASH_SHA256_ENABLED + select PSA_WANT_ALG_SHA_256 config MBEDTLS_SSL_DTLS_CONNECTION_ID bool "DTLS Connection ID extension" diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 92ab1f66edb76c..6a731d4f61ac7b 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -35,7 +35,6 @@ #if defined(CONFIG_MBEDTLS_LMS) #define MBEDTLS_LMS_C -#define PSA_WANT_ALG_SHA_256 1 #endif #if defined(CONFIG_MBEDTLS_HAVE_TIME_DATE) @@ -486,6 +485,10 @@ #define MBEDTLS_FS_IO #endif +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_C */ + +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) +#define MBEDTLS_PSA_CRYPTO_CLIENT #endif #if defined(CONFIG_MBEDTLS_TLS_VERSION_1_2) && defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) @@ -496,18 +499,12 @@ #define MBEDTLS_SSL_DTLS_CONNECTION_ID #endif -/* User config file */ - #if defined(CONFIG_MBEDTLS_USER_CONFIG_FILE) #include CONFIG_MBEDTLS_USER_CONFIG_FILE #endif #if defined(CONFIG_BUILD_WITH_TFM) #undef MBEDTLS_PSA_CRYPTO_C -#endif /* CONFIG_BUILD_WITH_TFM */ - -#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) -#define MBEDTLS_PSA_CRYPTO_CLIENT #endif #if defined(CONFIG_PSA_WANT_ALG_SHA_256) diff --git a/subsys/net/l2/openthread/Kconfig b/subsys/net/l2/openthread/Kconfig index 9673aa7702a083..c75af2c5c255d0 100644 --- a/subsys/net/l2/openthread/Kconfig +++ b/subsys/net/l2/openthread/Kconfig @@ -322,7 +322,7 @@ config OPENTHREAD_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE config OPENTHREAD_CRYPTO_PSA bool "ARM PSA crypto API" - depends on MBEDTLS_PSA_CRYPTO_C || BUILD_WITH_TFM + depends on MBEDTLS_PSA_CRYPTO_CLIENT select OPENTHREAD_PLATFORM_KEY_REF if !OPENTHREAD_COPROCESSOR_RCP imply OPENTHREAD_PLATFORM_KEYS_EXPORTABLE_ENABLE help From eda4b54754666ea044ac6bcbc4d5fdcbb0b41a69 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0474/1389] mgmt: mcumgr: replace Tinycrypt by PSA As part of ongoing work to move away from TinyCrypt and towards PSA (#43712), make fs_mgmt use either PSA (when available) or MbedTLS (as a fallback) for SHA-256. The use of PSA is guarded by CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT which requires a locally-built PSA core for devices without TF-M. Signed-off-by: Tomi Fontanilles --- doc/releases/migration-guide-3.7.rst | 6 + subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig | 3 +- .../src/fs_mgmt_hash_checksum_sha256.c | 147 +++++++++--------- tests/subsys/mgmt/mcumgr/all_options/prj.conf | 4 +- .../configuration/all.conf | 4 +- .../configuration/sha256.conf | 5 +- 6 files changed, 85 insertions(+), 84 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 07d2585fa1687b..19f272214045a8 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -370,6 +370,12 @@ LoRaWAN MCUmgr ====== +* The support for SHA-256 (when using checksum/hash functions), previously provided + by either TinyCrypt or MbedTLS, is now provided by either PSA or MbedTLS. + PSA is the recommended API going forward, however, if it is not already enabled + (:kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT`) and you have tight code size + constraints, you may be able to save 1.3 KB by using MbedTLS instead. + Modem ===== diff --git a/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig index 95e8a1c2658720..2bb7e74fb63099 100644 --- a/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig @@ -125,7 +125,8 @@ config MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32 config MCUMGR_GRP_FS_HASH_SHA256 bool "SHA256 hash support" - depends on TINYCRYPT_SHA256 || MBEDTLS_MAC_SHA256_ENABLED + depends on BUILD_WITH_TFM || MBEDTLS_MAC_SHA256_ENABLED + select PSA_WANT_ALG_SHA_256 if BUILD_WITH_TFM help Enable SHA256 hash support for MCUmgr. diff --git a/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt_hash_checksum_sha256.c b/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt_hash_checksum_sha256.c index 118dc93f9edb83..5005067f38c16a 100644 --- a/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt_hash_checksum_sha256.c +++ b/subsys/mgmt/mcumgr/grp/fs_mgmt/src/fs_mgmt_hash_checksum_sha256.c @@ -13,89 +13,41 @@ #include #include -#if defined(CONFIG_TINYCRYPT_SHA256) -#include -#include +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT +#include +typedef psa_hash_operation_t hash_ctx_t; +#define SUCCESS_VALUE PSA_SUCCESS + #else -#include #include -#endif - -#define SHA256_DIGEST_SIZE 32 - -#if defined(CONFIG_TINYCRYPT_SHA256) -/* Tinycrypt SHA256 implementation */ -static int fs_mgmt_hash_checksum_sha256(struct fs_file_t *file, uint8_t *output, - size_t *out_len, size_t len) -{ - int rc = 0; - ssize_t bytes_read = 0; - size_t read_size = CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE; - uint8_t buffer[CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE]; - struct tc_sha256_state_struct sha; - - /* Clear variables prior to calculation */ - *out_len = 0; - memset(output, 0, SHA256_DIGEST_SIZE); - - if (tc_sha256_init(&sha) != TC_CRYPTO_SUCCESS) { - return MGMT_ERR_EUNKNOWN; - } +typedef mbedtls_sha256_context hash_ctx_t; +#define SUCCESS_VALUE 0 - /* Read all data from file and add to SHA256 hash calculation */ - do { - if ((read_size + *out_len) >= len) { - /* Limit read size to size of requested data */ - read_size = len - *out_len; - } - - bytes_read = fs_read(file, buffer, read_size); +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */ - if (bytes_read < 0) { - /* Failed to read file data, pass generic unknown error back */ - return MGMT_ERR_EUNKNOWN; - } else if (bytes_read > 0) { - if (tc_sha256_update(&sha, buffer, bytes_read) != TC_CRYPTO_SUCCESS) { - return MGMT_ERR_EUNKNOWN; - } +#define SHA256_DIGEST_SIZE 32 - *out_len += bytes_read; - } - } while (bytes_read > 0 && *out_len < len); +/* The API that the different hash implementations provide further down. */ +static int hash_setup(hash_ctx_t *); +static int hash_update(hash_ctx_t *, const uint8_t *input, size_t ilen); +static int hash_finish(hash_ctx_t *, uint8_t *output); +static void hash_teardown(hash_ctx_t *); - /* Finalise SHA256 hash calculation and store output in provided output buffer */ - if (tc_sha256_final(output, &sha) != TC_CRYPTO_SUCCESS) { - rc = MGMT_ERR_EUNKNOWN; - } - - return rc; -} -#else -/* mbedtls SHA256 implementation */ static int fs_mgmt_hash_checksum_sha256(struct fs_file_t *file, uint8_t *output, size_t *out_len, size_t len) { - int rc = 0; + int rc = MGMT_ERR_EUNKNOWN; ssize_t bytes_read = 0; size_t read_size = CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE; uint8_t buffer[CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE]; - mbedtls_md_context_t mbed_hash_ctx; - const mbedtls_md_info_t *mbed_hash_info; + hash_ctx_t hash_ctx; /* Clear variables prior to calculation */ *out_len = 0; memset(output, 0, SHA256_DIGEST_SIZE); - mbed_hash_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - mbedtls_md_init(&mbed_hash_ctx); - - if (mbedtls_md_setup(&mbed_hash_ctx, mbed_hash_info, 0) != 0) { - return MGMT_ERR_EUNKNOWN; - } - - if (mbedtls_md_starts(&mbed_hash_ctx)) { - rc = MGMT_ERR_EUNKNOWN; - goto error; + if (hash_setup(&hash_ctx) != SUCCESS_VALUE) { + goto teardown; } /* Read all data from file and add to SHA256 hash calculation */ @@ -108,13 +60,11 @@ static int fs_mgmt_hash_checksum_sha256(struct fs_file_t *file, uint8_t *output, bytes_read = fs_read(file, buffer, read_size); if (bytes_read < 0) { - /* Failed to read file data, pass generic unknown error back */ - rc = MGMT_ERR_EUNKNOWN; - goto error; + /* Failed to read file data */ + goto teardown; } else if (bytes_read > 0) { - if (mbedtls_md_update(&mbed_hash_ctx, buffer, bytes_read) != 0) { - rc = MGMT_ERR_EUNKNOWN; - goto error; + if (hash_update(&hash_ctx, buffer, bytes_read) != SUCCESS_VALUE) { + goto teardown; } *out_len += bytes_read; @@ -122,16 +72,15 @@ static int fs_mgmt_hash_checksum_sha256(struct fs_file_t *file, uint8_t *output, } while (bytes_read > 0 && *out_len < len); /* Finalise SHA256 hash calculation and store output in provided output buffer */ - if (mbedtls_md_finish(&mbed_hash_ctx, output) != 0) { - rc = MGMT_ERR_EUNKNOWN; + if (hash_finish(&hash_ctx, output) == SUCCESS_VALUE) { + rc = 0; } -error: - mbedtls_md_free(&mbed_hash_ctx); +teardown: + hash_teardown(&hash_ctx); return rc; } -#endif static struct fs_mgmt_hash_checksum_group sha256 = { .group_name = "sha256", @@ -149,3 +98,47 @@ void fs_mgmt_hash_checksum_unregister_sha256(void) { fs_mgmt_hash_checksum_unregister_group(&sha256); } + +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT + +static int hash_setup(psa_hash_operation_t *ctx) +{ + *ctx = psa_hash_operation_init(); + return psa_hash_setup(ctx, PSA_ALG_SHA_256); +} +static int hash_update(psa_hash_operation_t *ctx, const uint8_t *input, size_t ilen) +{ + return psa_hash_update(ctx, input, ilen); +} +static int hash_finish(psa_hash_operation_t *ctx, uint8_t *output) +{ + size_t output_length; + + return psa_hash_finish(ctx, output, SHA256_DIGEST_SIZE, &output_length); +} +static void hash_teardown(psa_hash_operation_t *ctx) +{ + psa_hash_abort(ctx); +} + +#else + +static int hash_setup(mbedtls_sha256_context *ctx) +{ + mbedtls_sha256_init(ctx); + return mbedtls_sha256_starts(ctx, false); +} +static int hash_update(mbedtls_sha256_context *ctx, const uint8_t *input, size_t ilen) +{ + return mbedtls_sha256_update(ctx, input, ilen); +} +static int hash_finish(mbedtls_sha256_context *ctx, uint8_t *output) +{ + return mbedtls_sha256_finish(ctx, output); +} +static void hash_teardown(mbedtls_sha256_context *ctx) +{ + mbedtls_sha256_free(ctx); +} + +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */ diff --git a/tests/subsys/mgmt/mcumgr/all_options/prj.conf b/tests/subsys/mgmt/mcumgr/all_options/prj.conf index 42ce2e03c86e39..ed584f347629c8 100644 --- a/tests/subsys/mgmt/mcumgr/all_options/prj.conf +++ b/tests/subsys/mgmt/mcumgr/all_options/prj.conf @@ -4,8 +4,8 @@ # SPDX-License-Identifier: Apache-2.0 # CONFIG_ZTEST=y -CONFIG_TINYCRYPT=y -CONFIG_TINYCRYPT_SHA256=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y CONFIG_FILE_SYSTEM=y CONFIG_BASE64=y CONFIG_NET_BUF=y diff --git a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/all.conf b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/all.conf index 546b7f6128eae2..53b017ba80a966 100644 --- a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/all.conf +++ b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/all.conf @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: Apache-2.0 # -CONFIG_TINYCRYPT=y -CONFIG_TINYCRYPT_SHA256=y CONFIG_MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32=y CONFIG_MCUMGR_GRP_FS_HASH_SHA256=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y diff --git a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/sha256.conf b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/sha256.conf index d8f44a443a1b05..bf9bb9763c24af 100644 --- a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/sha256.conf +++ b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/configuration/sha256.conf @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: Apache-2.0 # -CONFIG_TINYCRYPT=y -CONFIG_TINYCRYPT_SHA256=y +CONFIG_MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32=n CONFIG_MCUMGR_GRP_FS_HASH_SHA256=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y From 43b750ca8956d7d7256f68b28d0998c7124ad28f Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0475/1389] tests: mgmt: mcumgr: fs_mgmt_hash_supported: make CI green Exclude some more platforms from the tests. They provoke devicetree-related build errors which weren't introduced by the changes in this PR (#71947). Signed-off-by: Tomi Fontanilles --- .../mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml index 4f07ecf0211d1b..fd0da3fd04799c 100644 --- a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml +++ b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml @@ -20,6 +20,9 @@ tests: - lpcxpresso51u68 - nucleo_h745zi_q/stm32h745xx/m4 - stm32h747i_disco/stm32h747xx/m4 + - lpcxpresso55s69/lpc55s69/cpu1 + - mpfs_icicle + - apollo4p_evb mgmt.mcumgr.fs.mgmt.hash.supported.sha256: extra_args: > OVERLAY_CONFIG="configuration/sha256.conf" @@ -29,6 +32,9 @@ tests: - lpcxpresso51u68 - nucleo_h745zi_q/stm32h745xx/m4 - stm32h747i_disco/stm32h747xx/m4 + - lpcxpresso55s69/lpc55s69/cpu1 + - mpfs_icicle + - apollo4p_evb mgmt.mcumgr.fs.mgmt.hash.supported.all: extra_args: > OVERLAY_CONFIG="configuration/all.conf" @@ -38,3 +44,6 @@ tests: - lpcxpresso51u68 - nucleo_h745zi_q/stm32h745xx/m4 - stm32h747i_disco/stm32h747xx/m4 + - lpcxpresso55s69/lpc55s69/cpu1 + - mpfs_icicle + - apollo4p_evb From be89838e3cbb12f83a03ed08062f636e610e8f58 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0476/1389] drivers: serial: mcux lpuart add (tx/rx)invert and single wire Adds device tree definitions to enable tx/rx invert and singlewire modes Signed-off-by: Peter van der Perk --- drivers/serial/uart_mcux_lpuart.c | 31 +++++++++++++++++++++ dts/bindings/serial/nxp,kinetis-lpuart.yaml | 20 +++++++++++++ 2 files changed, 51 insertions(+) diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index ea6b82ebc0e20f..a3a46039bfc993 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -58,6 +58,9 @@ struct mcux_lpuart_config { uint8_t parity; bool rs485_de_active_low; bool loopback_en; + bool single_wire; + bool tx_invert; + bool rx_invert; #ifdef CONFIG_UART_MCUX_LPUART_ISR_SUPPORT void (*irq_config_func)(const struct device *dev); #endif @@ -1105,8 +1108,30 @@ static int mcux_lpuart_configure_init(const struct device *dev, const struct uar /* Set the LPUART into loopback mode */ config->base->CTRL |= LPUART_CTRL_LOOPS_MASK; config->base->CTRL &= ~LPUART_CTRL_RSRC_MASK; + } else if (config->single_wire) { + /* Enable the single wire / half-duplex mode, only possible when + * loopback is disabled. We need a critical section to prevent + * the UART firing an interrupt during mode switch + */ + unsigned int key = irq_lock(); + + config->base->CTRL |= (LPUART_CTRL_LOOPS_MASK | LPUART_CTRL_RSRC_MASK); + irq_unlock(key); + } else { +#ifdef LPUART_CTRL_TXINV + /* Only invert TX in full-duplex mode */ + if (config->tx_invert) { + config->base->CTRL |= LPUART_CTRL_TXINV(1); + } +#endif } +#ifdef LPUART_STAT_RXINV + if (config->rx_invert) { + config->base->STAT |= LPUART_STAT_RXINV(1); + } +#endif + /* update internal uart_config */ data->uart_config = *cfg; @@ -1126,6 +1151,9 @@ static int mcux_lpuart_configure(const struct device *dev, { const struct mcux_lpuart_config *config = dev->config; + /* Make sure that RSRC is de-asserted otherwise deinit will hang. */ + config->base->CTRL &= ~LPUART_CTRL_RSRC_MASK; + /* disable LPUART */ LPUART_Deinit(config->base); @@ -1330,6 +1358,9 @@ static const struct mcux_lpuart_config mcux_lpuart_##n##_config = { \ .parity = DT_INST_ENUM_IDX_OR(n, parity, UART_CFG_PARITY_NONE), \ .rs485_de_active_low = DT_INST_PROP(n, nxp_rs485_de_active_low), \ .loopback_en = DT_INST_PROP(n, nxp_loopback), \ + .single_wire = DT_INST_PROP(n, single_wire), \ + .rx_invert = DT_INST_PROP(n, rx_invert), \ + .tx_invert = DT_INST_PROP(n, tx_invert), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ MCUX_LPUART_IRQ_INIT(n) \ RX_DMA_CONFIG(n) \ diff --git a/dts/bindings/serial/nxp,kinetis-lpuart.yaml b/dts/bindings/serial/nxp,kinetis-lpuart.yaml index 1b8f540072253e..4e06853323b660 100644 --- a/dts/bindings/serial/nxp,kinetis-lpuart.yaml +++ b/dts/bindings/serial/nxp,kinetis-lpuart.yaml @@ -15,6 +15,26 @@ properties: disconnected, and transmitter output is internally connected to the receiver input. + single-wire: + type: boolean + description: | + Enable the single wire half-duplex communication. + Using this mode, TX and RX lines are internally connected and + only TX pin is used afterwards and should be configured. + RX/TX conflicts must be handled on user side. + + tx-invert: + type: boolean + description: | + Invert the binary logic of tx pin. When enabled, physical logic levels are inverted and + we use 1=Low, 0=High instead of 1=High, 0=Low. + + rx-invert: + type: boolean + description: | + Invert the binary logic of rx pin. When enabled, physical logic levels are inverted and + we use 1=Low, 0=High instead of 1=High, 0=Low. + nxp,rs485-mode: type: boolean description: | From 40bf70169162c4165441ef7442eaec67b4b8e225 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0477/1389] doc/kernel/drivers: Mention deferred initialization Add a section discussing device deferred initialization on the device model documentation. Signed-off-by: Ederson de Souza --- doc/kernel/drivers/index.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/kernel/drivers/index.rst b/doc/kernel/drivers/index.rst index 51b31de006f72c..fcc2e6676501f6 100644 --- a/doc/kernel/drivers/index.rst +++ b/doc/kernel/drivers/index.rst @@ -373,6 +373,24 @@ Drivers and other system utilities can determine whether startup is still in pre-kernel states by using the :c:func:`k_is_pre_kernel` function. +Deferred initialization +*********************** + +Initialization of devices can also be deferred to a later time. In this case, +the device is not automatically initialized by Zephyr at boot time. Instead, +the device is initialized when the application calls :c:func:`device_init`. +To defer a device driver initialization, add the property ``zephyr,deferred-init`` +to the associated device node in the DTS file. For example: + +.. code-block:: devicetree + + / { + a-driver@40000000 { + reg = <0x40000000 0x1000>; + zephyr,deferred-init; + }; + }; + System Drivers ************** From 1a78ac47861640b47512cbb18d93d8f4c8608e17 Mon Sep 17 00:00:00 2001 From: Dino Li Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0478/1389] espi/it8xxx2: enable EC to accept port 81 cycle This allows EC to accept 2 bytes of port 80 data written from the Host. Signed-off-by: Dino Li --- drivers/espi/Kconfig.it8xxx2 | 15 +++++++++++++++ drivers/espi/espi_it8xxx2.c | 15 ++++++++++++--- soc/ite/ec/common/chip_chipregs.h | 2 ++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/espi/Kconfig.it8xxx2 b/drivers/espi/Kconfig.it8xxx2 index e018f869515714..6c19eb2514c1e9 100644 --- a/drivers/espi/Kconfig.it8xxx2 +++ b/drivers/espi/Kconfig.it8xxx2 @@ -127,4 +127,19 @@ config ESPI_IT8XXX2_PNPCFG_DEVICE_KBC_MOUSE With this option enabled, EC will send IRQ12 signal to host when the KBC mouse output buffer is full. +# On IT8xxx2 series, this configuration option has limitation: +# Port 80 and 81 I/O cycles share the same interrupt source and there is no +# status bit to indicate which cycle triggered the interrupt and data registers +# of these two ports are read only. Hence EC have to read these two data +# registers at the same time in the ISR. +# It means that the Host must alwasy write 2 bytes of data to port 80 otherwise +# port 81 data will not be updated. +config ESPI_IT8XXX2_PORT_81_CYCLE + bool "EC accepts 0x81 I/O cycle from eSPI transaction" + depends on ESPI_PERIPHERAL_DEBUG_PORT_80 + help + With this option enabled, EC will accept 0x81 I/O cycle from the Host. + This allows EC to accept 2 bytes of port 80 data written from the Host. + (e.g. using iotools: iotools io_write16 0x80 0x1234) + endif #ESPI_IT8XXX2 diff --git a/drivers/espi/espi_it8xxx2.c b/drivers/espi/espi_it8xxx2.c index bd0d83c02103ef..f0510c7f1f5865 100644 --- a/drivers/espi/espi_it8xxx2.c +++ b/drivers/espi/espi_it8xxx2.c @@ -517,7 +517,11 @@ static void port80_it8xxx2_isr(const struct device *dev) ESPI_PERIPHERAL_NODATA }; - evt.evt_data = gctrl->GCTRL_P80HDR; + if (IS_ENABLED(CONFIG_ESPI_IT8XXX2_PORT_81_CYCLE)) { + evt.evt_data = gctrl->GCTRL_P80HDR | (gctrl->GCTRL_P81HDR << 8); + } else { + evt.evt_data = gctrl->GCTRL_P80HDR; + } /* Write 1 to clear this bit */ gctrl->GCTRL_P80H81HSR |= BIT(0); @@ -529,8 +533,13 @@ static void port80_it8xxx2_init(const struct device *dev) ARG_UNUSED(dev); struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE; - /* Accept Port 80h Cycle */ - gctrl->GCTRL_SPCTRL1 |= IT8XXX2_GCTRL_ACP80; + /* Accept Port 80h (and 81h) Cycle */ + if (IS_ENABLED(CONFIG_ESPI_IT8XXX2_PORT_81_CYCLE)) { + gctrl->GCTRL_SPCTRL1 |= + (IT8XXX2_GCTRL_ACP80 | IT8XXX2_GCTRL_ACP81); + } else { + gctrl->GCTRL_SPCTRL1 |= IT8XXX2_GCTRL_ACP80; + } IRQ_CONNECT(IT8XXX2_PORT_80_IRQ, 0, port80_it8xxx2_isr, DEVICE_DT_INST_GET(0), 0); irq_enable(IT8XXX2_PORT_80_IRQ); diff --git a/soc/ite/ec/common/chip_chipregs.h b/soc/ite/ec/common/chip_chipregs.h index 71176c366d6f87..c585271542eab3 100644 --- a/soc/ite/ec/common/chip_chipregs.h +++ b/soc/ite/ec/common/chip_chipregs.h @@ -1661,6 +1661,8 @@ struct gctrl_it8xxx2_regs { #define IT8XXX2_GCTRL_ILM0_ENABLE BIT(0) /* Accept Port 80h Cycle */ #define IT8XXX2_GCTRL_ACP80 BIT(6) +/* Accept Port 81h Cycle */ +#define IT8XXX2_GCTRL_ACP81 BIT(3) /* USB Debug Enable */ #define IT8XXX2_GCTRL_MCCR_USB_EN BIT(7) /* USB Pad Power-On Enable */ From 94e3caa04f1713edb1198588f299d5af1fea386c Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0479/1389] twister: allow using west-flash with 'erase' Using `erase` with west-flash was blocked as it was messing with sysbuild. With #69748 the issue is fixed, hence 'erase' is no longer blocked. Remove obsolete twister test Signed-off-by: Maciej Perkowski --- scripts/pylib/twister/twisterlib/runner.py | 8 +------- scripts/tests/twister/test_runner.py | 16 +--------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 3073a7c4ca6fb9..25037eb2632452 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -501,17 +501,11 @@ def parse_generated(self, filter_stages=[]): if self.testsuite.sysbuild and self.env.options.device_testing: # Verify that twister's arguments support sysbuild. # Twister sysbuild flashing currently only works with west, so - # --west-flash must be passed. Additionally, erasing the DUT - # before each test with --west-flash=--erase will inherently not - # work with sysbuild. + # --west-flash must be passed. if self.env.options.west_flash is None: logger.warning("Sysbuild test will be skipped. " + "West must be used for flashing.") return {os.path.join(self.platform.name, self.testsuite.name): True} - elif "--erase" in self.env.options.west_flash: - logger.warning("Sysbuild test will be skipped, " + - "--erase is not supported with --west-flash") - return {os.path.join(self.platform.name, self.testsuite.name): True} if self.testsuite and self.testsuite.filter: try: diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index e2a51fc2a09d1a..592d2c63042086 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -554,20 +554,6 @@ def mock_popen(*args, **kwargs): ['Sysbuild test will be skipped. West must be used for flashing.'], {os.path.join('other', 'dummy.testsuite.name'): True} ), - ( - 'other', ['other'], True, - False, ['--erase'], True, - 'Dummy parse results', True, - None, - None, - {}, - {}, - None, - b'dummy edt pickle contents', - ['Sysbuild test will be skipped,' \ - ' --erase is not supported with --west-flash'], - {os.path.join('other', 'dummy.testsuite.name'): True} - ), ( 'other', ['other'], False, True, None, False, @@ -651,7 +637,7 @@ def mock_popen(*args, **kwargs): ' expected_logs, expected_return', TESTDATA_3, ids=['unit testing', 'domain', 'kconfig', 'no cache', - 'no west options', 'erase west flash option', 'no edt', + 'no west options', 'no edt', 'parse result', 'no parse result', 'no testsuite filter', 'parse err'] ) def test_filterbuilder_parse_generated( From 3429cfbdcf8b68a90780a8e8caaf8aadff38d51f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0480/1389] lorawan: make possible to send empty frames Empty frames are allowed by the LoRaWAN protocol and are actually useful to open new RX slots or flush MAC commands in stack. Therefore allow the data pointer to be NULL if len is 0. Signed-off-by: Aurelien Jarno --- subsys/lorawan/lorawan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/lorawan/lorawan.c b/subsys/lorawan/lorawan.c index 2213c0dccf409e..b37f24a7cddf25 100644 --- a/subsys/lorawan/lorawan.c +++ b/subsys/lorawan/lorawan.c @@ -595,7 +595,7 @@ int lorawan_send(uint8_t port, uint8_t *data, uint8_t len, int ret = 0; bool empty_frame = false; - if (data == NULL) { + if (data == NULL && len > 0) { return -EINVAL; } From a410899a8006ca341aff03f8af674b9efc61aa50 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0481/1389] samples: drivers: crypto: Align error message 'But got:' should be vertically aligned with the message 'Was waiting for:'. Signed-off-by: Reto Schneider --- samples/drivers/crypto/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/drivers/crypto/src/main.c b/samples/drivers/crypto/src/main.c index 38205ef5df6191..76481eb69adb55 100644 --- a/samples/drivers/crypto/src/main.c +++ b/samples/drivers/crypto/src/main.c @@ -65,7 +65,7 @@ static void print_buffer_comparison(const uint8_t *wanted_result, } } - printk("\n But got:\n"); + printk("\nBut got:\n"); for (i = 0, j = 1; i < length; i++, j++) { printk("0x%02x ", result[i]); From 1424fcddab0b30b99cda366c303ecc2475d785a0 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0482/1389] net: capture: fix doxygen parameter names Fix parameter names in the doxygen comment to fix warnings when building the docs. Signed-off-by: Jordan Yates --- include/zephyr/net/capture.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zephyr/net/capture.h b/include/zephyr/net/capture.h index 0d5a61c49113cd..0a90e444f728ee 100644 --- a/include/zephyr/net/capture.h +++ b/include/zephyr/net/capture.h @@ -271,7 +271,7 @@ struct net_capture_cooked { /** * @brief Initialize cooked mode capture context. * - * @param cooked Cooked context struct allocated by user. + * @param ctx Cooked context struct allocated by user. * @param hatype Link-layer address type * @param halen Link-layer address length (maximum is 8 bytes) * @param addr Link-layer address @@ -307,7 +307,7 @@ static inline int net_capture_cooked_setup(struct net_capture_cooked *ctx, * layer packets so that packet boundary is not lost. * * @param ctx Cooked mode capture context. - * @param buf Data to capture. + * @param data Data to capture. * @param len Length of the data. * @param type The direction and type of the packet (did we sent it etc). * @param ptype Protocol type id. These are the ETH_P_* types set in ethernet.h From 1bcefe3d44dcc8545f74ddab13e1163ebb65aee1 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:38:50 +0200 Subject: [PATCH 0483/1389] tests: test_mcuboot: update test pattern for upgrade mode NXP LPC series flash only supoort upgrade mode, so change the pattern to match this mode Signed-off-by: Hake Huang --- tests/boot/test_mcuboot/testcase.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/boot/test_mcuboot/testcase.yaml b/tests/boot/test_mcuboot/testcase.yaml index 3514983420987f..abb1d3a44b13dc 100644 --- a/tests/boot/test_mcuboot/testcase.yaml +++ b/tests/boot/test_mcuboot/testcase.yaml @@ -7,7 +7,7 @@ common: - "I: Starting bootloader" - "Launching primary slot application on (.*)" - "Secondary application ready for swap, rebooting" - - "I: Starting swap using (.*)" + - "I: Starting swap using (.*)|I: Image 0 upgrade secondary slot -> primary slot" - "Swapped application booted on (.*)" tests: bootloader.mcuboot: From 38fb14f3b9118cb6b5ecd5443d6e8c8d53762193 Mon Sep 17 00:00:00 2001 From: Michael Stumpf Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0484/1389] Fixes small typo in log_backend_fs.c Signed-off-by: Michael Stumpf --- subsys/logging/backends/log_backend_fs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/logging/backends/log_backend_fs.c b/subsys/logging/backends/log_backend_fs.c index f12ba05addaf3e..845b03d15187d2 100644 --- a/subsys/logging/backends/log_backend_fs.c +++ b/subsys/logging/backends/log_backend_fs.c @@ -35,7 +35,7 @@ static int get_log_file_id(struct fs_dirent *ent); static uint32_t log_format_current = CONFIG_LOG_BACKEND_FS_OUTPUT_DEFAULT; #endif -static int check_log_volumen_available(void) +static int check_log_volume_available(void) { int index = 0; char const *name; @@ -152,7 +152,7 @@ int write_log_to_file(uint8_t *data, size_t length, void *ctx) struct fs_file_t *f = &fs_file; if (backend_state == BACKEND_FS_NOT_INITIALIZED) { - if (check_log_volumen_available()) { + if (check_log_volume_available()) { return length; } rc = create_log_dir(CONFIG_LOG_BACKEND_FS_DIR); From a3120b0cc5df5bed8f1d49bfcdc40a16131e2314 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0485/1389] doc: releases: add MbedTLS-related notes For changes brought by PRs #71118 and #72078. Signed-off-by: Tomi Fontanilles --- doc/releases/migration-guide-3.7.rst | 6 ++++++ doc/releases/release-notes-3.7.rst | 3 +++ 2 files changed, 9 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 19f272214045a8..3471a1a9a9d2dd 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -39,6 +39,12 @@ Boards Modules ******* +MbedTLS +======= + +* The hash algorithms SHA-384, SHA-512, MD5 and SHA-1 are not enabled by default anymore. + Their respective Kconfig options now need to be explicitly enabled to be able to use them. + MCUboot ======= diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index bc60d8f3d2c400..2659e536310385 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -319,6 +319,9 @@ Libraries / Subsystems * Crypto + * MbedTLS was updated to 3.6.0. Release notes can be found at: + https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.0 + * Random * Besides the existing :c:func:`sys_rand32_get` function, :c:func:`sys_rand8_get`, From 397685e7b1f2a98f64641bc623834a5922526420 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0486/1389] cmake/modules/extensions: Fix string list replacement Changing from `;` to `|` directly doesn't consider for escaped `;` inside a list. Fix suggested by @pillo79. Signed-off-by: Ederson de Souza --- cmake/modules/extensions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 35ab0e246b250b..924417286ce3d4 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -5326,7 +5326,7 @@ function(add_llext_target target_name) REPLACE "(.+)" "^\\1$" OUTPUT_VARIABLE llext_remove_flags_regexp ) - string(REPLACE ";" "|" llext_remove_flags_regexp "${llext_remove_flags_regexp}") + list(JOIN llext_remove_flags_regexp "|" llext_remove_flags_regexp) if ("${llext_remove_flags_regexp}" STREQUAL "") # an empty regexp would match anything, we actually need the opposite # so set it to match empty strings From 089bc45384ad346de8dd6b78eb1da2f4fbd7f274 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0487/1389] coding guidelines: comply with MISRA Rule 12.1. added parentheses verifying lack of ambiguities Signed-off-by: Hess Nathan --- kernel/futex.c | 2 +- kernel/include/ksched.h | 2 +- kernel/kheap.c | 2 +- kernel/mem_domain.c | 4 ++-- kernel/mem_slab.c | 2 +- kernel/mmu.c | 4 ++-- kernel/pipes.c | 14 +++++++------- kernel/queue.c | 2 +- kernel/sched.c | 6 +++--- kernel/thread.c | 6 +++--- kernel/timeout.c | 6 +++--- kernel/userspace.c | 6 +++--- 12 files changed, 28 insertions(+), 28 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 1354a6314e496d..813ce0f62e3f03 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -17,7 +17,7 @@ static struct z_futex_data *k_futex_find_data(struct k_futex *futex) struct k_object *obj; obj = k_object_find(futex); - if (obj == NULL || obj->type != K_OBJ_FUTEX) { + if ((obj == NULL) || (obj->type != K_OBJ_FUTEX)) { return NULL; } diff --git a/kernel/include/ksched.h b/kernel/include/ksched.h index 058e44ebef3a99..a25755aac279bb 100644 --- a/kernel/include/ksched.h +++ b/kernel/include/ksched.h @@ -117,7 +117,7 @@ int32_t z_sched_prio_cmp(struct k_thread *thread_1, struct k_thread *thread_2); static inline bool _is_valid_prio(int prio, void *entry_point) { - if (prio == K_IDLE_PRIO && z_is_idle_thread_entry(entry_point)) { + if ((prio == K_IDLE_PRIO) && z_is_idle_thread_entry(entry_point)) { return true; } diff --git a/kernel/kheap.c b/kernel/kheap.c index fd29df2e92c0d8..ccdd66907880c0 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -123,7 +123,7 @@ void k_heap_free(struct k_heap *heap, void *mem) sys_heap_free(&heap->heap, mem); SYS_PORT_TRACING_OBJ_FUNC(k_heap, free, heap); - if (IS_ENABLED(CONFIG_MULTITHREADING) && z_unpend_all(&heap->wait_q) != 0) { + if (IS_ENABLED(CONFIG_MULTITHREADING) && (z_unpend_all(&heap->wait_q) != 0)) { z_reschedule(&heap->lock, key); } else { k_spin_unlock(&heap->lock, key); diff --git a/kernel/mem_domain.c b/kernel/mem_domain.c index 5c41c1418fe006..16b337acf011df 100644 --- a/kernel/mem_domain.c +++ b/kernel/mem_domain.c @@ -225,8 +225,8 @@ int k_mem_domain_remove_partition(struct k_mem_domain *domain, /* find a partition that matches the given start and size */ for (p_idx = 0; p_idx < max_partitions; p_idx++) { - if (domain->partitions[p_idx].start == part->start && - domain->partitions[p_idx].size == part->size) { + if ((domain->partitions[p_idx].start == part->start) && + (domain->partitions[p_idx].size == part->size)) { break; } } diff --git a/kernel/mem_slab.c b/kernel/mem_slab.c index 7b62c96facc369..9482f0e88c50a2 100644 --- a/kernel/mem_slab.c +++ b/kernel/mem_slab.c @@ -261,7 +261,7 @@ void k_mem_slab_free(struct k_mem_slab *slab, void *mem) "Invalid memory pointer provided"); SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_mem_slab, free, slab); - if (slab->free_list == NULL && IS_ENABLED(CONFIG_MULTITHREADING)) { + if ((slab->free_list == NULL) && IS_ENABLED(CONFIG_MULTITHREADING)) { struct k_thread *pending_thread = z_unpend_first_thread(&slab->wait_q); if (pending_thread != NULL) { diff --git a/kernel/mmu.c b/kernel/mmu.c index 162e1c413e941a..7b283733edd6b2 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -581,7 +581,7 @@ void *k_mem_map_impl(uintptr_t phys, size_t size, uint32_t flags, bool is_anon) /* Need extra for the guard pages (before and after) which we * won't map. */ - total_size = size + CONFIG_MMU_PAGE_SIZE * 2; + total_size = size + (CONFIG_MMU_PAGE_SIZE * 2); dst = virt_region_alloc(total_size, CONFIG_MMU_PAGE_SIZE); if (dst == NULL) { @@ -731,7 +731,7 @@ void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) * region. So we also need to free them from the bitmap. */ pos = (uint8_t *)addr - CONFIG_MMU_PAGE_SIZE; - total_size = size + CONFIG_MMU_PAGE_SIZE * 2; + total_size = size + (CONFIG_MMU_PAGE_SIZE * 2); virt_region_free(pos, total_size); out: diff --git a/kernel/pipes.c b/kernel/pipes.c index 7ef2c1fa022873..d91a4d6b7c1a5c 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -162,8 +162,8 @@ int k_pipe_cleanup(struct k_pipe *pipe) k_spinlock_key_t key = k_spin_lock(&pipe->lock); - CHECKIF(z_waitq_head(&pipe->wait_q.readers) != NULL || - z_waitq_head(&pipe->wait_q.writers) != NULL) { + CHECKIF((z_waitq_head(&pipe->wait_q.readers) != NULL) || + (z_waitq_head(&pipe->wait_q.writers) != NULL)) { k_spin_unlock(&pipe->lock, key); SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, cleanup, pipe, -EAGAIN); @@ -308,7 +308,7 @@ static size_t pipe_buffer_list_populate(sys_dlist_t *list, static int pipe_return_code(size_t min_xfer, size_t bytes_remaining, size_t bytes_requested) { - if (bytes_requested - bytes_remaining >= min_xfer) { + if ((bytes_requested - bytes_remaining) >= min_xfer) { /* * At least the minimum number of requested * bytes have been transferred. @@ -394,7 +394,7 @@ int z_impl_k_pipe_put(struct k_pipe *pipe, const void *data, SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, put, pipe, timeout); - CHECKIF((min_xfer > bytes_to_write) || bytes_written == NULL) { + CHECKIF((min_xfer > bytes_to_write) || (bytes_written == NULL)) { SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, put, pipe, timeout, -EINVAL); @@ -704,7 +704,7 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, get, pipe, timeout); - CHECKIF((min_xfer > bytes_to_read) || bytes_read == NULL) { + CHECKIF((min_xfer > bytes_to_read) || (bytes_read == NULL)) { SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, get, pipe, timeout, -EINVAL); @@ -742,7 +742,7 @@ size_t z_impl_k_pipe_read_avail(struct k_pipe *pipe) k_spinlock_key_t key; /* Buffer and size are fixed. No need to spin. */ - if (pipe->buffer == NULL || pipe->size == 0U) { + if ((pipe->buffer == NULL) || (pipe->size == 0U)) { res = 0; goto out; } @@ -779,7 +779,7 @@ size_t z_impl_k_pipe_write_avail(struct k_pipe *pipe) k_spinlock_key_t key; /* Buffer and size are fixed. No need to spin. */ - if (pipe->buffer == NULL || pipe->size == 0U) { + if ((pipe->buffer == NULL) || (pipe->size == 0U)) { res = 0; goto out; } diff --git a/kernel/queue.c b/kernel/queue.c index b99bfb0174ab87..fcccde56f93108 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -249,7 +249,7 @@ int k_queue_append_list(struct k_queue *queue, void *head, void *tail) SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_queue, append_list, queue); /* invalid head or tail of list */ - CHECKIF(head == NULL || tail == NULL) { + CHECKIF((head == NULL) || (tail == NULL)) { SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_queue, append_list, queue, -EINVAL); return -EINVAL; diff --git a/kernel/sched.c b/kernel/sched.c index 32cdb5eff7e7eb..bb9676b18320ec 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -140,7 +140,7 @@ static ALWAYS_INLINE struct k_thread *runq_best(void) */ static inline bool should_queue_thread(struct k_thread *thread) { - return !IS_ENABLED(CONFIG_SMP) || thread != _current; + return !IS_ENABLED(CONFIG_SMP) || (thread != _current); } static ALWAYS_INLINE void queue_thread(struct k_thread *thread) @@ -272,7 +272,7 @@ static ALWAYS_INLINE struct k_thread *next_up(void) } /* Put _current back into the queue */ - if (thread != _current && active && + if ((thread != _current) && active && !z_is_idle_thread_object(_current) && !queued) { queue_thread(_current); } @@ -1007,7 +1007,7 @@ void z_impl_k_thread_priority_set(k_tid_t thread, int prio) bool need_sched = z_thread_prio_set((struct k_thread *)thread, prio); flag_ipi(); - if (need_sched && _current->base.sched_locked == 0U) { + if (need_sched && (_current->base.sched_locked == 0U)) { z_reschedule_unlocked(); } } diff --git a/kernel/thread.c b/kernel/thread.c index dfd5eb7bdd698d..3b197743b09ac9 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -284,15 +284,15 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, /* Special case: we allow reading the names of initialized threads * even if we don't have permission on them */ - if (thread == NULL || ko->type != K_OBJ_THREAD || - (ko->flags & K_OBJ_FLAG_INITIALIZED) == 0) { + if ((thread == NULL) || (ko->type != K_OBJ_THREAD) || + ((ko->flags & K_OBJ_FLAG_INITIALIZED) == 0)) { return -EINVAL; } if (K_SYSCALL_MEMORY_WRITE(buf, size) != 0) { return -EFAULT; } len = strlen(thread->name); - if (len + 1 > size) { + if ((len + 1) > size) { return -ENOSPC; } diff --git a/kernel/timeout.c b/kernel/timeout.c index 8c727e204f91b7..cf4a6d681d585d 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -40,14 +40,14 @@ static struct _timeout *first(void) { sys_dnode_t *t = sys_dlist_peek_head(&timeout_list); - return t == NULL ? NULL : CONTAINER_OF(t, struct _timeout, node); + return (t == NULL) ? NULL : CONTAINER_OF(t, struct _timeout, node); } static struct _timeout *next(struct _timeout *t) { sys_dnode_t *n = sys_dlist_peek_next(&timeout_list, &t->node); - return n == NULL ? NULL : CONTAINER_OF(n, struct _timeout, node); + return (n == NULL) ? NULL : CONTAINER_OF(n, struct _timeout, node); } static void remove_timeout(struct _timeout *t) @@ -114,7 +114,7 @@ void z_add_timeout(struct _timeout *to, _timeout_func_t fn, struct _timeout *t; if (IS_ENABLED(CONFIG_TIMEOUT_64BIT) && - Z_TICK_ABS(timeout.ticks) >= 0) { + (Z_TICK_ABS(timeout.ticks) >= 0)) { k_ticks_t ticks = Z_TICK_ABS(timeout.ticks) - curr_tick; to->dticks = MAX(1, ticks); diff --git a/kernel/userspace.c b/kernel/userspace.c index fed8f3a983c5f4..6a77532f8aebc0 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -391,7 +391,7 @@ static void *z_object_alloc(enum k_objects otype, size_t size) struct k_object *zo; uintptr_t tidx = 0; - if (otype <= K_OBJ_ANY || otype >= K_OBJ_LAST) { + if ((otype <= K_OBJ_ANY) || (otype >= K_OBJ_LAST)) { LOG_ERR("bad object type %d requested", otype); return NULL; } @@ -586,7 +586,7 @@ static void wordlist_cb(struct k_object *ko, void *ctx_ptr) struct perm_ctx *ctx = (struct perm_ctx *)ctx_ptr; if (sys_bitfield_test_bit((mem_addr_t)&ko->perms, ctx->parent_id) && - (struct k_thread *)ko->name != ctx->parent) { + ((struct k_thread *)ko->name != ctx->parent)) { sys_bitfield_set_bit((mem_addr_t)&ko->perms, ctx->child_id); } } @@ -727,7 +727,7 @@ int k_object_validate(struct k_object *ko, enum k_objects otype, enum _obj_init_check init) { if (unlikely((ko == NULL) || - (otype != K_OBJ_ANY && ko->type != otype))) { + ((otype != K_OBJ_ANY) && (ko->type != otype)))) { return -EBADF; } From d32da90857cf442daeca660b08512bdb398c70c5 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0488/1389] coding guidelines: comply with MISRA Rule 12.1. -added parentheses verifying lack of ambiguities Signed-off-by: Hess Nathan --- include/zephyr/internal/syscall_handler.h | 2 +- include/zephyr/kernel.h | 4 ++-- include/zephyr/sys/cbprintf_internal.h | 2 +- include/zephyr/sys/list_gen.h | 2 +- include/zephyr/sys/math_extras_impl.h | 8 ++++---- include/zephyr/sys/time_units.h | 2 +- include/zephyr/toolchain/gcc.h | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/zephyr/internal/syscall_handler.h b/include/zephyr/internal/syscall_handler.h index d3879621917788..09a19f1074388b 100644 --- a/include/zephyr/internal/syscall_handler.h +++ b/include/zephyr/internal/syscall_handler.h @@ -62,7 +62,7 @@ static inline bool k_is_in_user_syscall(void) * calls from supervisor mode bypass everything directly to * the implementation function. */ - return !k_is_in_isr() && _current->syscall_frame != NULL; + return !k_is_in_isr() && (_current->syscall_frame != NULL); } /** diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 56471770a7cdfa..71277e0b864215 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -46,7 +46,7 @@ BUILD_ASSERT(sizeof(intptr_t) == sizeof(long)); #define K_ANY NULL -#if CONFIG_NUM_COOP_PRIORITIES + CONFIG_NUM_PREEMPT_PRIORITIES == 0 +#if (CONFIG_NUM_COOP_PRIORITIES + CONFIG_NUM_PREEMPT_PRIORITIES) == 0 #error Zero available thread priorities defined! #endif @@ -5383,7 +5383,7 @@ void k_heap_free(struct k_heap *h, void *mem) __attribute_nonnull(1); /* Hand-calculated minimum heap sizes needed to return a successful * 1-byte allocation. See details in lib/os/heap.[ch] */ -#define Z_HEAP_MIN_SIZE (sizeof(void *) > 4 ? 56 : 44) +#define Z_HEAP_MIN_SIZE ((sizeof(void *) > 4) ? 56 : 44) /** * @brief Define a static k_heap in the specified linker section diff --git a/include/zephyr/sys/cbprintf_internal.h b/include/zephyr/sys/cbprintf_internal.h index 2ffc599aa40f43..e54903a0a1d149 100644 --- a/include/zephyr/sys/cbprintf_internal.h +++ b/include/zephyr/sys/cbprintf_internal.h @@ -676,7 +676,7 @@ do { \ Z_CBPRINTF_IS_LONGDOUBLE(_arg) && \ !IS_ENABLED(CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE)),\ "Packaging of long double not enabled in Kconfig."); \ - while (_align_offset % Z_CBPRINTF_ALIGNMENT(_arg) != 0UL) { \ + while ((_align_offset % Z_CBPRINTF_ALIGNMENT(_arg)) != 0UL) { \ _idx += sizeof(int); \ _align_offset += sizeof(int); \ } \ diff --git a/include/zephyr/sys/list_gen.h b/include/zephyr/sys/list_gen.h index ba29f7d9bec260..82d1986fe9bf1c 100644 --- a/include/zephyr/sys/list_gen.h +++ b/include/zephyr/sys/list_gen.h @@ -72,7 +72,7 @@ static inline sys_ ## __nname ## _t * \ sys_ ## __lname ## _peek_next(sys_ ## __nname ## _t *node) \ { \ - return node != NULL ? \ + return (node != NULL) ? \ sys_ ## __lname ## _peek_next_no_check(node) : \ NULL; \ } diff --git a/include/zephyr/sys/math_extras_impl.h b/include/zephyr/sys/math_extras_impl.h index f6f856c4ad46d0..76e0fa19cb6ff5 100644 --- a/include/zephyr/sys/math_extras_impl.h +++ b/include/zephyr/sys/math_extras_impl.h @@ -187,7 +187,7 @@ static inline bool size_mul_overflow(size_t a, size_t b, size_t *result) #if use_builtin(__builtin_clz) static inline int u32_count_leading_zeros(uint32_t x) { - return x == 0 ? 32 : __builtin_clz(x); + return (x == 0) ? 32 : __builtin_clz(x); } #else /* !use_builtin(__builtin_clz) */ static inline int u32_count_leading_zeros(uint32_t x) @@ -205,7 +205,7 @@ static inline int u32_count_leading_zeros(uint32_t x) #if use_builtin(__builtin_clzll) static inline int u64_count_leading_zeros(uint64_t x) { - return x == 0 ? 64 : __builtin_clzll(x); + return (x == 0) ? 64 : __builtin_clzll(x); } #else /* !use_builtin(__builtin_clzll) */ static inline int u64_count_leading_zeros(uint64_t x) @@ -221,7 +221,7 @@ static inline int u64_count_leading_zeros(uint64_t x) #if use_builtin(__builtin_ctz) static inline int u32_count_trailing_zeros(uint32_t x) { - return x == 0 ? 32 : __builtin_ctz(x); + return (x == 0) ? 32 : __builtin_ctz(x); } #else /* !use_builtin(__builtin_ctz) */ static inline int u32_count_trailing_zeros(uint32_t x) @@ -239,7 +239,7 @@ static inline int u32_count_trailing_zeros(uint32_t x) #if use_builtin(__builtin_ctzll) static inline int u64_count_trailing_zeros(uint64_t x) { - return x == 0 ? 64 : __builtin_ctzll(x); + return (x == 0) ? 64 : __builtin_ctzll(x); } #else /* !use_builtin(__builtin_ctzll) */ static inline int u64_count_trailing_zeros(uint64_t x) diff --git a/include/zephyr/sys/time_units.h b/include/zephyr/sys/time_units.h index 62c199bc488d9c..796be1d43a2141 100644 --- a/include/zephyr/sys/time_units.h +++ b/include/zephyr/sys/time_units.h @@ -56,7 +56,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) } #endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */ -#if defined(__cplusplus) && __cplusplus >= 201402L +#if defined(__cplusplus) && (__cplusplus >= 201402L) #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) #define TIME_CONSTEXPR #else diff --git a/include/zephyr/toolchain/gcc.h b/include/zephyr/toolchain/gcc.h index 8f1dcda0156a9b..99da187f9e40f8 100644 --- a/include/zephyr/toolchain/gcc.h +++ b/include/zephyr/toolchain/gcc.h @@ -82,7 +82,7 @@ * static_assert() is not available) */ #elif !defined(__cplusplus) && \ - ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) || \ + (((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))) || \ (__STDC_VERSION__) >= 201100) #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG) #else @@ -138,7 +138,7 @@ __extension__ ({ \ }) -#if __GNUC__ >= 7 && (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) +#if (__GNUC__ >= 7) && (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) /* Version of UNALIGNED_PUT() which issues a compiler_barrier() after * the store. It is required to workaround an apparent optimization @@ -590,7 +590,7 @@ do { \ /* random suffix to avoid naming conflict */ \ __typeof__(a) _value_a_ = (a); \ __typeof__(b) _value_b_ = (b); \ - _value_a_ > _value_b_ ? _value_a_ : _value_b_; \ + (_value_a_ > _value_b_) ? _value_a_ : _value_b_; \ }) /** @brief Return smaller value of two provided expressions. @@ -602,7 +602,7 @@ do { \ /* random suffix to avoid naming conflict */ \ __typeof__(a) _value_a_ = (a); \ __typeof__(b) _value_b_ = (b); \ - _value_a_ < _value_b_ ? _value_a_ : _value_b_; \ + (_value_a_ < _value_b_) ? _value_a_ : _value_b_; \ }) /** @brief Return a value clamped to a given range. From 26338e15f1a896c73867110bbf8434055ed138a4 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0489/1389] coding guidelines: comply with MISRA Rule 13.4 - avoid to use assignment expression value Signed-off-by: Hess Nathan --- include/zephyr/sys/rb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/sys/rb.h b/include/zephyr/sys/rb.h index 3054119ff660cf..71d671b6222f83 100644 --- a/include/zephyr/sys/rb.h +++ b/include/zephyr/sys/rb.h @@ -232,7 +232,7 @@ struct rbnode *z_rb_foreach_next(struct rbtree *tree, struct _rb_foreach *f); for (struct _rb_foreach __f = _RB_FOREACH_INIT(tree, node); \ ({struct rbnode *n = z_rb_foreach_next(tree, &__f); \ node = n ? CONTAINER_OF(n, __typeof__(*(node)), \ - field) : NULL; }) != NULL; \ + field) : NULL; (node); }) != NULL; \ /**/) /** @} */ From c5e03f65f6d023bedff1fb549de231030b68fc48 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0490/1389] pm: device_runtime: Small API documentation fix Remove an invalid return value in pm_device_runtime_enable Signed-off-by: Flavio Ceolin --- include/zephyr/pm/device_runtime.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/zephyr/pm/device_runtime.h b/include/zephyr/pm/device_runtime.h index b1404fa4ac4c8a..fde8f631ca2f9f 100644 --- a/include/zephyr/pm/device_runtime.h +++ b/include/zephyr/pm/device_runtime.h @@ -48,7 +48,6 @@ int pm_device_runtime_auto_enable(const struct device *dev); * @param dev Device instance. * * @retval 0 If the device runtime PM is enabled successfully. - * @retval -EPERM If device has power state locked. * @retval -EBUSY If device is busy. * @retval -ENOTSUP If the device does not support PM. * @retval -errno Other negative errno, result of suspending the device. From 821b07c5ce1d8f536485bf6e8279baf9f391b8a5 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0491/1389] drivers: serial: Smartbond: Flow control for uart2 and uart3 UART2 and UART3 (unlink UART) do support hardware flow control. This simply add necessary flag that is already handled in the code. Signed-off-by: Jerzy Kasenberg --- dts/arm/renesas/smartbond/da1469x.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index eed1abc33ee79c..c78e8bb414bf04 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -272,6 +272,7 @@ reg = <0x50020100 0x100>; periph-clock-config = <0x02>; interrupts = <6 0>; + hw-flow-control-supported; status = "disabled"; }; @@ -280,6 +281,7 @@ reg = <0x50020200 0x100>; periph-clock-config = <0x08>; interrupts = <7 0>; + hw-flow-control-supported; status = "disabled"; }; From 7067f70abc8e4a0e6a4743793314be1ccfd07238 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0492/1389] drivers: serial: smartbond: Add PM for UART This is initial version that implements device power management support when configured in Kconfig files. Signed-off-by: Andrzej Kaczmarek --- drivers/serial/uart_smartbond.c | 134 +++++++++++++++++++++++--------- 1 file changed, 98 insertions(+), 36 deletions(-) diff --git a/drivers/serial/uart_smartbond.c b/drivers/serial/uart_smartbond.c index 7d5ef34cc72db6..e6f3e0d300f76f 100644 --- a/drivers/serial/uart_smartbond.c +++ b/drivers/serial/uart_smartbond.c @@ -9,11 +9,13 @@ #include #include #include +#include #include #include #include #include #include +#include #define IIR_NO_INTR 1 #define IIR_THR_EMPTY 2 @@ -77,8 +79,14 @@ struct uart_smartbond_cfg { #endif }; +struct uart_smartbond_runtime_cfg { + uint32_t baudrate_cfg; + uint32_t lcr_reg_val; +}; + struct uart_smartbond_data { struct uart_config current_config; + struct uart_smartbond_runtime_cfg runtime_cfg; struct k_spinlock lock; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t callback; @@ -122,14 +130,46 @@ static void uart_smartbond_poll_out(const struct device *dev, unsigned char out_ k_spin_unlock(&data->lock, key); } +static void apply_runtime_config(const struct device *dev) +{ + const struct uart_smartbond_cfg *config = dev->config; + struct uart_smartbond_data *data = dev->data; + k_spinlock_key_t key; + + key = k_spin_lock(&data->lock); + + CRG_COM->SET_CLK_COM_REG = config->periph_clock_config; + + config->regs->UART2_SRR_REG = UART2_UART2_SRR_REG_UART_UR_Msk | + UART2_UART2_SRR_REG_UART_RFR_Msk | + UART2_UART2_SRR_REG_UART_XFR_Msk; + + /* Configure baudrate */ + config->regs->UART2_LCR_REG |= UART2_UART2_LCR_REG_UART_DLAB_Msk; + config->regs->UART2_IER_DLH_REG = BAUDRATE_CFG_DLH(data->runtime_cfg.baudrate_cfg); + config->regs->UART2_RBR_THR_DLL_REG = BAUDRATE_CFG_DLL(data->runtime_cfg.baudrate_cfg); + config->regs->UART2_DLF_REG = BAUDRATE_CFG_DLF(data->runtime_cfg.baudrate_cfg); + config->regs->UART2_LCR_REG &= ~UART2_UART2_LCR_REG_UART_DLAB_Msk; + + /* Configure frame */ + config->regs->UART2_LCR_REG = data->runtime_cfg.lcr_reg_val; + + /* Enable hardware FIFO */ + config->regs->UART2_SFE_REG = UART2_UART2_SFE_REG_UART_SHADOW_FIFO_ENABLE_Msk; + + config->regs->UART2_SRT_REG = RX_FIFO_TRIG_1_CHAR; + config->regs->UART2_STET_REG = TX_FIFO_TRIG_1_2_FULL; + + k_spin_unlock(&data->lock, key); +} + static int uart_smartbond_configure(const struct device *dev, - const struct uart_config *cfg) + const struct uart_config *cfg) { const struct uart_smartbond_cfg *config = dev->config; struct uart_smartbond_data *data = dev->data; uint32_t baudrate_cfg = 0; - k_spinlock_key_t key; - uint32_t reg_val; + uint32_t lcr_reg_val; int err; int i; @@ -161,63 +201,43 @@ static int uart_smartbond_configure(const struct device *dev, return -ENOTSUP; } - key = k_spin_lock(&data->lock); - - CRG_COM->SET_CLK_COM_REG = config->periph_clock_config; - - config->regs->UART2_SRR_REG = UART2_UART2_SRR_REG_UART_UR_Msk | - UART2_UART2_SRR_REG_UART_RFR_Msk | - UART2_UART2_SRR_REG_UART_XFR_Msk; - - config->regs->UART2_LCR_REG |= UART2_UART2_LCR_REG_UART_DLAB_Msk; - config->regs->UART2_IER_DLH_REG = BAUDRATE_CFG_DLH(baudrate_cfg); - config->regs->UART2_RBR_THR_DLL_REG = BAUDRATE_CFG_DLL(baudrate_cfg); - config->regs->UART2_DLF_REG = BAUDRATE_CFG_DLF(baudrate_cfg); - config->regs->UART2_LCR_REG &= ~UART2_UART2_LCR_REG_UART_DLAB_Msk; - - /* Configure frame */ - - reg_val = 0; + /* Calculate frame configuration register value */ + lcr_reg_val = 0; switch (cfg->parity) { case UART_CFG_PARITY_NONE: break; case UART_CFG_PARITY_EVEN: - reg_val |= UART2_UART2_LCR_REG_UART_EPS_Msk; + lcr_reg_val |= UART2_UART2_LCR_REG_UART_EPS_Msk; /* no break */ case UART_CFG_PARITY_ODD: - reg_val |= UART2_UART2_LCR_REG_UART_PEN_Msk; + lcr_reg_val |= UART2_UART2_LCR_REG_UART_PEN_Msk; break; } if (cfg->stop_bits == UART_CFG_STOP_BITS_2) { - reg_val |= STOP_BITS_2 << UART2_UART2_LCR_REG_UART_STOP_Pos; + lcr_reg_val |= STOP_BITS_2 << UART2_UART2_LCR_REG_UART_STOP_Pos; } switch (cfg->data_bits) { case UART_CFG_DATA_BITS_6: - reg_val |= DATA_BITS_6 << UART2_UART2_LCR_REG_UART_DLS_Pos; + lcr_reg_val |= DATA_BITS_6 << UART2_UART2_LCR_REG_UART_DLS_Pos; break; case UART_CFG_DATA_BITS_7: - reg_val |= DATA_BITS_7 << UART2_UART2_LCR_REG_UART_DLS_Pos; + lcr_reg_val |= DATA_BITS_7 << UART2_UART2_LCR_REG_UART_DLS_Pos; break; case UART_CFG_DATA_BITS_8: - reg_val |= DATA_BITS_8 << UART2_UART2_LCR_REG_UART_DLS_Pos; + lcr_reg_val |= DATA_BITS_8 << UART2_UART2_LCR_REG_UART_DLS_Pos; break; } - config->regs->UART2_LCR_REG = reg_val; + data->runtime_cfg.baudrate_cfg = baudrate_cfg; + data->runtime_cfg.lcr_reg_val = lcr_reg_val; - /* Enable hardware FIFO */ - config->regs->UART2_SFE_REG = UART2_UART2_SFE_REG_UART_SHADOW_FIFO_ENABLE_Msk; - - config->regs->UART2_SRT_REG = RX_FIFO_TRIG_1_CHAR; - config->regs->UART2_STET_REG = TX_FIFO_TRIG_1_2_FULL; + apply_runtime_config(dev); data->current_config = *cfg; - k_spin_unlock(&data->lock, key); - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); if (err < 0) { return err; @@ -241,8 +261,16 @@ static int uart_smartbond_config_get(const struct device *dev, static int uart_smartbond_init(const struct device *dev) { struct uart_smartbond_data *data = dev->data; + int ret; + + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + + ret = uart_smartbond_configure(dev, &data->current_config); + if (ret < 0) { + da1469x_pd_release(MCU_PD_DOMAIN_COM); + } - return uart_smartbond_configure(dev, &data->current_config); + return ret; } #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -455,6 +483,39 @@ static void uart_smartbond_isr(const struct device *dev) } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef CONFIG_PM_DEVICE +static void uart_disable(const struct device *dev) +{ + const struct uart_smartbond_cfg *config = dev->config; + + while (!(config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_TFE_Msk) || + (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_BUSY_Msk)) { + /* Wait until FIFO is empty and UART finished tx */ + } + + CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; + da1469x_pd_release(MCU_PD_DOMAIN_COM); +} + +static int uart_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_RESUME: + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + apply_runtime_config(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + uart_disable(dev); + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct uart_driver_api uart_smartbond_driver_api = { .poll_in = uart_smartbond_poll_in, .poll_out = uart_smartbond_poll_out, @@ -516,9 +577,10 @@ static const struct uart_driver_api uart_smartbond_driver_api = { UART_SMARTBOND_CONFIGURE(id); \ return uart_smartbond_init(dev); \ } \ + PM_DEVICE_DT_INST_DEFINE(id, uart_smartbond_pm_action); \ DEVICE_DT_INST_DEFINE(id, \ uart_smartbond_##id##_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(id), \ &uart_smartbond_##id##_data, \ &uart_smartbond_##id##_cfg, \ PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ From 6c0d902004cf9f86e0d22d2e3e0c2e4979d4b79d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0493/1389] drivers: serial: Smartbond: add support RX line wakeup This change allows to wake up UART from sleep mode when low level on inactive UART is detected during platform sleep. Timeout can be specified for each UART separately in device tree. If one of the UARTs is selected as console sleep timeout is taken from Kconfig same way other platform configure same functionality using CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT Signed-off-by: Jerzy Kasenberg --- .../renesas/da1469x_dk_pro/da1469x_dk_pro.dts | 1 + drivers/serial/Kconfig.smartbond | 1 + drivers/serial/uart_smartbond.c | 150 +++++++++++++++++- .../serial/renesas,smartbond-uart.yaml | 9 ++ 4 files changed, 156 insertions(+), 5 deletions(-) diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts index f83098f6f197cd..f4a3d1d674ee4f 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts @@ -119,6 +119,7 @@ status = "okay"; pinctrl-0 = <&uart_default>; pinctrl-names = "default"; + rx-wake-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; }; zephyr_udc0: &usbd { diff --git a/drivers/serial/Kconfig.smartbond b/drivers/serial/Kconfig.smartbond index 5572b5ba187497..2ea73a37fa110a 100644 --- a/drivers/serial/Kconfig.smartbond +++ b/drivers/serial/Kconfig.smartbond @@ -7,5 +7,6 @@ config UART_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT + select UART_INTERRUPT_DRIVEN if PM_DEVICE help Enable UART driver for Renesas SmartBond(tm) DA1469x series MCU. diff --git a/drivers/serial/uart_smartbond.c b/drivers/serial/uart_smartbond.c index e6f3e0d300f76f..66ec3e108f62ba 100644 --- a/drivers/serial/uart_smartbond.c +++ b/drivers/serial/uart_smartbond.c @@ -7,9 +7,11 @@ #define DT_DRV_COMPAT renesas_smartbond_uart #include +#include #include #include #include +#include #include #include #include @@ -77,11 +79,22 @@ struct uart_smartbond_cfg { #ifdef CONFIG_UART_INTERRUPT_DRIVEN void (*irq_config_func)(const struct device *dev); #endif +#if CONFIG_PM_DEVICE + int rx_wake_timeout; + struct gpio_dt_spec rx_wake_gpio; +#endif }; struct uart_smartbond_runtime_cfg { uint32_t baudrate_cfg; uint32_t lcr_reg_val; + uint8_t mcr_reg_val; + uint8_t ier_reg_val; +}; + +enum uart_smartbond_pm_policy_state_flag { + UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG, + UART_SMARTBOND_PM_POLICY_STATE_FLAG_COUNT, }; struct uart_smartbond_data { @@ -94,9 +107,43 @@ struct uart_smartbond_data { uint32_t flags; uint8_t rx_enabled; uint8_t tx_enabled; +#if CONFIG_PM_DEVICE + const struct uart_smartbond_cfg *config; + struct gpio_callback rx_wake_cb; + int rx_wake_timeout; + struct k_work_delayable rx_timeout_work; + + ATOMIC_DEFINE(pm_policy_state_flag, UART_SMARTBOND_PM_POLICY_STATE_FLAG_COUNT); +#endif #endif }; +#if defined(CONFIG_PM_DEVICE) + +static void uart_smartbond_pm_policy_state_lock_get(struct uart_smartbond_data *data, int flag) +{ + if (atomic_test_and_set_bit(data->pm_policy_state_flag, flag) == 0) { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +static void uart_smartbond_pm_policy_state_lock_put(struct uart_smartbond_data *data, int flag) +{ + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, flag) == 1) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +static void uart_smartbond_rx_refresh_timeout(struct k_work *work) +{ + struct uart_smartbond_data *data = CONTAINER_OF(work, struct uart_smartbond_data, + rx_timeout_work.work); + + uart_smartbond_pm_policy_state_lock_put(data, UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG); +} + +#endif + static int uart_smartbond_poll_in(const struct device *dev, unsigned char *p_char) { const struct uart_smartbond_cfg *config = dev->config; @@ -140,6 +187,7 @@ static void apply_runtime_config(const struct device *dev) CRG_COM->SET_CLK_COM_REG = config->periph_clock_config; + config->regs->UART2_MCR_REG = data->runtime_cfg.mcr_reg_val; config->regs->UART2_SRR_REG = UART2_UART2_SRR_REG_UART_UR_Msk | UART2_UART2_SRR_REG_UART_RFR_Msk | UART2_UART2_SRR_REG_UART_XFR_Msk; @@ -159,6 +207,7 @@ static void apply_runtime_config(const struct device *dev) config->regs->UART2_SRT_REG = RX_FIFO_TRIG_1_CHAR; config->regs->UART2_STET_REG = TX_FIFO_TRIG_1_2_FULL; + config->regs->UART2_IER_DLH_REG = data->runtime_cfg.ier_reg_val; k_spin_unlock(&data->lock, key); } @@ -233,6 +282,7 @@ static int uart_smartbond_configure(const struct device *dev, data->runtime_cfg.baudrate_cfg = baudrate_cfg; data->runtime_cfg.lcr_reg_val = lcr_reg_val; + data->runtime_cfg.mcr_reg_val = cfg->flow_ctrl ? UART2_UART2_MCR_REG_UART_AFCE_Msk : 0; apply_runtime_config(dev); @@ -258,13 +308,65 @@ static int uart_smartbond_config_get(const struct device *dev, } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#if CONFIG_PM_DEVICE + +static void uart_smartbond_wake_handler(const struct device *gpio, struct gpio_callback *cb, + uint32_t pins) +{ + struct uart_smartbond_data *data = CONTAINER_OF(cb, struct uart_smartbond_data, + rx_wake_cb); + + /* Disable interrupts on UART RX pin to avoid repeated interrupts. */ + (void)gpio_pin_interrupt_configure(gpio, (find_msb_set(pins) - 1), + GPIO_INT_DISABLE); + /* Refresh console expired time */ + if (data->rx_wake_timeout) { + + uart_smartbond_pm_policy_state_lock_get(data, + UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG); + k_work_reschedule(&data->rx_timeout_work, K_MSEC(data->rx_wake_timeout)); + } +} + +#endif + static int uart_smartbond_init(const struct device *dev) { struct uart_smartbond_data *data = dev->data; - int ret; + int ret = 0; da1469x_pd_acquire(MCU_PD_DOMAIN_COM); +#ifdef CONFIG_PM_DEVICE + int rx_wake_timeout; + const struct uart_smartbond_cfg *config = dev->config; + const struct device *uart_console_dev = + DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); + /* All uarts can have wake time specified in device tree to keep + * device awake after receiving data + */ + rx_wake_timeout = config->rx_wake_timeout; + if (dev == uart_console_dev) { +#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED + /* For device configured as console wake time is taken from + * Kconfig same way it is configured for other platforms + */ + rx_wake_timeout = CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT; +#endif + } + if (rx_wake_timeout > 0 && config->rx_wake_gpio.port != NULL) { + k_work_init_delayable(&data->rx_timeout_work, + uart_smartbond_rx_refresh_timeout); + gpio_init_callback(&data->rx_wake_cb, uart_smartbond_wake_handler, + BIT(config->rx_wake_gpio.pin)); + + ret = gpio_add_callback(config->rx_wake_gpio.port, &data->rx_wake_cb); + if (ret == 0) { + data->rx_wake_timeout = rx_wake_timeout; + } + } +#endif + ret = uart_smartbond_configure(dev, &data->current_config); if (ret < 0) { da1469x_pd_release(MCU_PD_DOMAIN_COM); @@ -344,6 +446,11 @@ static int uart_smartbond_fifo_read(const struct device *dev, uint8_t *rx_data, irq_rx_enable(dev); } +#ifdef CONFIG_PM_DEVICE + if (data->rx_wake_timeout) { + k_work_reschedule(&data->rx_timeout_work, K_MSEC(data->rx_wake_timeout)); + } +#endif k_spin_unlock(&data->lock, key); return num_rx; @@ -484,35 +591,56 @@ static void uart_smartbond_isr(const struct device *dev) #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_PM_DEVICE -static void uart_disable(const struct device *dev) +static int uart_disable(const struct device *dev) { const struct uart_smartbond_cfg *config = dev->config; + struct uart_smartbond_data *data = dev->data; + + /* Store IER register in case UART will go to sleep */ + data->runtime_cfg.ier_reg_val = config->regs->UART2_IER_DLH_REG; + if (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_RFNE_Msk) { + return -EBUSY; + } while (!(config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_TFE_Msk) || (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_BUSY_Msk)) { /* Wait until FIFO is empty and UART finished tx */ + if (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_RFNE_Msk) { + return -EBUSY; + } } CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; da1469x_pd_release(MCU_PD_DOMAIN_COM); + + return 0; } static int uart_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { + const struct uart_smartbond_cfg *config; + int ret = 0; + switch (action) { case PM_DEVICE_ACTION_RESUME: da1469x_pd_acquire(MCU_PD_DOMAIN_COM); apply_runtime_config(dev); break; case PM_DEVICE_ACTION_SUSPEND: - uart_disable(dev); + config = dev->config; + ret = uart_disable(dev); + if (ret == 0 && config->rx_wake_gpio.port != NULL) { + ret = gpio_pin_interrupt_configure_dt(&config->rx_wake_gpio, + GPIO_INT_MODE_EDGE | + GPIO_INT_TRIG_LOW); + } break; default: - return -ENOTSUP; + ret = -ENOTSUP; } - return 0; + return ret; } #endif /* CONFIG_PM_DEVICE */ @@ -555,6 +683,16 @@ static const struct uart_driver_api uart_smartbond_driver_api = { #define UART_SMARTBOND_CONFIGURE(id) #endif +#ifdef CONFIG_PM_DEVICE +#define UART_PM_WAKE_RX_TIMEOUT(n) \ + .rx_wake_timeout = (DT_INST_PROP_OR(n, rx_wake_timeout, 0)), +#define UART_PM_WAKE_RX_PIN(n) \ + .rx_wake_gpio = GPIO_DT_SPEC_INST_GET_OR(n, rx_wake_gpios, {0}), +#else +#define UART_PM_WAKE_RX_PIN(n) /* Not used */ +#define UART_PM_WAKE_RX_TIMEOUT(n) /* Not used */ +#endif + #define UART_SMARTBOND_DEVICE(id) \ PINCTRL_DT_INST_DEFINE(id); \ static const struct uart_smartbond_cfg uart_smartbond_##id##_cfg = { \ @@ -562,6 +700,8 @@ static const struct uart_driver_api uart_smartbond_driver_api = { .periph_clock_config = DT_INST_PROP(id, periph_clock_config), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ .hw_flow_control_supported = DT_INST_PROP(id, hw_flow_control_supported), \ + UART_PM_WAKE_RX_TIMEOUT(id) \ + UART_PM_WAKE_RX_PIN(id) \ }; \ static struct uart_smartbond_data uart_smartbond_##id##_data = { \ .current_config = { \ diff --git a/dts/bindings/serial/renesas,smartbond-uart.yaml b/dts/bindings/serial/renesas,smartbond-uart.yaml index 4b2a2b973c2d95..9eaf48974e89ad 100644 --- a/dts/bindings/serial/renesas,smartbond-uart.yaml +++ b/dts/bindings/serial/renesas,smartbond-uart.yaml @@ -38,3 +38,12 @@ properties: hw-flow-control-supported: type: boolean description: Set to indicate RTS/CTS flow control is supported. + + rx-wake-gpios: + type: phandle-array + description: GPIO configured as wake source + + rx-wake-timeout: + type: int + description: | + Time to prevent UART entering sleep mode after receiving data (ms) From 8004c23c71f8ca0cba57d26e19d7a575ace1e1de Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0494/1389] drivers: serial: Smartbond: add support DTR line wakeup This change allows to use DTR line driven from external serial port that when active (low) will prevent UART device from going to sleep. It will also wake up platform when DTR line becomes active. DTR line is often activated in serial port connected to host computer when operating system opens serial device like COMx for Windows or /dev/ttyACMx /dev/ttyUSBx for Linux based systems. DTR line (specified in device tree) will be used by WAKEUP and PDC controllers (via GPIO driver) to handle DTR line changes. Signed-off-by: Jerzy Kasenberg --- drivers/serial/uart_smartbond.c | 39 +++++++++++++++++++ .../serial/renesas,smartbond-uart.yaml | 12 ++++++ 2 files changed, 51 insertions(+) diff --git a/drivers/serial/uart_smartbond.c b/drivers/serial/uart_smartbond.c index 66ec3e108f62ba..8656ae8dc433d9 100644 --- a/drivers/serial/uart_smartbond.c +++ b/drivers/serial/uart_smartbond.c @@ -82,6 +82,7 @@ struct uart_smartbond_cfg { #if CONFIG_PM_DEVICE int rx_wake_timeout; struct gpio_dt_spec rx_wake_gpio; + struct gpio_dt_spec dtr_gpio; #endif }; @@ -94,6 +95,7 @@ struct uart_smartbond_runtime_cfg { enum uart_smartbond_pm_policy_state_flag { UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG, UART_SMARTBOND_PM_POLICY_STATE_FLAG_COUNT, }; @@ -108,6 +110,7 @@ struct uart_smartbond_data { uint8_t rx_enabled; uint8_t tx_enabled; #if CONFIG_PM_DEVICE + struct gpio_callback dtr_wake_cb; const struct uart_smartbond_cfg *config; struct gpio_callback rx_wake_cb; int rx_wake_timeout; @@ -328,6 +331,22 @@ static void uart_smartbond_wake_handler(const struct device *gpio, struct gpio_c } } +static void uart_smartbond_dtr_handler(const struct device *gpio, struct gpio_callback *cb, + uint32_t pins) +{ + struct uart_smartbond_data *data = CONTAINER_OF(cb, struct uart_smartbond_data, + dtr_wake_cb); + int pin = find_lsb_set(pins) - 1; + + if (gpio_pin_get(gpio, pin) == 1) { + uart_smartbond_pm_policy_state_lock_put(data, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG); + } else { + uart_smartbond_pm_policy_state_lock_get(data, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG); + } +} + #endif static int uart_smartbond_init(const struct device *dev) @@ -354,6 +373,22 @@ static int uart_smartbond_init(const struct device *dev) rx_wake_timeout = CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT; #endif } + /* If DTR pin is configured, use it for power management */ + if (config->dtr_gpio.port != NULL) { + gpio_init_callback(&data->dtr_wake_cb, uart_smartbond_dtr_handler, + BIT(config->dtr_gpio.pin)); + ret = gpio_add_callback(config->dtr_gpio.port, &data->dtr_wake_cb); + if (ret == 0) { + ret = gpio_pin_interrupt_configure_dt(&config->dtr_gpio, + GPIO_INT_MODE_EDGE | + GPIO_INT_TRIG_BOTH); + /* Check if DTR is already active (low), if so lock power state */ + if (gpio_pin_get(config->dtr_gpio.port, config->dtr_gpio.pin) == 0) { + uart_smartbond_pm_policy_state_lock_get(data, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG); + } + } + } if (rx_wake_timeout > 0 && config->rx_wake_gpio.port != NULL) { k_work_init_delayable(&data->rx_timeout_work, uart_smartbond_rx_refresh_timeout); @@ -688,9 +723,12 @@ static const struct uart_driver_api uart_smartbond_driver_api = { .rx_wake_timeout = (DT_INST_PROP_OR(n, rx_wake_timeout, 0)), #define UART_PM_WAKE_RX_PIN(n) \ .rx_wake_gpio = GPIO_DT_SPEC_INST_GET_OR(n, rx_wake_gpios, {0}), +#define UART_PM_WAKE_DTR_PIN(n) \ + .dtr_gpio = GPIO_DT_SPEC_INST_GET_OR(n, dtr_gpios, {0}), #else #define UART_PM_WAKE_RX_PIN(n) /* Not used */ #define UART_PM_WAKE_RX_TIMEOUT(n) /* Not used */ +#define UART_PM_WAKE_DTR_PIN(n) /* Not used */ #endif #define UART_SMARTBOND_DEVICE(id) \ @@ -702,6 +740,7 @@ static const struct uart_driver_api uart_smartbond_driver_api = { .hw_flow_control_supported = DT_INST_PROP(id, hw_flow_control_supported), \ UART_PM_WAKE_RX_TIMEOUT(id) \ UART_PM_WAKE_RX_PIN(id) \ + UART_PM_WAKE_DTR_PIN(id) \ }; \ static struct uart_smartbond_data uart_smartbond_##id##_data = { \ .current_config = { \ diff --git a/dts/bindings/serial/renesas,smartbond-uart.yaml b/dts/bindings/serial/renesas,smartbond-uart.yaml index 9eaf48974e89ad..428eb0ca76e3d1 100644 --- a/dts/bindings/serial/renesas,smartbond-uart.yaml +++ b/dts/bindings/serial/renesas,smartbond-uart.yaml @@ -47,3 +47,15 @@ properties: type: int description: | Time to prevent UART entering sleep mode after receiving data (ms) + + dtr-gpios: + type: phandle-array + description: | + DTR pin specification. DTR pin when active tells that the driver that there + is active client on the other side of serial line. + The device driver does not use DTR for hardware flow control. + When device is connected to computer serial converter usually asserts DTR + line when serial port is opened and ready for communication. + This line can be used in Smartbond(tm) driver to detect remote client presence. + If client is not present the device can disable UART, allowing for + power system management to enter more efficient power levels. From e11c8ea1359579a21dd36ba47347ee27a1c90858 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0495/1389] dt-bindings: adc: Fix BIT_MASK redefined warning Include `dt-util.h` instead of providing a separate macro definition. Signed-off-by: Grzegorz Swiderski --- include/zephyr/dt-bindings/adc/adc.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/include/zephyr/dt-bindings/adc/adc.h b/include/zephyr/dt-bindings/adc/adc.h index fafadb163b6b9f..fcbb21e7875942 100644 --- a/include/zephyr/dt-bindings/adc/adc.h +++ b/include/zephyr/dt-bindings/adc/adc.h @@ -6,13 +6,7 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADC_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADC_H_ -/* - * Provide the BIT_MASK() macro for when this file is included from - * devicetrees. - */ -#ifndef BIT_MASK -#define BIT_MASK(n) ((1 << (n)) - 1) -#endif +#include /** Acquisition time is expressed in microseconds. */ #define ADC_ACQ_TIME_MICROSECONDS (1) From 29ed9d6ebf00d3c969dc7d3d9db0cd8eb1df9c06 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0496/1389] dt-bindings: misc: Add nRF54H20 Domain IDs and Owner IDs Move the Domain IDs from `nrf54h20.dtsi` into its own header file. Additionally, include another header with Owner IDs. Signed-off-by: Grzegorz Swiderski --- dts/common/nordic/nrf54h20.dtsi | 8 ++------ .../dt-bindings/misc/nordic-domain-id-nrf54h20.h | 13 +++++++++++++ .../dt-bindings/misc/nordic-owner-id-nrf54h20.h | 12 ++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h create mode 100644 include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 5671ac699a4cce..809dcd62ae426a 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -8,12 +8,8 @@ #include #include - -/* Domain IDs. Can be used to specify channel links in IPCT nodes. */ -#define NRF_DOMAIN_ID_APPLICATION 2 -#define NRF_DOMAIN_ID_RADIOCORE 3 -#define NRF_DOMAIN_ID_GLOBALFAST 12 -#define NRF_DOMAIN_ID_GLOBALSLOW 13 +#include +#include /delete-node/ &sw_pwm; diff --git a/include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h b/include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h new file mode 100644 index 00000000000000..a5fd23fd34b23a --- /dev/null +++ b/include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_DOMAIN_ID_NRF54H20_H_ + +#define NRF_DOMAIN_ID_APPLICATION 2 +#define NRF_DOMAIN_ID_RADIOCORE 3 +#define NRF_DOMAIN_ID_GLOBALFAST 12 +#define NRF_DOMAIN_ID_GLOBALSLOW 13 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_DOMAIN_ID_NRF54H20_H_ */ diff --git a/include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h b/include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h new file mode 100644 index 00000000000000..080b4e048e22a0 --- /dev/null +++ b/include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_OWNER_ID_NRF54H20_H_ + +#define NRF_OWNER_ID_NONE 0 +#define NRF_OWNER_ID_APPLICATION 2 +#define NRF_OWNER_ID_RADIOCORE 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_OWNER_ID_NRF54H20_H_ */ From b2cf170b3ed25a89f60b3297437bb1aeab7b2b24 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0497/1389] cmake: modules: dts: Expose DTS_INCLUDE_FILES This was previously used as a variable internal to the module, but it can be used in other places in the build system, which may want a list of DT-specific includes. Therefore, document it as an output variable. Signed-off-by: Grzegorz Swiderski --- cmake/modules/dts.cmake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/modules/dts.cmake b/cmake/modules/dts.cmake index d1ff4df9bcd620..1cd531b7f3c57b 100644 --- a/cmake/modules/dts.cmake +++ b/cmake/modules/dts.cmake @@ -57,8 +57,9 @@ find_package(Dtc 1.4.6) # - ${PROJECT_BINARY_DIR}/zephyr.dts exists # - ${PROJECT_BINARY_DIR}/edt.pickle exists # - ${KCONFIG_BINARY_DIR}/Kconfig.dts exists -# - the build system will be regenerated if any devicetree files -# used in this build change, including transitive includes +# - DTS_INCLUDE_FILES is set to a ;-list of all devicetree files +# used in this build, including transitive includes (the build +# system will be regenerated if any of those files change) # - the devicetree extensions in the extensions.cmake module # will be ready for use in other CMake list files that run # after this module @@ -257,14 +258,14 @@ zephyr_dt_preprocess( # Parse the generated dependency file to find the DT sources that # were included, including any transitive includes. toolchain_parse_make_rule(${DTS_DEPS} - include_files # Output parameter + DTS_INCLUDE_FILES # Output parameter ) # Add the results to the list of files that, when change, force the # build system to re-run CMake. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS - ${include_files} + ${DTS_INCLUDE_FILES} ${GEN_DEFINES_SCRIPT} ${GEN_DRIVER_KCONFIG_SCRIPT} ${GEN_DTS_CMAKE_SCRIPT} From cf1359972198b08dfd2b7439534bb4579d10240c Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0498/1389] soc: nordic: Add system for validating DT headers against MDK Hardware-specific properties should stay in sync with the definitions provided by MDK. Existing measures for this include: * The `validate_base_addresses.c` file included in every build; * The `nordic-nrf-ficr-nrf54h20.h` header generated from SVD. If there's information that cannot be extracted from SVD, it may have to be validated against C types. Add `validate_binding_headers.c` for this purpose, which automagically includes all `dt-bindings` headers included by DTS in a given build. Signed-off-by: Grzegorz Swiderski --- soc/nordic/CMakeLists.txt | 13 ++++++++ soc/nordic/validate_binding_headers.c | 48 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 soc/nordic/validate_binding_headers.c diff --git a/soc/nordic/CMakeLists.txt b/soc/nordic/CMakeLists.txt index 9797d2e717a309..f1ad19476f0997 100644 --- a/soc/nordic/CMakeLists.txt +++ b/soc/nordic/CMakeLists.txt @@ -8,9 +8,22 @@ endif() zephyr_library_sources( validate_base_addresses.c + validate_binding_headers.c validate_enabled_instances.c ) +# Include dt-bindings headers into the build. This lets us validate all required +# DT values against the MDK, without having to conditionally include different +# headers for different SoCs. +set(dt_binding_includes ${DTS_INCLUDE_FILES}) +list(FILTER dt_binding_includes INCLUDE REGEX "/dt-bindings/.*\.h$") +list(TRANSFORM dt_binding_includes PREPEND "-include;") +set_source_files_properties( + validate_binding_headers.c + DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + PROPERTIES COMPILE_OPTIONS "${dt_binding_includes}" +) + if(CONFIG_SOC_HAS_TIMING_FUNCTIONS AND NOT CONFIG_BOARD_HAS_TIMING_FUNCTIONS) if(CONFIG_TIMING_FUNCTIONS) # Use nRF-specific timing calculations only if DWT is not present diff --git a/soc/nordic/validate_binding_headers.c b/soc/nordic/validate_binding_headers.c new file mode 100644 index 00000000000000..98ffffe867031c --- /dev/null +++ b/soc/nordic/validate_binding_headers.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * This file validates definitions found in dt-bindings headers against their + * expected values from MDK, which may be provided in the form of C types. + * + * Note: all dt-bindings headers which have been included by DTS in this build + * are automagically included in this file as well. See CMakeLists.txt. + */ + +#include +#include + +#include + +/** + * Domain IDs. See: + * - dt-bindings/misc/nordic-domain-id-nrf54h20.h + */ +#if defined(NRF_DOMAIN_ID_APPLICATION) +BUILD_ASSERT(NRF_DOMAIN_ID_APPLICATION == NRF_DOMAIN_APPLICATION); +#endif +#if defined(NRF_DOMAIN_ID_RADIOCORE) +BUILD_ASSERT(NRF_DOMAIN_ID_RADIOCORE == NRF_DOMAIN_RADIOCORE); +#endif +#if defined(NRF_DOMAIN_ID_GLOBALFAST) +BUILD_ASSERT(NRF_DOMAIN_ID_GLOBALFAST == NRF_DOMAIN_GLOBALFAST); +#endif +#if defined(NRF_DOMAIN_ID_GLOBALSLOW) +BUILD_ASSERT(NRF_DOMAIN_ID_GLOBALSLOW == NRF_DOMAIN_GLOBALSLOW); +#endif + +/** + * Owner IDs. See: + * - dt-bindings/misc/nordic-owner-id-nrf54h20.h + */ +#if defined(NRF_OWNER_ID_NONE) +BUILD_ASSERT(NRF_OWNER_ID_NONE == NRF_OWNER_NONE); +#endif +#if defined(NRF_OWNER_ID_APPLICATION) +BUILD_ASSERT(NRF_OWNER_ID_APPLICATION == NRF_OWNER_APPLICATION); +#endif +#if defined(NRF_OWNER_ID_RADIOCORE) +BUILD_ASSERT(NRF_OWNER_ID_RADIOCORE == NRF_OWNER_RADIOCORE); +#endif From fbb68f2398e7777b313e8c3ce11a0c4e07e871fd Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0499/1389] tests: net: ipv6: Fix RA test Due to recent changes, as simple k_yield() is not enough on some platforms (nRF platforms for example), as the entropy subsystem is now used because of PE, which may block, causing context switch before entire RA message is processed. Fix this by adding small delay before checking if RA was processed properly. Signed-off-by: Robert Lubos --- tests/net/ipv6/src/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index ffdd263e603fdb..59f374024c02e3 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -756,6 +756,8 @@ static void ra_message(void) ZTEST(net_ipv6, test_rs_ra_message) { rs_message(); + /* Small delay to let the net stack process the generated RA message. */ + k_sleep(K_MSEC(10)); ra_message(); } From 861195fa118168de968b763cc57d8ababe2bbda8 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0500/1389] dts: bindings: rtc: stm32-rtc: add alarms-count property Add alarms-count property to STM32 RTC binding Signed-off-by: Abderrahmane Jarmouni --- dts/bindings/rtc/st,stm32-rtc.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dts/bindings/rtc/st,stm32-rtc.yaml b/dts/bindings/rtc/st,stm32-rtc.yaml index dcfd2a49276b16..7cb3343269b2d5 100644 --- a/dts/bindings/rtc/st,stm32-rtc.yaml +++ b/dts/bindings/rtc/st,stm32-rtc.yaml @@ -1,11 +1,14 @@ # Copyright (c) 2018, Workaround GmbH +# Copyright (c) 2024 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 description: STM32 RTC compatible: "st,stm32-rtc" -include: rtc.yaml +include: + - rtc.yaml + - rtc-device.yaml properties: reg: @@ -18,3 +21,9 @@ properties: enum: - 1 - 512 + + alarms-count: + description: | + Number of alarms supported by STM32 RTC device. + Most of STM32 MCU series have 2 RTC alarms, A & B. + Defaults to 0 when not declared in devicetree. From 26b2bdcf2913afd1da7c18aafdbc40d061f5aaab Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:51 +0200 Subject: [PATCH 0501/1389] dts: arm: st: stm32-rtc: add alarms-count property Add alarms-count to STM32 RTC node of all series except F1X. Signed-off-by: Abderrahmane Jarmouni --- dts/arm/st/c0/stm32c0.dtsi | 2 ++ dts/arm/st/f0/stm32f0.dtsi | 2 ++ dts/arm/st/f2/stm32f2.dtsi | 2 ++ dts/arm/st/f3/stm32f3.dtsi | 2 ++ dts/arm/st/f4/stm32f4.dtsi | 2 ++ dts/arm/st/f7/stm32f7.dtsi | 2 ++ dts/arm/st/g0/stm32g0.dtsi | 3 ++- dts/arm/st/g4/stm32g4.dtsi | 2 ++ dts/arm/st/h5/stm32h5.dtsi | 3 ++- dts/arm/st/h7/stm32h7.dtsi | 2 ++ dts/arm/st/l0/stm32l0.dtsi | 1 + dts/arm/st/l1/stm32l1.dtsi | 2 ++ dts/arm/st/l4/stm32l4.dtsi | 2 ++ dts/arm/st/l5/stm32l5.dtsi | 2 ++ dts/arm/st/u5/stm32u5.dtsi | 2 ++ dts/arm/st/wb/stm32wb.dtsi | 2 ++ dts/arm/st/wba/stm32wba.dtsi | 3 ++- dts/arm/st/wl/stm32wl.dtsi | 3 ++- 18 files changed, 35 insertions(+), 4 deletions(-) diff --git a/dts/arm/st/c0/stm32c0.dtsi b/dts/arm/st/c0/stm32c0.dtsi index fd37b14b5f93b0..39ea370bdfbfe1 100644 --- a/dts/arm/st/c0/stm32c0.dtsi +++ b/dts/arm/st/c0/stm32c0.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Benjamin Björnsson + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -154,6 +155,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <1>; status = "disabled"; }; diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index 0371ac75ac6e10..ba44fb6246f957 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 RnDity Sp. z o.o. * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -210,6 +211,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; interrupts = <2 0>; prescaler = <32768>; + alarms-count = <1>; status = "disabled"; }; diff --git a/dts/arm/st/f2/stm32f2.dtsi b/dts/arm/st/f2/stm32f2.dtsi index 9c913756919841..eeb1d8e0284852 100644 --- a/dts/arm/st/f2/stm32f2.dtsi +++ b/dts/arm/st/f2/stm32f2.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 qianfan Zhao * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -202,6 +203,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; interrupts = <41 0>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index 725ed0eacb622b..c17eaa5d9d4fbd 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 I-SENSE group of ICCS * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -410,6 +411,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; interrupts = <41 0>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/f4/stm32f4.dtsi b/dts/arm/st/f4/stm32f4.dtsi index 231c8b988f886f..686b84e302c1a3 100644 --- a/dts/arm/st/f4/stm32f4.dtsi +++ b/dts/arm/st/f4/stm32f4.dtsi @@ -2,6 +2,7 @@ * Copyright (c) 2017 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc * Copyright (c) 2022 Valerio Setti + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -515,6 +516,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index 600f959b4fd85b..78b3ea42d52165 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 Yurii Hamann * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -724,6 +725,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index bfa023d027d3e1..6e4c7992f12d6f 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -1,6 +1,6 @@ /* * Copyright (c) 2019 Philippe Retornaz - * Copyright (c) 2019 ST Microelectronics + * Copyright (c) 2019-2024 STMicroelectronics * Copyright (c) 2019 Centaur Analytics, Inc * Copyright (C) 2020 Framework Computer LLC * Copyright (c) 2021 G-Technologies Sdn. Bhd. @@ -189,6 +189,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 1450efbee38351..cf9caddc327e90 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2019 Richard Osterloh + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -598,6 +599,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index cd19d329e60f4c..13a11ea7ac9e5a 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -308,6 +308,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index f3a24e2718fc80..7e7db46ccf0d44 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -2,6 +2,7 @@ * Copyright (c) 2019 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc * Copyright (c) 2020 Teslabs Engineering S.L. + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -352,6 +353,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index 91d290d0d08076..ad01e090173382 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -97,6 +97,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/l1/stm32l1.dtsi b/dts/arm/st/l1/stm32l1.dtsi index 1f6f0644819ccd..ac1161a946234a 100644 --- a/dts/arm/st/l1/stm32l1.dtsi +++ b/dts/arm/st/l1/stm32l1.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Linaro Ltd. * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -118,6 +119,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index 7dcabdf877cd7c..869652f8868372 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -380,6 +381,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index f9c37b33cd8c5e..673019120f0d33 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2020 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -460,6 +461,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index bd9bb445858d1b..642431a52ecaef 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -2,6 +2,7 @@ * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2021 Linaro Limited * Copyright (c) 2023 PSICONTROL nv + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -475,6 +476,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index d76f2f243f7435..0addc69cd095c3 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -285,6 +286,7 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi index 38a76023cfc43a..05efb0a9431e18 100644 --- a/dts/arm/st/wba/stm32wba.dtsi +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -212,6 +212,7 @@ reg = <0x46007800 0x400>; interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00200000>; + alarms-count = <2>; status = "disabled"; }; diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 5e69ef4f3b7866..ac2098ca4c1e1e 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 STMicroelectronics + * Copyright (c) 2020-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -206,6 +206,7 @@ interrupts = <42 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; /* In STM32WL, the backup registers are defined as part of the TAMP From 6c73eeb87aa34d20d6d758a471085beaac03b18d Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0502/1389] dts: bindings: rtc: stm32-rtc: add alrm-exti-line property Gives number of the Extended Interrupts and Event Controller (EXTI) interrupt line connected to the RTC Alarm event. Used on all series, except WBAX & U5X, where RTC Alarm interrupt is routed directly to Nested Vectored Interrupt Controller (NVIC) and to Power Control (PWR) wake-up pins. Signed-off-by: Abderrahmane Jarmouni --- dts/bindings/rtc/st,stm32-rtc.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dts/bindings/rtc/st,stm32-rtc.yaml b/dts/bindings/rtc/st,stm32-rtc.yaml index 7cb3343269b2d5..d368410b6ee6e3 100644 --- a/dts/bindings/rtc/st,stm32-rtc.yaml +++ b/dts/bindings/rtc/st,stm32-rtc.yaml @@ -27,3 +27,13 @@ properties: Number of alarms supported by STM32 RTC device. Most of STM32 MCU series have 2 RTC alarms, A & B. Defaults to 0 when not declared in devicetree. + + alrm-exti-line: + type: int + description: | + Number of the Extended Interrupts and Event Controller (EXTI) interrupt + line connected to the RTC Alarm event. + Not required, since RTC Alarm interrupt could be routed directly to Nested + Vectored Interrupt Controller (NVIC) and to Power Control (PWR) wake-up + pins on some series. + Valid range: 0 - 31 From d5a4ef5d97d975199360a32dabc9d606a747ef30 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0503/1389] dts: arm: st: stm32-rtc: add alrm-exti-line property Add alrm-exti-line to STM32 RTC node of concerned series. Signed-off-by: Abderrahmane Jarmouni --- dts/arm/st/c0/stm32c0.dtsi | 1 + dts/arm/st/f0/stm32f0.dtsi | 1 + dts/arm/st/f2/stm32f2.dtsi | 1 + dts/arm/st/f3/stm32f3.dtsi | 1 + dts/arm/st/f4/stm32f4.dtsi | 1 + dts/arm/st/f7/stm32f7.dtsi | 1 + dts/arm/st/g0/stm32g0.dtsi | 1 + dts/arm/st/g4/stm32g4.dtsi | 1 + dts/arm/st/h5/stm32h5.dtsi | 1 + dts/arm/st/h7/stm32h7.dtsi | 1 + dts/arm/st/l0/stm32l0.dtsi | 1 + dts/arm/st/l1/stm32l1.dtsi | 1 + dts/arm/st/l4/stm32l4.dtsi | 1 + dts/arm/st/l5/stm32l5.dtsi | 1 + dts/arm/st/wb/stm32wb.dtsi | 1 + dts/arm/st/wl/stm32wl.dtsi | 1 + 16 files changed, 16 insertions(+) diff --git a/dts/arm/st/c0/stm32c0.dtsi b/dts/arm/st/c0/stm32c0.dtsi index 39ea370bdfbfe1..f7e58c7b699193 100644 --- a/dts/arm/st/c0/stm32c0.dtsi +++ b/dts/arm/st/c0/stm32c0.dtsi @@ -156,6 +156,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; alarms-count = <1>; + alrm-exti-line = <19>; status = "disabled"; }; diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index ba44fb6246f957..5f25181e6578a7 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -212,6 +212,7 @@ interrupts = <2 0>; prescaler = <32768>; alarms-count = <1>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/f2/stm32f2.dtsi b/dts/arm/st/f2/stm32f2.dtsi index eeb1d8e0284852..8af21aaa468040 100644 --- a/dts/arm/st/f2/stm32f2.dtsi +++ b/dts/arm/st/f2/stm32f2.dtsi @@ -204,6 +204,7 @@ interrupts = <41 0>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index c17eaa5d9d4fbd..07ed6f9dc2606e 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -412,6 +412,7 @@ interrupts = <41 0>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/f4/stm32f4.dtsi b/dts/arm/st/f4/stm32f4.dtsi index 686b84e302c1a3..b69d32d6cf3019 100644 --- a/dts/arm/st/f4/stm32f4.dtsi +++ b/dts/arm/st/f4/stm32f4.dtsi @@ -517,6 +517,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index 78b3ea42d52165..a20419f001d36d 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -726,6 +726,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index 6e4c7992f12d6f..89c6944e6a42f0 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -190,6 +190,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <19>; status = "disabled"; }; diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index cf9caddc327e90..8cba3a5802153e 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -600,6 +600,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 13a11ea7ac9e5a..64a2ac37fee40b 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -309,6 +309,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 7e7db46ccf0d44..c9b8d5e4f968d1 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -354,6 +354,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index ad01e090173382..f515f9c3166bf1 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -98,6 +98,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/l1/stm32l1.dtsi b/dts/arm/st/l1/stm32l1.dtsi index ac1161a946234a..3816489f42ffc7 100644 --- a/dts/arm/st/l1/stm32l1.dtsi +++ b/dts/arm/st/l1/stm32l1.dtsi @@ -120,6 +120,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index 869652f8868372..e6e87879b95a41 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -382,6 +382,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <18>; status = "disabled"; }; diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index 673019120f0d33..d4f7a7f000b0a4 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -462,6 +462,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index 0addc69cd095c3..acd8d3c0fd89fe 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -287,6 +287,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index ac2098ca4c1e1e..a6611b8ef1b226 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -207,6 +207,7 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; /* In STM32WL, the backup registers are defined as part of the TAMP From 6a3ec3fc3c4da08fd557dc474c23a4d44bd62199 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0504/1389] drivers: rtc_stm32: add support for alarms A & B Add support for STM32 RTC Alarms A & B for all series except F1X. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 599 ++++++++++++++++++++++++++++++++++++- drivers/rtc/rtc_ll_stm32.h | 49 +++ 2 files changed, 646 insertions(+), 2 deletions(-) create mode 100644 drivers/rtc/rtc_ll_stm32.h diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index cecd7ca9a25c86..fee7ef1e618186 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2023 Prevas A/S * Copyright (c) 2023 Syslinbit + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 * @@ -22,10 +23,19 @@ #include #include #include +#ifdef CONFIG_RTC_ALARM +#include +#endif /* CONFIG_RTC_ALARM */ #include +#ifdef CONFIG_RTC_ALARM +#include +#endif /* CONFIG_RTC_ALARM */ #include +#include "rtc_utils.h" + +#include "rtc_ll_stm32.h" LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); @@ -67,6 +77,36 @@ LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); /* Timeout in microseconds used to wait for flags */ #define RTC_TIMEOUT 1000000 +#ifdef CONFIG_RTC_ALARM +#define RTC_STM32_ALARMS_COUNT DT_INST_PROP(0, alarms_count) + +#define RTC_STM32_ALRM_A 0U +#define RTC_STM32_ALRM_B 1U + +/* Zephyr mask supported by RTC device, values from RTC_ALARM_TIME_MASK */ +#define RTC_STM32_SUPPORTED_ALARM_FIELDS \ + (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE \ + | RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_WEEKDAY \ + | RTC_ALARM_TIME_MASK_MONTHDAY) + +#if DT_INST_NODE_HAS_PROP(0, alrm_exti_line) +#define RTC_STM32_EXTI_LINE CONCAT(LL_EXTI_LINE_, DT_INST_PROP(0, alrm_exti_line)) +#else +#define RTC_STM32_EXTI_LINE 0 +#endif /* DT_INST_NODE_HAS_PROP(0, alrm_exti_line) */ +#endif /* CONFIG_RTC_ALARM */ + +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +/* + * After system reset, the RTC registers are protected against parasitic write access by the + * DBP bit in the power control peripheral (PWR). + * Hence, DBP bit must be set in order to enable RTC registers write access. + */ +#define RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION (1) +#else +#define RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION (0) +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPCR_DBP || PWR_DBPR_DBP */ + struct rtc_stm32_config { uint32_t async_prescaler; uint32_t sync_prescaler; @@ -76,8 +116,23 @@ struct rtc_stm32_config { #endif }; +#ifdef CONFIG_RTC_ALARM +struct rtc_stm32_alrm { + LL_RTC_AlarmTypeDef ll_rtc_alrm; + /* user-defined alarm mask, values from RTC_ALARM_TIME_MASK */ + uint16_t user_mask; + rtc_alarm_callback user_callback; + void *user_data; + bool is_pending; +}; +#endif /* CONFIG_RTC_ALARM */ + struct rtc_stm32_data { struct k_mutex lock; +#ifdef CONFIG_RTC_ALARM + struct rtc_stm32_alrm rtc_alrm_a; + struct rtc_stm32_alrm rtc_alrm_b; +#endif /* CONFIG_RTC_ALARM */ }; static int rtc_stm32_configure(const struct device *dev) @@ -126,6 +181,149 @@ static int rtc_stm32_configure(const struct device *dev) return err; } +#ifdef CONFIG_RTC_ALARM +static inline ErrorStatus rtc_stm32_init_alarm(RTC_TypeDef *rtc, uint32_t format, + LL_RTC_AlarmTypeDef *ll_alarm_struct, uint16_t id) +{ + ll_alarm_struct->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE; + /* RTC write protection is disabled & enabled again inside LL_RTC_ALMx_Init functions */ + if (id == RTC_STM32_ALRM_A) { + return LL_RTC_ALMA_Init(rtc, format, ll_alarm_struct); + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + return LL_RTC_ALMB_Init(rtc, format, ll_alarm_struct); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + + return 0; +} + +static inline void rtc_stm32_clear_alarm_flag(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_ClearFlag_ALRA(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_ClearFlag_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline uint32_t rtc_stm32_is_active_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + return LL_RTC_IsActiveFlag_ALRA(rtc); + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + return LL_RTC_IsActiveFlag_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + + return 0; +} + +static inline void rtc_stm32_enable_interrupt_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_EnableIT_ALRA(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_EnableIT_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline void rtc_stm32_disable_interrupt_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_DisableIT_ALRA(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_DisableIT_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline void rtc_stm32_enable_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_ALMA_Enable(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_ALMB_Enable(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline void rtc_stm32_disable_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_ALMA_Disable(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_ALMB_Disable(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +void rtc_stm32_isr(const struct device *dev) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + int id = 0; + +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_EnableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + for (id = 0; id < RTC_STM32_ALARMS_COUNT; id++) { + if (rtc_stm32_is_active_alarm(RTC, (uint16_t)id) != 0) { + LL_RTC_DisableWriteProtection(RTC); + rtc_stm32_clear_alarm_flag(RTC, (uint16_t)id); + LL_RTC_EnableWriteProtection(RTC); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else { + p_rtc_alrm = &(data->rtc_alrm_b); + } + + p_rtc_alrm->is_pending = true; + + if (p_rtc_alrm->user_callback != NULL) { + p_rtc_alrm->user_callback(dev, (uint16_t)id, p_rtc_alrm->user_data); + } + } + } + +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_DisableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + ll_func_exti_clear_rtc_alarm_flag(RTC_STM32_EXTI_LINE); +} + +static void rtc_stm32_irq_config(const struct device *dev) +{ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + rtc_stm32_isr, DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +} +#endif /* CONFIG_RTC_ALARM */ + static int rtc_stm32_init(const struct device *dev) { const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); @@ -170,6 +368,17 @@ static int rtc_stm32_init(const struct device *dev) LL_PWR_DisableBkUpAccess(); #endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#ifdef CONFIG_RTC_ALARM + rtc_stm32_irq_config(dev); + + ll_func_exti_enable_rtc_alarm_it(RTC_STM32_EXTI_LINE); + + k_mutex_lock(&data->lock, K_FOREVER); + memset(&(data->rtc_alrm_a), 0, sizeof(struct rtc_stm32_alrm)); + memset(&(data->rtc_alrm_b), 0, sizeof(struct rtc_stm32_alrm)); + k_mutex_unlock(&data->lock); +#endif /* CONFIG_RTC_ALARM */ + return err; } @@ -327,6 +536,387 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr return 0; } +#ifdef CONFIG_RTC_ALARM +static void rtc_stm32_init_ll_alrm_struct(LL_RTC_AlarmTypeDef *p_rtc_alarm, + const struct rtc_time *timeptr, uint16_t mask) +{ + LL_RTC_TimeTypeDef *p_rtc_alrm_time = &(p_rtc_alarm->AlarmTime); + uint32_t ll_mask = 0; + + /* + * STM32 RTC Alarm LL mask should be set for all fields beyond the broadest one + * that's being matched with RTC calendar to trigger alarm periodically, + * the opposite of Zephyr RTC Alarm mask which is set for active fields. + */ + ll_mask = RTC_STM32_ALRM_MASK_ALL; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + ll_mask &= ~RTC_STM32_ALRM_MASK_SECONDS; + p_rtc_alrm_time->Seconds = bin2bcd(timeptr->tm_sec); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + ll_mask &= ~RTC_STM32_ALRM_MASK_MINUTES; + p_rtc_alrm_time->Minutes = bin2bcd(timeptr->tm_min); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + ll_mask &= ~RTC_STM32_ALRM_MASK_HOURS; + p_rtc_alrm_time->Hours = bin2bcd(timeptr->tm_hour); + } + + if (mask & RTC_ALARM_TIME_MASK_WEEKDAY) { + /* the Alarm Mask field compares with the day of the week */ + ll_mask &= ~RTC_STM32_ALRM_MASK_DATEWEEKDAY; + p_rtc_alarm->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_WEEKDAY; + + if (timeptr->tm_wday == 0) { + /* sunday (tm_wday = 0) is not represented by the same value in hardware */ + p_rtc_alarm->AlarmDateWeekDay = LL_RTC_WEEKDAY_SUNDAY; + } else { + /* all the other values are consistent with what is expected by hardware */ + p_rtc_alarm->AlarmDateWeekDay = bin2bcd(timeptr->tm_wday); + } + + } else if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + /* the Alarm compares with the day number & ignores the day of the week */ + ll_mask &= ~RTC_STM32_ALRM_MASK_DATEWEEKDAY; + p_rtc_alarm->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE; + p_rtc_alarm->AlarmDateWeekDay = bin2bcd(timeptr->tm_mday); + } + + p_rtc_alrm_time->TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24; + + p_rtc_alarm->AlarmMask = ll_mask; +} + +static inline void rtc_stm32_get_ll_alrm_time(uint16_t id, struct rtc_time *timeptr) +{ + if (id == RTC_STM32_ALRM_A) { + timeptr->tm_sec = bcd2bin(LL_RTC_ALMA_GetSecond(RTC)); + timeptr->tm_min = bcd2bin(LL_RTC_ALMA_GetMinute(RTC)); + timeptr->tm_hour = bcd2bin(LL_RTC_ALMA_GetHour(RTC)); + timeptr->tm_wday = bcd2bin(LL_RTC_ALMA_GetWeekDay(RTC)); + timeptr->tm_mday = bcd2bin(LL_RTC_ALMA_GetDay(RTC)); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + timeptr->tm_sec = bcd2bin(LL_RTC_ALMB_GetSecond(RTC)); + timeptr->tm_min = bcd2bin(LL_RTC_ALMB_GetMinute(RTC)); + timeptr->tm_hour = bcd2bin(LL_RTC_ALMB_GetHour(RTC)); + timeptr->tm_wday = bcd2bin(LL_RTC_ALMB_GetWeekDay(RTC)); + timeptr->tm_mday = bcd2bin(LL_RTC_ALMB_GetDay(RTC)); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline uint16_t rtc_stm32_get_ll_alrm_mask(uint16_t id) +{ + uint32_t ll_alarm_mask = 0; + uint16_t zephyr_alarm_mask = 0; + uint32_t week_day = 0; + + /* + * STM32 RTC Alarm LL mask is set for all fields beyond the broadest one + * that's being matched with RTC calendar to trigger alarm periodically, + * the opposite of Zephyr RTC Alarm mask which is set for active fields. + */ + + if (id == RTC_STM32_ALRM_A) { + ll_alarm_mask = LL_RTC_ALMA_GetMask(RTC); + } + +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + ll_alarm_mask = LL_RTC_ALMB_GetMask(RTC); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_SECONDS) == 0x0) { + zephyr_alarm_mask = RTC_ALARM_TIME_MASK_SECOND; + } + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_MINUTES) == 0x0) { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_HOURS) == 0x0) { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_HOUR; + } + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_DATEWEEKDAY) == 0x0) { + if (id == RTC_STM32_ALRM_A) { + week_day = LL_RTC_ALMA_GetWeekDay(RTC); + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + week_day = LL_RTC_ALMB_GetWeekDay(RTC); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + if (week_day) { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_WEEKDAY; + } else { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + } + + return zephyr_alarm_mask; +} + +static int rtc_stm32_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + if (mask == NULL) { + LOG_ERR("NULL mask pointer"); + return -EINVAL; + } + + if ((id != RTC_STM32_ALRM_A) && (id != RTC_STM32_ALRM_B)) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + *mask = (uint16_t)RTC_STM32_SUPPORTED_ALARM_FIELDS; + + return 0; +} + +static int rtc_stm32_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + LL_RTC_AlarmTypeDef *p_ll_rtc_alarm; + LL_RTC_TimeTypeDef *p_ll_rtc_alrm_time; + int err = 0; + + if ((mask == NULL) || (timeptr == NULL)) { + LOG_ERR("NULL pointer"); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + err = -EINVAL; + goto unlock; + } + + p_ll_rtc_alarm = &(p_rtc_alrm->ll_rtc_alrm); + p_ll_rtc_alrm_time = &(p_ll_rtc_alarm->AlarmTime); + + memset(timeptr, -1, sizeof(struct rtc_time)); + + rtc_stm32_get_ll_alrm_time(id, timeptr); + + p_rtc_alrm->user_mask = rtc_stm32_get_ll_alrm_mask(id); + + *mask = p_rtc_alrm->user_mask; + + LOG_DBG("get alarm: mday = %d, wday = %d, hour = %d, min = %d, sec = %d, " + "mask = 0x%04x", timeptr->tm_mday, timeptr->tm_wday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, *mask); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + LL_RTC_AlarmTypeDef *p_ll_rtc_alarm; + LL_RTC_TimeTypeDef *p_ll_rtc_alrm_time; + int err = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + err = -EINVAL; + goto unlock; + } + + if ((mask == 0) && (timeptr == NULL)) { + memset(&(p_rtc_alrm->ll_rtc_alrm), 0, sizeof(LL_RTC_AlarmTypeDef)); + p_rtc_alrm->user_callback = NULL; + p_rtc_alrm->user_data = NULL; + p_rtc_alrm->is_pending = false; +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_EnableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + if (rtc_stm32_is_active_alarm(RTC, id)) { + LL_RTC_DisableWriteProtection(RTC); + rtc_stm32_disable_alarm(RTC, id); + LL_RTC_EnableWriteProtection(RTC); + } + LOG_DBG("Alarm %d has been disabled", id); + goto disable_bkup_access; + } + + if ((mask & ~RTC_STM32_SUPPORTED_ALARM_FIELDS) != 0) { + LOG_ERR("unsupported alarm %d field mask 0x%04x", id, mask); + err = -EINVAL; + goto unlock; + } + + if (timeptr == NULL) { + LOG_ERR("timeptr is invalid"); + err = -EINVAL; + goto unlock; + } + + if (!rtc_utils_validate_rtc_time(timeptr, mask)) { + LOG_DBG("One or multiple time values are invalid"); + err = -EINVAL; + goto unlock; + } + + p_ll_rtc_alarm = &(p_rtc_alrm->ll_rtc_alrm); + p_ll_rtc_alrm_time = &(p_ll_rtc_alarm->AlarmTime); + + memset(p_ll_rtc_alrm_time, 0, sizeof(LL_RTC_TimeTypeDef)); + rtc_stm32_init_ll_alrm_struct(p_ll_rtc_alarm, timeptr, mask); + + p_rtc_alrm->user_mask = mask; + + LOG_DBG("set alarm: second = %d, min = %d, hour = %d," + "wday = %d, mday = %d, mask = 0x%04x", + timeptr->tm_sec, timeptr->tm_min, timeptr->tm_hour, + timeptr->tm_wday, timeptr->tm_mday, mask); + +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_EnableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTC); + + if (rtc_stm32_is_active_alarm(RTC, id)) { + /* Disable Alarm if already active */ + rtc_stm32_disable_alarm(RTC, id); + } + +#ifdef RTC_ISR_ALRAWF + if (id == RTC_STM32_ALRM_A) { + /* Wait till RTC ALRAWF flag is set before writing to RTC registers */ + while ((LL_RTC_ReadReg(RTC, ISR) & RTC_ISR_ALRAWF) == 0U) { + ; + } + } +#endif /* RTC_ISR_ALRAWF */ + +#ifdef RTC_ISR_ALRBWF + if (id == RTC_STM32_ALRM_B) { + /* Wait till RTC ALRBWF flag is set before writing to RTC registers */ + while ((LL_RTC_ReadReg(RTC, ISR) & RTC_ISR_ALRBWF) == 0U) { + ; + } + } +#endif /* RTC_ISR_ALRBWF */ + + /* init Alarm */ + /* write protection is disabled & enabled again inside the LL_RTC_ALMx_Init function */ + if (rtc_stm32_init_alarm(RTC, LL_RTC_FORMAT_BCD, p_ll_rtc_alarm, id) != SUCCESS) { + LOG_ERR("Could not initialize Alarm %d", id); + err = -ECANCELED; + goto disable_bkup_access; + } + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTC); + + /* Enable Alarm */ + rtc_stm32_enable_alarm(RTC, id); + /* Clear Alarm flag */ + rtc_stm32_clear_alarm_flag(RTC, id); + /* Enable Alarm IT */ + rtc_stm32_enable_interrupt_alarm(RTC, id); + + ll_func_exti_enable_rtc_alarm_it(RTC_STM32_EXTI_LINE); + + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTC); + +disable_bkup_access: +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_DisableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int rtc_stm32_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + int err = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + err = -EINVAL; + goto unlock; + } + + /* Passing the callback function and userdata filled by the user */ + p_rtc_alrm->user_callback = callback; + p_rtc_alrm->user_data = user_data; + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int rtc_stm32_alarm_is_pending(const struct device *dev, uint16_t id) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + int ret = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + ret = -EINVAL; + goto unlock; + } + + __disable_irq(); + ret = p_rtc_alrm->is_pending ? 1 : 0; + p_rtc_alrm->is_pending = false; + __enable_irq(); + +unlock: + k_mutex_unlock(&data->lock); + return ret; +} +#endif /* CONFIG_RTC_ALARM */ + #ifdef CONFIG_RTC_CALIBRATION #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT)) @@ -408,8 +998,13 @@ static int rtc_stm32_get_calibration(const struct device *dev, int32_t *calibrat static const struct rtc_driver_api rtc_stm32_driver_api = { .set_time = rtc_stm32_set_time, .get_time = rtc_stm32_get_time, - /* RTC_ALARM not supported */ - /* RTC_UPDATE not supported */ +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rtc_stm32_alarm_get_supported_fields, + .alarm_set_time = rtc_stm32_alarm_set_time, + .alarm_get_time = rtc_stm32_alarm_get_time, + .alarm_set_callback = rtc_stm32_alarm_set_callback, + .alarm_is_pending = rtc_stm32_alarm_is_pending, +#endif /* CONFIG_RTC_ALARM */ #ifdef CONFIG_RTC_CALIBRATION #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT)) diff --git a/drivers/rtc/rtc_ll_stm32.h b/drivers/rtc/rtc_ll_stm32.h new file mode 100644 index 00000000000000..16f381081c174f --- /dev/null +++ b/drivers/rtc/rtc_ll_stm32.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_RTC_RTC_LL_STM32_H_ +#define ZEPHYR_DRIVERS_RTC_RTC_LL_STM32_H_ + +#ifdef CONFIG_RTC_ALARM + +/* STM32 RTC alarms, A & B, LL masks are equal */ +#define RTC_STM32_ALRM_MASK_ALL LL_RTC_ALMA_MASK_ALL +#define RTC_STM32_ALRM_MASK_SECONDS LL_RTC_ALMA_MASK_SECONDS +#define RTC_STM32_ALRM_MASK_MINUTES LL_RTC_ALMA_MASK_MINUTES +#define RTC_STM32_ALRM_MASK_HOURS LL_RTC_ALMA_MASK_HOURS +#define RTC_STM32_ALRM_MASK_DATEWEEKDAY LL_RTC_ALMA_MASK_DATEWEEKDAY + +#define RTC_STM32_ALRM_DATEWEEKDAYSEL_WEEKDAY LL_RTC_ALMA_DATEWEEKDAYSEL_WEEKDAY +#define RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE LL_RTC_ALMA_DATEWEEKDAYSEL_DATE + +static inline void ll_func_exti_enable_rtc_alarm_it(uint32_t exti_line) +{ +#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) + LL_C2_EXTI_EnableIT_0_31(exti_line); + LL_EXTI_EnableRisingTrig_0_31(exti_line); +#elif defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) + /* in STM32U5 & STM32WBAX series, RTC Alarm event is not routed to EXTI */ +#else + LL_EXTI_EnableIT_0_31(exti_line); + LL_EXTI_EnableRisingTrig_0_31(exti_line); +#endif /* CONFIG_SOC_SERIES_STM32H7X and CONFIG_CPU_CORTEX_M4 */ +} + +static inline void ll_func_exti_clear_rtc_alarm_flag(uint32_t exti_line) +{ +#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) + LL_C2_EXTI_ClearFlag_0_31(exti_line); +#elif defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) + /* in STM32U5 & STM32WBAX series, RTC Alarm event is not routed to EXTI */ +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) + LL_EXTI_ClearRisingFlag_0_31(exti_line); +#else + LL_EXTI_ClearFlag_0_31(exti_line); +#endif /* CONFIG_SOC_SERIES_STM32H7X and CONFIG_CPU_CORTEX_M4 */ +} +#endif /* CONFIG_RTC_ALARM */ + +#endif /* ZEPHYR_DRIVERS_RTC_RTC_LL_STM32_H_ */ From 5c53b5b97fe3a9dd042b291ca2d1ac959dc45001 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0505/1389] drivers: rtc: stm32: fix clk enable call On STM32WBAX series, there is no bit in BCDR register to enable RTC. Enabling RTC is done directly via the RCC APB register bit. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index fee7ef1e618186..3ed8f9fdf9284a 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -356,11 +356,17 @@ static int rtc_stm32_init(const struct device *dev) return -EIO; } +/* + * On STM32WBAX series, there is no bit in BCDR register to enable RTC. + * Enabling RTC is done directly via the RCC APB register bit. + */ +#ifndef CONFIG_SOC_SERIES_STM32WBAX z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); LL_RCC_EnableRTC(); z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); +#endif /* CONFIG_SOC_SERIES_STM32WBAX */ err = rtc_stm32_configure(dev); From 217ca51bdb8706a36bf9bdf6032755888846691a Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0506/1389] boards: st: configure STM32 RTC Configure STM32 RTC for a large selction of boards. Signed-off-by: Abderrahmane Jarmouni --- boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi | 7 +++++++ boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml | 1 + boards/st/b_u585i_iot02a/doc/index.rst | 2 ++ boards/st/disco_l475_iot1/disco_l475_iot1.yaml | 1 + boards/st/disco_l475_iot1/doc/index.rst | 2 ++ boards/st/nucleo_c031c6/doc/index.rst | 2 ++ boards/st/nucleo_c031c6/nucleo_c031c6.yaml | 1 + boards/st/nucleo_f070rb/doc/index.rst | 2 ++ boards/st/nucleo_f070rb/nucleo_f070rb.dts | 11 +++++++++++ boards/st/nucleo_f070rb/nucleo_f070rb.yaml | 1 + boards/st/nucleo_f091rc/doc/index.rst | 2 ++ boards/st/nucleo_f091rc/nucleo_f091rc.yaml | 1 + boards/st/nucleo_f207zg/doc/index.rst | 2 ++ boards/st/nucleo_f207zg/nucleo_f207zg.yaml | 1 + boards/st/nucleo_f401re/doc/index.rst | 2 ++ boards/st/nucleo_f401re/nucleo_f401re.yaml | 1 + boards/st/nucleo_f429zi/doc/index.rst | 2 ++ boards/st/nucleo_f429zi/nucleo_f429zi.yaml | 1 + boards/st/nucleo_f722ze/doc/index.rst | 2 ++ boards/st/nucleo_f722ze/nucleo_f722ze.dts | 5 +++++ boards/st/nucleo_f722ze/nucleo_f722ze.yaml | 1 + boards/st/nucleo_f746zg/doc/index.rst | 2 ++ boards/st/nucleo_f746zg/nucleo_f746zg.yaml | 1 + boards/st/nucleo_f767zi/doc/index.rst | 2 ++ boards/st/nucleo_f767zi/nucleo_f767zi.yaml | 1 + boards/st/nucleo_g071rb/doc/index.rst | 2 ++ boards/st/nucleo_g071rb/nucleo_g071rb.yaml | 1 + boards/st/nucleo_g474re/doc/index.rst | 2 ++ boards/st/nucleo_g474re/nucleo_g474re.yaml | 1 + boards/st/nucleo_h723zg/doc/index.rst | 2 ++ boards/st/nucleo_h723zg/nucleo_h723zg.yaml | 1 + boards/st/nucleo_h743zi/doc/index.rst | 2 ++ boards/st/nucleo_h743zi/nucleo_h743zi.yaml | 1 + boards/st/nucleo_l073rz/doc/index.rst | 2 ++ boards/st/nucleo_l073rz/nucleo_l073rz.dts | 7 +++++++ boards/st/nucleo_l073rz/nucleo_l073rz.yaml | 1 + boards/st/nucleo_l152re/doc/index.rst | 2 ++ boards/st/nucleo_l152re/nucleo_l152re.yaml | 1 + boards/st/nucleo_l4r5zi/doc/index.rst | 2 ++ boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml | 1 + boards/st/nucleo_u575zi_q/doc/index.rst | 2 ++ .../st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi | 7 +++++++ boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml | 1 + boards/st/nucleo_u5a5zj_q/doc/index.rst | 2 ++ .../st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi | 8 +++++++- boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml | 1 + boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst | 2 ++ boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml | 1 + boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst | 2 ++ boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml | 1 + boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst | 2 ++ boards/st/nucleo_wl55jc/nucleo_wl55jc.dts | 12 +++++++++++- boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml | 1 + boards/st/stm32f3_disco/doc/index.rst | 2 ++ boards/st/stm32f3_disco/stm32f3_disco_B.yaml | 1 + .../stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml | 1 + boards/st/stm32h573i_dk/doc/index.rst | 2 ++ boards/st/stm32h573i_dk/stm32h573i_dk.yaml | 1 + boards/st/stm32h750b_dk/doc/index.rst | 4 ++++ boards/st/stm32h750b_dk/stm32h750b_dk.dts | 12 +++++++++++- boards/st/stm32h750b_dk/stm32h750b_dk.yaml | 2 ++ boards/st/stm32u5a9j_dk/doc/index.rst | 2 ++ boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts | 12 +++++++++++- boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml | 1 + 64 files changed, 162 insertions(+), 4 deletions(-) diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi b/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi index 7912aa33deb4bf..97fe4e0be57b7d 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -246,6 +247,12 @@ zephyr_udc0: &usbotg_fs { status = "okay"; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &iwdg { status = "okay"; }; diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml b/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml index 27ba601cae56db..ef3e9b0a210a1c 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml @@ -23,4 +23,5 @@ supported: - pwm - counter - i2c + - rtc vendor: st diff --git a/boards/st/b_u585i_iot02a/doc/index.rst b/boards/st/b_u585i_iot02a/doc/index.rst index 166d2ac390736a..0631b5b1ada943 100644 --- a/boards/st/b_u585i_iot02a/doc/index.rst +++ b/boards/st/b_u585i_iot02a/doc/index.rst @@ -197,6 +197,8 @@ The Zephyr b_u585i_iot02a board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | RADIO | STM32WB5MMG| Bluetooth Low Energy (BLE) | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ The default configuration can be found in the defconfig file: :zephyr_file:`boards/st/b_u585i_iot02a/b_u585i_iot02a_defconfig` diff --git a/boards/st/disco_l475_iot1/disco_l475_iot1.yaml b/boards/st/disco_l475_iot1/disco_l475_iot1.yaml index ca90da9607a00c..6600d0724a8558 100644 --- a/boards/st/disco_l475_iot1/disco_l475_iot1.yaml +++ b/boards/st/disco_l475_iot1/disco_l475_iot1.yaml @@ -25,6 +25,7 @@ supported: - dac - qspi - dma + - rtc ram: 96 flash: 1024 vendor: st diff --git a/boards/st/disco_l475_iot1/doc/index.rst b/boards/st/disco_l475_iot1/doc/index.rst index dc49d4fcb2d68a..63ccdd9582eacf 100644 --- a/boards/st/disco_l475_iot1/doc/index.rst +++ b/boards/st/disco_l475_iot1/doc/index.rst @@ -131,6 +131,8 @@ The Zephyr Disco L475 IoT board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_c031c6/doc/index.rst b/boards/st/nucleo_c031c6/doc/index.rst index 8ed5a7edfeae32..8f44ab9d3079ba 100644 --- a/boards/st/nucleo_c031c6/doc/index.rst +++ b/boards/st/nucleo_c031c6/doc/index.rst @@ -90,6 +90,8 @@ The Zephyr nucleo_c031c6 board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | DMA | on-chip | Direct Memory Access | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_c031c6/nucleo_c031c6.yaml b/boards/st/nucleo_c031c6/nucleo_c031c6.yaml index c4766287cc564a..7f311f93c489ab 100644 --- a/boards/st/nucleo_c031c6/nucleo_c031c6.yaml +++ b/boards/st/nucleo_c031c6/nucleo_c031c6.yaml @@ -14,6 +14,7 @@ supported: - adc - i2c - dma + - rtc ram: 12 flash: 32 vendor: st diff --git a/boards/st/nucleo_f070rb/doc/index.rst b/boards/st/nucleo_f070rb/doc/index.rst index 5e6544e9cfb768..e8d9f40a77b371 100644 --- a/boards/st/nucleo_f070rb/doc/index.rst +++ b/boards/st/nucleo_f070rb/doc/index.rst @@ -94,6 +94,8 @@ The Zephyr nucleo_f070rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | SPI | on-chip | SPI controller | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_f070rb/nucleo_f070rb.dts b/boards/st/nucleo_f070rb/nucleo_f070rb.dts index 7cd2e3bd7b6629..c504dad4de50c0 100644 --- a/boards/st/nucleo_f070rb/nucleo_f070rb.dts +++ b/boards/st/nucleo_f070rb/nucleo_f070rb.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 qianfan Zhao + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +49,10 @@ }; }; +&clk_lse { + status = "okay"; +}; + &clk_hse { hse-bypass; clock-frequency = ; /* STLink 8MHz clock */ @@ -121,6 +126,12 @@ status = "okay"; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &die_temp { status = "okay"; }; diff --git a/boards/st/nucleo_f070rb/nucleo_f070rb.yaml b/boards/st/nucleo_f070rb/nucleo_f070rb.yaml index 60af06296a94ec..5ed0d28dd3d549 100644 --- a/boards/st/nucleo_f070rb/nucleo_f070rb.yaml +++ b/boards/st/nucleo_f070rb/nucleo_f070rb.yaml @@ -18,6 +18,7 @@ supported: - i2c - spi - watchdog + - rtc testing: ignore_tags: - net diff --git a/boards/st/nucleo_f091rc/doc/index.rst b/boards/st/nucleo_f091rc/doc/index.rst index eee47f79254e14..a83b00bd82a446 100644 --- a/boards/st/nucleo_f091rc/doc/index.rst +++ b/boards/st/nucleo_f091rc/doc/index.rst @@ -108,6 +108,8 @@ The Zephyr nucleo_f091rc board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_f091rc/nucleo_f091rc.yaml b/boards/st/nucleo_f091rc/nucleo_f091rc.yaml index c19aa47d955b93..d0ac388b263a6b 100644 --- a/boards/st/nucleo_f091rc/nucleo_f091rc.yaml +++ b/boards/st/nucleo_f091rc/nucleo_f091rc.yaml @@ -23,6 +23,7 @@ supported: - dma - pwm - can + - rtc testing: ignore_tags: - net diff --git a/boards/st/nucleo_f207zg/doc/index.rst b/boards/st/nucleo_f207zg/doc/index.rst index a801f0bc1e9a60..032cf2ab85944a 100644 --- a/boards/st/nucleo_f207zg/doc/index.rst +++ b/boards/st/nucleo_f207zg/doc/index.rst @@ -108,6 +108,8 @@ The Zephyr nucleo_207zg board configuration supports the following hardware feat +-------------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_f207zg/nucleo_f207zg.yaml b/boards/st/nucleo_f207zg/nucleo_f207zg.yaml index f89510912be0f0..aeb13880f84adb 100644 --- a/boards/st/nucleo_f207zg/nucleo_f207zg.yaml +++ b/boards/st/nucleo_f207zg/nucleo_f207zg.yaml @@ -24,4 +24,5 @@ supported: - pwm - rng - dma + - rtc vendor: st diff --git a/boards/st/nucleo_f401re/doc/index.rst b/boards/st/nucleo_f401re/doc/index.rst index bd806a6378acea..4b848eb10171ea 100644 --- a/boards/st/nucleo_f401re/doc/index.rst +++ b/boards/st/nucleo_f401re/doc/index.rst @@ -87,6 +87,8 @@ The Zephyr nucleo_401re board configuration supports the following hardware feat +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. diff --git a/boards/st/nucleo_f401re/nucleo_f401re.yaml b/boards/st/nucleo_f401re/nucleo_f401re.yaml index ea1d89798c0c60..457c4295196ce3 100644 --- a/boards/st/nucleo_f401re/nucleo_f401re.yaml +++ b/boards/st/nucleo_f401re/nucleo_f401re.yaml @@ -17,6 +17,7 @@ supported: - spi - adc - watchdog + - rtc ram: 96 flash: 512 vendor: st diff --git a/boards/st/nucleo_f429zi/doc/index.rst b/boards/st/nucleo_f429zi/doc/index.rst index 9e795649a4ebfa..c15e524238b760 100644 --- a/boards/st/nucleo_f429zi/doc/index.rst +++ b/boards/st/nucleo_f429zi/doc/index.rst @@ -111,6 +111,8 @@ The Zephyr nucleo_f429zi board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_f429zi/nucleo_f429zi.yaml b/boards/st/nucleo_f429zi/nucleo_f429zi.yaml index 762ede6fb2c4b9..f8c167bc5ef4d9 100644 --- a/boards/st/nucleo_f429zi/nucleo_f429zi.yaml +++ b/boards/st/nucleo_f429zi/nucleo_f429zi.yaml @@ -24,4 +24,5 @@ supported: - dac - dma - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_f722ze/doc/index.rst b/boards/st/nucleo_f722ze/doc/index.rst index f0c40595f3a41c..83b5413040524f 100644 --- a/boards/st/nucleo_f722ze/doc/index.rst +++ b/boards/st/nucleo_f722ze/doc/index.rst @@ -115,6 +115,8 @@ Supported Features +---------------+------------+-------------------------------+ | WWDG | on-chip | watchdog | +---------------+------------+-------------------------------+ +| RTC | on-chip | rtc | ++---------------+------------+-------------------------------+ Connections and IOs =================== diff --git a/boards/st/nucleo_f722ze/nucleo_f722ze.dts b/boards/st/nucleo_f722ze/nucleo_f722ze.dts index 8a128e61e6e602..47bce02573291b 100644 --- a/boards/st/nucleo_f722ze/nucleo_f722ze.dts +++ b/boards/st/nucleo_f722ze/nucleo_f722ze.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Evan Perry Grove + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -69,6 +70,10 @@ status = "disabled"; }; +&clk_lsi { + status = "okay"; +}; + &pll { div-m = <4>; mul-n = <216>; diff --git a/boards/st/nucleo_f722ze/nucleo_f722ze.yaml b/boards/st/nucleo_f722ze/nucleo_f722ze.yaml index 94cdcb739143da..4286f55eca9a14 100644 --- a/boards/st/nucleo_f722ze/nucleo_f722ze.yaml +++ b/boards/st/nucleo_f722ze/nucleo_f722ze.yaml @@ -20,6 +20,7 @@ supported: - quadspi - spi - usb_device + - rtc ram: 256 flash: 512 vendor: st diff --git a/boards/st/nucleo_f746zg/doc/index.rst b/boards/st/nucleo_f746zg/doc/index.rst index cc1ca6d95ed714..dcbff3ca0bc37e 100644 --- a/boards/st/nucleo_f746zg/doc/index.rst +++ b/boards/st/nucleo_f746zg/doc/index.rst @@ -122,6 +122,8 @@ features: +-------------+------------+-------------------------------------+ | Backup SRAM | on-chip | Backup SRAM | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_f746zg/nucleo_f746zg.yaml b/boards/st/nucleo_f746zg/nucleo_f746zg.yaml index 015b1e3e642f10..ce8b0322fcd3ee 100644 --- a/boards/st/nucleo_f746zg/nucleo_f746zg.yaml +++ b/boards/st/nucleo_f746zg/nucleo_f746zg.yaml @@ -26,4 +26,5 @@ supported: - dac - dma - backup_sram + - rtc vendor: st diff --git a/boards/st/nucleo_f767zi/doc/index.rst b/boards/st/nucleo_f767zi/doc/index.rst index 8500f7fd3f17af..5dec0099d905ab 100644 --- a/boards/st/nucleo_f767zi/doc/index.rst +++ b/boards/st/nucleo_f767zi/doc/index.rst @@ -122,6 +122,8 @@ features: +-----------+------------+-------------------------------------+ | DAC | on-chip | DAC Controller | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ (*) nucleo_f767zi with soc cut-A (Device marking A) has some ethernet diff --git a/boards/st/nucleo_f767zi/nucleo_f767zi.yaml b/boards/st/nucleo_f767zi/nucleo_f767zi.yaml index e3be20e3780619..1ca2d19993fb7a 100644 --- a/boards/st/nucleo_f767zi/nucleo_f767zi.yaml +++ b/boards/st/nucleo_f767zi/nucleo_f767zi.yaml @@ -25,4 +25,5 @@ supported: - counter - can - dac + - rtc vendor: st diff --git a/boards/st/nucleo_g071rb/doc/index.rst b/boards/st/nucleo_g071rb/doc/index.rst index 9cc78b0f4c823d..094666250f3979 100644 --- a/boards/st/nucleo_g071rb/doc/index.rst +++ b/boards/st/nucleo_g071rb/doc/index.rst @@ -112,6 +112,8 @@ The Zephyr nucleo_g071rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_g071rb/nucleo_g071rb.yaml b/boards/st/nucleo_g071rb/nucleo_g071rb.yaml index 755196fec16978..8caf70832cded5 100644 --- a/boards/st/nucleo_g071rb/nucleo_g071rb.yaml +++ b/boards/st/nucleo_g071rb/nucleo_g071rb.yaml @@ -25,4 +25,5 @@ supported: - dma - lptim - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_g474re/doc/index.rst b/boards/st/nucleo_g474re/doc/index.rst index 9d23c072b75979..d826ce3718858f 100644 --- a/boards/st/nucleo_g474re/doc/index.rst +++ b/boards/st/nucleo_g474re/doc/index.rst @@ -129,6 +129,8 @@ The Zephyr nucleo_g474re board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | FDCAN1 | on-chip | CAN controller | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_g474re/nucleo_g474re.yaml b/boards/st/nucleo_g474re/nucleo_g474re.yaml index d473be929bfde8..26c4254294ffe8 100644 --- a/boards/st/nucleo_g474re/nucleo_g474re.yaml +++ b/boards/st/nucleo_g474re/nucleo_g474re.yaml @@ -24,4 +24,5 @@ supported: - dac - dma - can + - rtc vendor: st diff --git a/boards/st/nucleo_h723zg/doc/index.rst b/boards/st/nucleo_h723zg/doc/index.rst index 0c24a479920950..93574531dae218 100644 --- a/boards/st/nucleo_h723zg/doc/index.rst +++ b/boards/st/nucleo_h723zg/doc/index.rst @@ -115,6 +115,8 @@ features: +-------------+------------+-------------------------------------+ | Backup SRAM | on-chip | Backup SRAM | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_h723zg/nucleo_h723zg.yaml b/boards/st/nucleo_h723zg/nucleo_h723zg.yaml index 622c268eceafa0..698fb32a091b93 100644 --- a/boards/st/nucleo_h723zg/nucleo_h723zg.yaml +++ b/boards/st/nucleo_h723zg/nucleo_h723zg.yaml @@ -21,4 +21,5 @@ supported: - netif:eth - backup_sram - usb_device + - rtc vendor: st diff --git a/boards/st/nucleo_h743zi/doc/index.rst b/boards/st/nucleo_h743zi/doc/index.rst index d5d1ee596b62a0..66e75e574bbcd4 100644 --- a/boards/st/nucleo_h743zi/doc/index.rst +++ b/boards/st/nucleo_h743zi/doc/index.rst @@ -129,6 +129,8 @@ features: +-------------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_h743zi/nucleo_h743zi.yaml b/boards/st/nucleo_h743zi/nucleo_h743zi.yaml index e67e8d0e54e7f9..b283964820abf2 100644 --- a/boards/st/nucleo_h743zi/nucleo_h743zi.yaml +++ b/boards/st/nucleo_h743zi/nucleo_h743zi.yaml @@ -25,4 +25,5 @@ supported: - can - dac - dma + - rtc vendor: st diff --git a/boards/st/nucleo_l073rz/doc/index.rst b/boards/st/nucleo_l073rz/doc/index.rst index 4c4ca788ddd0be..991a3710d08d20 100644 --- a/boards/st/nucleo_l073rz/doc/index.rst +++ b/boards/st/nucleo_l073rz/doc/index.rst @@ -104,6 +104,8 @@ The Zephyr nucleo_l073rz board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_l073rz/nucleo_l073rz.dts b/boards/st/nucleo_l073rz/nucleo_l073rz.dts index 93571670b7dba0..eefd8d428e7e27 100644 --- a/boards/st/nucleo_l073rz/nucleo_l073rz.dts +++ b/boards/st/nucleo_l073rz/nucleo_l073rz.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Ilya Tagunov + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -165,6 +166,12 @@ stm32_lp_tick_source: &lptim1 { }; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, + <&rcc STM32_SRC_LSI RTC_SEL(2)>; + status = "okay"; +}; + &rng { status = "okay"; }; diff --git a/boards/st/nucleo_l073rz/nucleo_l073rz.yaml b/boards/st/nucleo_l073rz/nucleo_l073rz.yaml index f97973c48542dc..2a2ffde92bd788 100644 --- a/boards/st/nucleo_l073rz/nucleo_l073rz.yaml +++ b/boards/st/nucleo_l073rz/nucleo_l073rz.yaml @@ -22,4 +22,5 @@ supported: - counter - rng - eeprom + - rtc vendor: st diff --git a/boards/st/nucleo_l152re/doc/index.rst b/boards/st/nucleo_l152re/doc/index.rst index 9d8e31a6a6e3a8..e0e92e5c16843a 100644 --- a/boards/st/nucleo_l152re/doc/index.rst +++ b/boards/st/nucleo_l152re/doc/index.rst @@ -100,6 +100,8 @@ The Zephyr nucleo_l152re board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_l152re/nucleo_l152re.yaml b/boards/st/nucleo_l152re/nucleo_l152re.yaml index cc550b993c9c5f..2713e735fa5a39 100644 --- a/boards/st/nucleo_l152re/nucleo_l152re.yaml +++ b/boards/st/nucleo_l152re/nucleo_l152re.yaml @@ -23,4 +23,5 @@ supported: - pwm - dma - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_l4r5zi/doc/index.rst b/boards/st/nucleo_l4r5zi/doc/index.rst index f449c985a83600..5fd6156e1ba963 100644 --- a/boards/st/nucleo_l4r5zi/doc/index.rst +++ b/boards/st/nucleo_l4r5zi/doc/index.rst @@ -141,6 +141,8 @@ hardware features: +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml b/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml index ee4115fc1e6d3e..5be0e1f69bed58 100644 --- a/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml +++ b/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml @@ -18,6 +18,7 @@ supported: - nvs - counter - adc + - rtc ram: 640 flash: 2048 vendor: st diff --git a/boards/st/nucleo_u575zi_q/doc/index.rst b/boards/st/nucleo_u575zi_q/doc/index.rst index 88c4ed94b282dc..d69bbe3f28d2a5 100644 --- a/boards/st/nucleo_u575zi_q/doc/index.rst +++ b/boards/st/nucleo_u575zi_q/doc/index.rst @@ -173,6 +173,8 @@ The Zephyr nucleo_u575zi_q board configuration supports the following hardware f +-----------+------------+-------------------------------------+ | RNG | on-chip | True Random number generator | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi index 62b466defb4e4a..26069f4b73f54a 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -187,6 +188,12 @@ zephyr_udc0: &usbotg_fs { status = "okay"; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &vref1 { status = "okay"; }; diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml index 0c65b8361ff6cb..a8a38453cb6f39 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml @@ -20,6 +20,7 @@ supported: - watchdog - backup_sram - dma + - rtc ram: 786 flash: 2048 vendor: st diff --git a/boards/st/nucleo_u5a5zj_q/doc/index.rst b/boards/st/nucleo_u5a5zj_q/doc/index.rst index 521997ca266143..9245300e816ba2 100644 --- a/boards/st/nucleo_u5a5zj_q/doc/index.rst +++ b/boards/st/nucleo_u5a5zj_q/doc/index.rst @@ -205,6 +205,8 @@ The Zephyr nucleo_u5a5zj_q board configuration supports the following hardware f +-----------+------------+-------------------------------------+ | RNG | on-chip | True Random number generator | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi index d0ba893c873006..14a5b1de80fe00 100644 --- a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi +++ b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -180,6 +180,12 @@ status = "okay"; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &vref1 { status = "okay"; }; diff --git a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml index 4d74f6a13b8b07..cd937080414106 100644 --- a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml +++ b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml @@ -20,5 +20,6 @@ supported: - watchdog - backup_sram - dma + - rtc ram: 2450 flash: 4096 diff --git a/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst b/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst index 04bdc9d45ec719..6be25936050be1 100644 --- a/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst +++ b/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst @@ -173,6 +173,8 @@ The Zephyr nucleo_wb55rg board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml b/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml index f455356048c475..a2b42575b1b54a 100644 --- a/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml +++ b/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml @@ -22,4 +22,5 @@ supported: - arduino_spi - usb_device - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst b/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst index 2423d6bc36a663..70b08b6b0566b7 100644 --- a/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst +++ b/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst @@ -177,6 +177,8 @@ The Zephyr nucleo_wba55cg board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | RADIO | on-chip | Bluetooth Low Energy | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml b/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml index 0f435e29c75e0d..947549a697cf46 100644 --- a/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml +++ b/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml @@ -16,6 +16,7 @@ supported: - arduino_i2c - arduino_spi - counter + - rtc ram: 128 flash: 1024 vendor: st diff --git a/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst b/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst index df32bbc07c071d..50f7c63d9e02cf 100644 --- a/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst +++ b/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst @@ -208,6 +208,8 @@ features: +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts b/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts index e83f45452ddd8a..6e37b1c148533a 100644 --- a/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts +++ b/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 STMicroelectronics + * Copyright (c) 2020-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,6 +85,10 @@ stm32_lp_tick_source: &lptim1 { status = "okay"; }; +&clk_lse { + status = "okay"; +}; + &pll { div-m = <1>; mul-n = <6>; @@ -216,6 +220,12 @@ stm32_lp_tick_source: &lptim1 { }; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &vref { status = "okay"; }; diff --git a/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml b/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml index b741d37280550e..4eb53ef3324fb9 100644 --- a/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml +++ b/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml @@ -23,4 +23,5 @@ supported: - watchdog - nvs - lora + - rtc vendor: st diff --git a/boards/st/stm32f3_disco/doc/index.rst b/boards/st/stm32f3_disco/doc/index.rst index 8862d754fbbd1d..d4a629a4895923 100644 --- a/boards/st/stm32f3_disco/doc/index.rst +++ b/boards/st/stm32f3_disco/doc/index.rst @@ -109,6 +109,8 @@ features: +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. diff --git a/boards/st/stm32f3_disco/stm32f3_disco_B.yaml b/boards/st/stm32f3_disco/stm32f3_disco_B.yaml index 1c87cb7fd36bfb..ebdbe230d20dc4 100644 --- a/boards/st/stm32f3_disco/stm32f3_disco_B.yaml +++ b/boards/st/stm32f3_disco/stm32f3_disco_B.yaml @@ -21,4 +21,5 @@ supported: - adc - dac - dma + - rtc vendor: st diff --git a/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml b/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml index 13e6b0bf1431fb..bc17f1c2d684db 100644 --- a/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml +++ b/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml @@ -20,4 +20,5 @@ supported: - pwm - adc - dac + - rtc vendor: st diff --git a/boards/st/stm32h573i_dk/doc/index.rst b/boards/st/stm32h573i_dk/doc/index.rst index bdc29c5dc751f7..72fba315ace508 100644 --- a/boards/st/stm32h573i_dk/doc/index.rst +++ b/boards/st/stm32h573i_dk/doc/index.rst @@ -197,6 +197,8 @@ hardware features: +-----------+------------+-------------------------------------+ | USB | on-chip | USB full-speed host/device bus | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.yaml b/boards/st/stm32h573i_dk/stm32h573i_dk.yaml index ac963c5756f43f..b2b3ae93b79a0d 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.yaml +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.yaml @@ -25,4 +25,5 @@ supported: - usb - i2c - sdhc + - rtc vendor: st diff --git a/boards/st/stm32h750b_dk/doc/index.rst b/boards/st/stm32h750b_dk/doc/index.rst index f295947a334451..e450488ed4d39e 100644 --- a/boards/st/stm32h750b_dk/doc/index.rst +++ b/boards/st/stm32h750b_dk/doc/index.rst @@ -55,6 +55,10 @@ The current Zephyr stm32h750b_dk board configuration supports the following hard +-----------+------------+-------------------------------------+ | GPIO | on-chip | gpio | +-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. diff --git a/boards/st/stm32h750b_dk/stm32h750b_dk.dts b/boards/st/stm32h750b_dk/stm32h750b_dk.dts index 7cd328e90dbde8..bb90724deadcb7 100644 --- a/boards/st/stm32h750b_dk/stm32h750b_dk.dts +++ b/boards/st/stm32h750b_dk/stm32h750b_dk.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,10 @@ status = "okay"; }; +&clk_lse { + status = "okay"; +}; + &pll { div-m = <5>; mul-n = <192>; @@ -163,3 +167,9 @@ }; }; }; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; diff --git a/boards/st/stm32h750b_dk/stm32h750b_dk.yaml b/boards/st/stm32h750b_dk/stm32h750b_dk.yaml index 126376b1464eda..ddca938bb51e68 100644 --- a/boards/st/stm32h750b_dk/stm32h750b_dk.yaml +++ b/boards/st/stm32h750b_dk/stm32h750b_dk.yaml @@ -12,4 +12,6 @@ supported: - arduino_gpio - gpio - dma + - flash + - rtc vendor: st diff --git a/boards/st/stm32u5a9j_dk/doc/index.rst b/boards/st/stm32u5a9j_dk/doc/index.rst index 29e4e02cdebd10..7e3d638fa3ead5 100644 --- a/boards/st/stm32u5a9j_dk/doc/index.rst +++ b/boards/st/stm32u5a9j_dk/doc/index.rst @@ -85,6 +85,8 @@ hardware features: +-----------+------------+-------------------------------------+ | TIMER | on-chip | counter | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features have not been enabled yet for this board. diff --git a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts index 66859c3daabcb3..05bdfdd34ebf34 100644 --- a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts +++ b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -89,6 +89,10 @@ msi-pll-mode; }; +&clk_lse { + status = "okay"; +}; + &pll1 { div-m = <1>; mul-n = <80>; @@ -271,6 +275,12 @@ uart0: &usart3 { }; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &iwdg { status = "okay"; }; diff --git a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml index 7205a3954d46c7..792eda8a7b76f6 100644 --- a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml +++ b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml @@ -20,6 +20,7 @@ supported: - sdmmc - timer - rng + - rtc ram: 2496 flash: 4096 vendor: st From 4ebea5b6ba554a523ff6a81d4d47fe2898724de3 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0507/1389] tests: drivers: rtc: rtc_api: support STM32 boards Add RTC config for a large selection of STM32 boards. Signed-off-by: Abderrahmane Jarmouni --- tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.conf | 2 ++ .../drivers/rtc/rtc_api/boards/b_u585i_iot02a.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.conf | 2 ++ .../rtc/rtc_api/boards/disco_l475_iot1.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_f070rb.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_f091rc.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.conf | 1 + .../drivers/rtc/rtc_api/boards/nucleo_f207zg.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f401re.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_f401re.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_f429zi.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_f746zg.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_f767zi.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_g071rb.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_g474re.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_g474re.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_h563zi.conf | 2 ++ tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_h723zg.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_h743zi.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_l073rz.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_l152re.conf | 1 + .../drivers/rtc/rtc_api/boards/nucleo_l152re.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_l4r5zi.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.conf | 2 ++ .../rtc/rtc_api/boards/nucleo_u575zi_q.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.conf | 2 ++ .../rtc/rtc_api/boards/nucleo_u5a5zj_q.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_wb55rg.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_wba52cg.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_wba55cg.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.conf | 1 + .../drivers/rtc/rtc_api/boards/nucleo_wl55jc.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/stm32f3_disco.conf | 2 ++ .../drivers/rtc/rtc_api/boards/stm32f3_disco.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.conf | 2 ++ .../drivers/rtc/rtc_api/boards/stm32h573i_dk.overlay | 11 +++++++++++ tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.conf | 2 ++ .../drivers/rtc/rtc_api/boards/stm32h750b_dk.overlay | 11 +++++++++++ 51 files changed, 324 insertions(+) create mode 100644 tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f401re.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f401re.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_g474re.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_g474re.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h563zi.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_l152re.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_l152re.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/stm32f3_disco.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/stm32f3_disco.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.overlay create mode 100644 tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.overlay diff --git a/tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.conf b/tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.overlay b/tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/b_u585i_iot02a.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.conf b/tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.overlay b/tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/disco_l475_iot1.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f070rb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f091rc.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.conf new file mode 100644 index 00000000000000..d8e316b0bf27f0 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.conf @@ -0,0 +1 @@ +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f207zg.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f401re.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f401re.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f401re.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f401re.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f401re.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f401re.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f429zi.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f746zg.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_f767zi.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_g071rb.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_g474re.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_g474re.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_g474re.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_g474re.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_g474re.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_g474re.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h563zi.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_h563zi.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h563zi.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h723zg.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h743zi.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_l073rz.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_l152re.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_l152re.conf new file mode 100644 index 00000000000000..d8e316b0bf27f0 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_l152re.conf @@ -0,0 +1 @@ +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_l152re.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_l152re.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_l152re.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_l4r5zi.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_u575zi_q.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_u5a5zj_q.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wb55rg.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wba52cg.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wba55cg.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.conf new file mode 100644 index 00000000000000..d8e316b0bf27f0 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.conf @@ -0,0 +1 @@ +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_wl55jc.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/stm32f3_disco.conf b/tests/drivers/rtc/rtc_api/boards/stm32f3_disco.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/stm32f3_disco.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/stm32f3_disco.overlay b/tests/drivers/rtc/rtc_api/boards/stm32f3_disco.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/stm32f3_disco.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.conf b/tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.overlay b/tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/stm32h573i_dk.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; diff --git a/tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.conf b/tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.conf new file mode 100644 index 00000000000000..8c6c114ee41fa6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.overlay b/tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.overlay new file mode 100644 index 00000000000000..bd861fccf42929 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/stm32h750b_dk.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; From 34179d0ce227b4a23211b05e93cc8f43182dd3c7 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0508/1389] tests: drivers: rtc_api: test_alarm: add alarm id in logs Add alarm ID in debug & error logs. Signed-off-by: Abderrahmane Jarmouni --- tests/drivers/rtc/rtc_api/src/test_alarm.c | 35 ++++++++++--------- .../rtc/rtc_api/src/test_alarm_callback.c | 21 +++++------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/tests/drivers/rtc/rtc_api/src/test_alarm.c b/tests/drivers/rtc/rtc_api/src/test_alarm.c index f65baf15877e90..5f81d05c87b42c 100644 --- a/tests/drivers/rtc/rtc_api/src/test_alarm.c +++ b/tests/drivers/rtc/rtc_api/src/test_alarm.c @@ -1,5 +1,6 @@ /* - * Copyright 2022 Bjarki Arge Andreasen + * Copyright (c) 2022 Bjarki Arge Andreasen + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -38,7 +39,7 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_time(rtc, i, 0, NULL); - zassert_ok(ret, "Failed to clear alarm time"); + zassert_ok(ret, "Failed to clear alarm %d time", i); } /* Disable alarm callback */ @@ -46,14 +47,14 @@ ZTEST(rtc_api, test_alarm) ret = rtc_alarm_set_callback(rtc, i, NULL, NULL); zassert_true((ret == 0) || (ret == -ENOTSUP), - "Failed to clear and disable alarm callback"); + "Failed to clear and disable alarm %d callback", i); } /* Every supported alarm field should reject invalid values. */ for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported); - zassert_ok(ret, "Failed to get supported alarm fields"); + zassert_ok(ret, "Failed to get supported alarm %d fields", i); alarm_time_set = (struct rtc_time) { .tm_sec = 70, @@ -77,8 +78,8 @@ ZTEST(rtc_api, test_alarm) ret = rtc_alarm_set_time(rtc, i, masks[j], &alarm_time_set); zassert_equal( -EINVAL, ret, - "%s: RTC should reject invalid alarm time in field %zu.", - rtc->name, j); + "%s: RTC should reject invalid alarm %d time in field %zu.", + rtc->name, i, j); } } } @@ -87,7 +88,7 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported); - zassert_ok(ret, "Failed to get supported alarm fields"); + zassert_ok(ret, "Failed to get supported alarm %d fields", i); /* Skip test if alarm does not support the minute and hour fields */ if (((RTC_ALARM_TIME_MASK_MINUTE & alarm_time_mask_supported) == 0) || @@ -104,23 +105,23 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_time(rtc, i, alarm_time_mask_set, &alarm_time_set); - zassert_ok(ret, "Failed to set alarm time"); + zassert_ok(ret, "Failed to set alarm %d time", i); } /* Validate alarm time */ for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_get_time(rtc, i, &alarm_time_mask_get, &alarm_time_get); - zassert_ok(ret, "Failed to set alarm time"); + zassert_ok(ret, "Failed to set alarm %d time", i); zassert_equal(alarm_time_mask_get, alarm_time_mask_set, - "Incorrect alarm time mask"); + "Incorrect alarm %d time mask", i); zassert_equal(alarm_time_get.tm_min, alarm_time_set.tm_min, - "Incorrect alarm time minute field"); + "Incorrect alarm %d time minute field", i); zassert_equal(alarm_time_get.tm_hour, alarm_time_set.tm_hour, - "Incorrect alarm time hour field"); + "Incorrect alarm %d time hour field", i); } /* Initialize RTC time to set */ @@ -141,7 +142,7 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_is_pending(rtc, i); - zassert_true(ret > -1, "Failed to clear alarm pending status"); + zassert_true(ret > -1, "Failed to clear alarm %d pending status", i); } /* Wait before validating alarm pending status has not been set prematurely */ @@ -151,7 +152,7 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_is_pending(rtc, i); - zassert_ok(ret, "Alarm should not be pending"); + zassert_ok(ret, "Alarm %d should not be pending", i); } /* Wait for alarm to trigger */ @@ -161,7 +162,7 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_is_pending(rtc, i); - zassert_equal(ret, 1, "Alarm should be pending"); + zassert_equal(ret, 1, "Alarm %d should be pending", i); } } @@ -169,10 +170,10 @@ ZTEST(rtc_api, test_alarm) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_time(rtc, i, 0, NULL); - zassert_ok(ret, "Failed to disable alarm"); + zassert_ok(ret, "Failed to disable alarm %d", i); ret = rtc_alarm_is_pending(rtc, i); - zassert_true(ret > -1, "Failed to clear alarm pending state"); + zassert_true(ret > -1, "Failed to clear alarm %d pending state", i); } } diff --git a/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c b/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c index 9b51d889c0e8e6..c73cbd5fbddf02 100644 --- a/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c +++ b/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c @@ -1,5 +1,6 @@ /* - * Copyright 2022 Bjarki Arge Andreasen + * Copyright (c) 2022 Bjarki Arge Andreasen + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,14 +55,14 @@ ZTEST(rtc_api, test_alarm_callback) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_callback(rtc, i, NULL, NULL); - zassert_ok(ret, "Failed to clear and disable alarm"); + zassert_ok(ret, "Failed to clear and disable alarm %d", i); } /* Validate alarms supported fields */ for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported); - zassert_ok(ret, "Failed to get supported alarm fields"); + zassert_ok(ret, "Failed to get supported alarm %d fields", i); /* Skip test if alarm does not support the minute and hour fields */ if (((RTC_ALARM_TIME_MASK_MINUTE & alarm_time_mask_supported) == 0) || @@ -78,7 +79,7 @@ ZTEST(rtc_api, test_alarm_callback) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_time(rtc, i, alarm_time_mask_set, &alarm_time_set); - zassert_ok(ret, "Failed to set alarm time"); + zassert_ok(ret, "Failed to set alarm %d time", i); } /* Initialize RTC time to set */ @@ -98,7 +99,7 @@ ZTEST(rtc_api, test_alarm_callback) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_is_pending(rtc, i); - zassert_true(ret > -1, "Failed to clear alarm pending status"); + zassert_true(ret > -1, "Failed to clear alarm %d pending status", i); } /* Set and enable alarm callback */ @@ -113,7 +114,7 @@ ZTEST(rtc_api, test_alarm_callback) &callback_user_data_even); } - zassert_ok(ret, "Failed to set alarm callback"); + zassert_ok(ret, "Failed to set alarm %d callback", i); } for (uint8_t i = 0; i < 2; i++) { @@ -143,7 +144,7 @@ ZTEST(rtc_api, test_alarm_callback) : atomic_test_bit(&callback_called_mask_even, j); zassert_equal(callback_called_status, true, - "Alarm callback should have been called"); + "Alarm %d callback should have been called", j); } /* Reset RTC time */ @@ -156,14 +157,14 @@ ZTEST(rtc_api, test_alarm_callback) for (uint16_t i = 0; i < alarms_count; i++) { ret = rtc_alarm_set_callback(rtc, i, NULL, NULL); - zassert_ok(ret, "Failed to disable alarm callback"); + zassert_ok(ret, "Failed to disable alarm %d callback", i); ret = rtc_alarm_set_time(rtc, i, 0, NULL); - zassert_ok(ret, "Failed to disable alarm"); + zassert_ok(ret, "Failed to disable alarm %d", i); ret = rtc_alarm_is_pending(rtc, i); - zassert_true(ret > -1, "Failed to clear alarm pending state"); + zassert_true(ret > -1, "Failed to clear alarm %d pending state", i); } } From 553cd39f16347866b9f9ff1cd63552c07749d6f0 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0509/1389] drivers: rtc: stm32: make it clean again Make driver clean again. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 3ed8f9fdf9284a..2d59137b25fc1e 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -346,9 +346,9 @@ static int rtc_stm32_init(const struct device *dev) k_mutex_init(&data->lock); /* Enable Backup access */ -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_EnableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ /* Enable RTC clock source */ if (clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL) != 0) { @@ -370,9 +370,9 @@ static int rtc_stm32_init(const struct device *dev) err = rtc_stm32_configure(dev); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ #ifdef CONFIG_RTC_ALARM rtc_stm32_irq_config(dev); @@ -413,18 +413,18 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t LOG_DBG("Setting clock"); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_EnableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ LL_RTC_DisableWriteProtection(RTC); ErrorStatus status = LL_RTC_EnterInitMode(RTC); if (status != SUCCESS) { -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ k_mutex_unlock(&data->lock); return -EIO; } @@ -450,9 +450,9 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t LL_RTC_EnableWriteProtection(RTC); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ k_mutex_unlock(&data->lock); @@ -962,9 +962,9 @@ static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibrati return -EIO; } -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_EnableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ LL_RTC_DisableWriteProtection(RTC); @@ -972,9 +972,9 @@ static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibrati LL_RTC_EnableWriteProtection(RTC); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ return 0; } From e4d335928faca8f825f9526b6d412950838f7366 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0510/1389] drivers: rtc: stm32: subsecond not supported by F2x subsecond counting is not supported by STM32F2x SoC series. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 2d59137b25fc1e..cdc975c4f1fe19 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -39,8 +39,9 @@ LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); -#if defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SUBSECOND_SUPPORT) -/* subsecond counting is not supported by some STM32L1x MCUs */ +#if (defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SUBSECOND_SUPPORT)) \ + || defined(CONFIG_SOC_SERIES_STM32F2X) +/* subsecond counting is not supported by some STM32L1x MCUs (Cat.1) & by STM32F2x SoC series */ #define HW_SUBSECOND_SUPPORT (0) #else #define HW_SUBSECOND_SUPPORT (1) From 94ae4446d70b337131b8c0ae294fd0a0a385c8f2 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0511/1389] boards: st: nucleo_f103rb: fix doc STM32 RTC driver does not support F1x series for now. Signed-off-by: Abderrahmane Jarmouni --- boards/st/nucleo_f103rb/doc/index.rst | 2 -- boards/st/stm32f103_mini/doc/index.rst | 2 -- 2 files changed, 4 deletions(-) diff --git a/boards/st/nucleo_f103rb/doc/index.rst b/boards/st/nucleo_f103rb/doc/index.rst index 0ff1a60ef85f11..e2313c5e932fd2 100644 --- a/boards/st/nucleo_f103rb/doc/index.rst +++ b/boards/st/nucleo_f103rb/doc/index.rst @@ -99,8 +99,6 @@ The Zephyr nucleo_f103rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | COUNTER | on-chip | rtc | +-----------+------------+-------------------------------------+ -| RTC | on-chip | rtc | -+-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/stm32f103_mini/doc/index.rst b/boards/st/stm32f103_mini/doc/index.rst index 63d2199e4d03ff..c6938020f99ef2 100644 --- a/boards/st/stm32f103_mini/doc/index.rst +++ b/boards/st/stm32f103_mini/doc/index.rst @@ -75,8 +75,6 @@ The Zephyr stm32f103_mini board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | COUNTER | on-chip | rtc | +-----------+------------+-------------------------------------+ -| RTC | on-chip | rtc | -+-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. From 3964e5a816aa52269a8710ac1dd51c5ad7038281 Mon Sep 17 00:00:00 2001 From: Wojciech Sipak Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0512/1389] boards: use unique names The pretty names specified in the YAML files of each board are not unique. Signed-off-by: Wojciech Sipak --- boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml | 2 +- boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml | 2 +- boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml | 2 +- boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml | 2 +- .../cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml | 2 +- .../cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml | 2 +- .../cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml | 2 +- .../cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml | 2 +- .../esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml | 2 +- .../esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml | 2 +- .../espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml | 2 +- .../espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml | 2 +- boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml | 2 +- boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml | 2 +- boards/hardkernel/odroid_go/odroid_go_appcpu.yaml | 2 +- boards/hardkernel/odroid_go/odroid_go_procpu.yaml | 2 +- .../heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml | 2 +- .../heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml | 2 +- .../heltec_wireless_stick_lite_v3_appcpu.yaml | 2 +- boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml | 2 +- boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml | 2 +- .../luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml | 2 +- .../esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml | 2 +- .../luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml | 2 +- .../esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml | 2 +- boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml | 2 +- boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml | 2 +- .../m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml | 2 +- .../m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml | 2 +- boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml | 2 +- boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml | 2 +- boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml | 2 +- boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml | 2 +- boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml | 2 +- boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml | 2 +- boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml | 2 +- boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml | 2 +- boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml | 2 +- boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml | 2 +- boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml | 2 +- .../lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml | 2 +- boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml | 2 +- boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml | 2 +- boards/others/stm32_min_dev/stm32_min_dev_black.yaml | 2 +- boards/others/stm32_min_dev/stm32_min_dev_blue.yaml | 2 +- boards/phytec/reel_board/reel_board_nrf52840_2.yaml | 2 +- boards/seagate/legend/legend_stm32f070xb_25hdd.yaml | 2 +- boards/seagate/legend/legend_stm32f070xb_25ssd.yaml | 2 +- boards/seagate/legend/legend_stm32f070xb_35.yaml | 2 +- boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml | 2 +- boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml | 2 +- boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml | 2 +- boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml | 2 +- boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml | 2 +- boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml | 2 +- boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml | 2 +- 56 files changed, 56 insertions(+), 56 deletions(-) diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml index 1f3d3d9e0c0d35..119745e52edebc 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@1.4.0/nrf9160 -name: Actinius Icarus +name: Actinius Icarus (rev. 1.4.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml index d8bce88855696d..f017d9c6f3c355 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@2.0.0/nrf9160 -name: Actinius Icarus +name: Actinius Icarus (rev. 2.0.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml index 46005a7da105c3..0733824966130f 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@1.4.0/nrf9160/ns -name: Actinius Icarus Non-Secure +name: Actinius Icarus Non-Secure (rev. 1.4.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml index e8d9256f3f0c9f..a6a5ecc7738bb8 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@2.0.0/nrf9160/ns -name: Actinius Icarus Non-Secure +name: Actinius Icarus Non-Secure (rev. 2.0.0) type: mcu arch: arm toolchain: diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml index 311c88f58acbfa..a8e935bd50ae94 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@0.0.0/cy8c6347/m0 -name: Cypress PSoC6 BLE Pioneer Kit (M0) +name: Cypress PSoC6 BLE Pioneer Kit (M0, rev. 0.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml index c3bcfac49c5188..27b02fa4bedbad 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@1.0.0/cy8c6347/m0 -name: Cypress PSoC6 BLE Pioneer Kit (M0) +name: Cypress PSoC6 BLE Pioneer Kit (M0, rev. 1.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml index ba22e8aa624b3a..30708da7fa4234 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@0.0.0/cy8c6347/m4 -name: Cypress PSoC6 BLE Pioneer Kit (M4) +name: Cypress PSoC6 BLE Pioneer Kit (M4, rev. 0.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml index bd4a3affce9f29..c75724709788dd 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@1.0.0/cy8c6347/m4 -name: Cypress PSoC6 BLE Pioneer Kit (M4) +name: Cypress PSoC6 BLE Pioneer Kit (M4, rev. 1.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml index 8c8e8ae15778e7..04082823801636 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_devkitc_wrover/esp32/appcpu -name: ESP32-DevkitC-WROVER-E +name: ESP32-DevkitC-WROVER-E APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml index bf130d7d3a8cd5..a2089253a3c6b2 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_devkitc_wrover/esp32/procpu -name: ESP32-DevkitC-WROVER-E +name: ESP32-DevkitC-WROVER-E PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml index 1984dea8da3c27..7f2f067d72c67f 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_ethernet_kit/esp32/appcpu -name: ESP32 ETHERNET KIT +name: ESP32 ETHERNET KIT APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml index d7d4958d2e73f7..ca098c1ef773d4 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_ethernet_kit/esp32/procpu -name: ESP32 ETHERNET KIT +name: ESP32 ETHERNET KIT PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml index 64f7ef2124f651..57971b3571c15d 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp_wrover_kit/esp32/appcpu -name: ESP WROVER KIT +name: ESP WROVER KIT APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml index ecec50611c35b4..d316dd1b8d0293 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp_wrover_kit/esp32/procpu -name: ESP WROVER KIT +name: ESP WROVER KIT PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml b/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml index a5a1c003ef35ca..946166f95b49da 100644 --- a/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml +++ b/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml @@ -1,5 +1,5 @@ identifier: odroid_go/esp32/appcpu -name: ODROID-GO +name: ODROID-GO APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/hardkernel/odroid_go/odroid_go_procpu.yaml b/boards/hardkernel/odroid_go/odroid_go_procpu.yaml index 59363bb4ee92e4..f2eafb526763f2 100644 --- a/boards/hardkernel/odroid_go/odroid_go_procpu.yaml +++ b/boards/hardkernel/odroid_go/odroid_go_procpu.yaml @@ -1,5 +1,5 @@ identifier: odroid_go/esp32/procpu -name: ODROID-GO +name: ODROID-GO PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml index 373c6b0eae9949..d838e27766ea2c 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml @@ -1,5 +1,5 @@ identifier: heltec_wifi_lora32_v2/esp32/appcpu -name: ESP32 DEVKITC WROVER APPCPU +name: HELTEC WiFi LoRa 32 (V2) Board APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml index f8571589d7a123..d516f1e1c5c892 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml @@ -1,5 +1,5 @@ identifier: heltec_wifi_lora32_v2/esp32/procpu -name: HELTEC WiFi LoRa 32 (V2) Board +name: HELTEC WiFi LoRa 32 (V2) Board PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml index a465da8f94dc97..d738477900dfbe 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml +++ b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: heltec_wireless_stick_lite_v3/esp32s3/appcpu -name: ESP32-S3 DevKitM APPCPU +name: Heltec Wireless Stick Lite (V3) APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml index af75ec0edbcf86..8a80a51872e170 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml @@ -1,5 +1,5 @@ identifier: kincony_kc868_a32/esp32/appcpu -name: ESP32 DEVKITC WROVER APPCPU +name: KINCONY-KC868-A32 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml index 51ac12191f6dd4..325c3794c29da5 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml @@ -1,5 +1,5 @@ identifier: kincony_kc868_a32/esp32/procpu -name: KINCONY-KC868-A32 +name: KINCONY-KC868-A32 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml index 05aac04c00fb8a..ae7e008793e8bb 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/appcpu -name: ESP32-S3 LuatOS Core +name: ESP32-S3 LuatOS Core APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml index cb2ac02717b5fc..3a80a65a46a916 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/appcpu/usb -name: ESP32-S3 LuatOS Core USB +name: ESP32-S3 LuatOS Core APPCPU USB type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml index 2a1bb02cc2f2c9..6d564843a1c32e 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/procpu -name: ESP32-S3 LuatOS Core +name: ESP32-S3 LuatOS Core PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml index f1cd4d19d5a6b2..7e160d68117160 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/procpu/usb -name: ESP32-S3 LuatOS Core USB +name: ESP32-S3 LuatOS Core PROCPU USB type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml index a8efc9aad007d9..30c20695c27e70 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3/esp32s3/appcpu -name: M5Stack AtomS3 +name: M5Stack AtomS3 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml index 4be28b02f83eb4..082aa4e5699255 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3/esp32s3/procpu -name: M5Stack AtomS3 +name: M5Stack AtomS3 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml index 0a641e9ef12755..004ed974675bd9 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3_lite/esp32s3/appcpu -name: M5Stack AtomS3-Lite +name: M5Stack AtomS3-Lite APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml index 3012207d36de95..996732bc3dd007 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3_lite/esp32s3/procpu -name: M5Stack AtomS3-Lite +name: M5Stack AtomS3-Lite PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml index 8e5a51d07c7f0e..a49668e954770c 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml +++ b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_core2/esp32/appcpu -name: M5Stack Core2 +name: M5Stack Core2 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml index b5f7a37910dde1..5a95351e16df30 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml +++ b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_core2/esp32/procpu -name: M5Stack Core2 +name: M5Stack Core2 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml index eb4fcfcd02809c..9443a7e09c65f2 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_stamps3/esp32s3/appcpu -name: M5Stack StampS3 +name: M5Stack StampS3 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml index 99e14f59b19762..746a5d2916e7cc 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_stamps3/esp32s3/procpu -name: M5Stack StampS3 +name: M5Stack StampS3 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml index e436849ced4d1a..ac942189097796 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stickc_plus/esp32/appcpu -name: M5StickC PLUS +name: M5StickC PLUS APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml index ad8985b55db08f..69741a72d8f515 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stickc_plus/esp32/procpu -name: M5StickC PLUS +name: M5StickC PLUS PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml b/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml index 20b765232869e6..7613fabaed57c8 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9160dk@0.7.0/nrf52840 -name: nRF9160-DK-NRF52840 +name: nRF9160-DK-NRF52840 (rev. 0.7.0) type: mcu arch: arm ram: 64 diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml index d66078fde8bb59..52a05c854556b8 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9160dk@0.7.0/nrf9160 -name: nRF9160-DK-NRF9160 +name: nRF9160-DK-NRF9160 (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml index 1957bc3ad259ba..0faa84b38c9485 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9160dk@0.7.0/nrf9160/ns -name: nRF9160-DK-NRF9160-Non-Secure +name: nRF9160-DK-NRF9160-Non-Secure (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml index 47842c49d46d87..9d9f07dc48b859 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9161dk@0.7.0/nrf9161 -name: nRF9161-DK-NRF9161 +name: nRF9161-DK-NRF9161 (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml index fd95098a773452..c8224cafae41c5 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9161dk@0.7.0/nrf9161/ns -name: nRF9161-DK-NRF9161-Non-Secure +name: nRF9161-DK-NRF9161-Non-Secure (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml b/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml index 29559d1e262dd6..ead08879d1b7d1 100644 --- a/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml +++ b/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml @@ -1,5 +1,5 @@ identifier: olimex_lora_stm32wl_devkit@D -name: Olimex LoRa STM32WL DevKit +name: Olimex LoRa STM32WL DevKit (rev. D) type: mcu arch: arm toolchain: diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml index 9e81868de21810..fa3b6417b90f1a 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml @@ -1,5 +1,5 @@ identifier: olimex_esp32_evb/esp32/appcpu -name: Olimex ESP32-EVB +name: Olimex ESP32-EVB APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml index f4929c52b42043..c897a54621493f 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml @@ -1,5 +1,5 @@ identifier: olimex_esp32_evb/esp32/procpu -name: Olimex ESP32-EVB +name: Olimex ESP32-EVB PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/others/stm32_min_dev/stm32_min_dev_black.yaml b/boards/others/stm32_min_dev/stm32_min_dev_black.yaml index 0740dc17fafb39..543b58db8375ea 100644 --- a/boards/others/stm32_min_dev/stm32_min_dev_black.yaml +++ b/boards/others/stm32_min_dev/stm32_min_dev_black.yaml @@ -1,5 +1,5 @@ identifier: stm32_min_dev@black -name: STM32 Minimum Development Board +name: STM32 Minimum Development Board (black) type: mcu arch: arm toolchain: diff --git a/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml b/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml index 8249d6f9719925..3a7f4ad73082ce 100644 --- a/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml +++ b/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml @@ -1,5 +1,5 @@ identifier: stm32_min_dev@blue -name: STM32 Minimum Development Board +name: STM32 Minimum Development Board (blue) type: mcu arch: arm toolchain: diff --git a/boards/phytec/reel_board/reel_board_nrf52840_2.yaml b/boards/phytec/reel_board/reel_board_nrf52840_2.yaml index dc6361d4f50197..7112c3fde8e163 100644 --- a/boards/phytec/reel_board/reel_board_nrf52840_2.yaml +++ b/boards/phytec/reel_board/reel_board_nrf52840_2.yaml @@ -1,5 +1,5 @@ identifier: reel_board@2 -name: reel-board +name: reel-board (rev. 2) type: mcu arch: arm ram: 512 diff --git a/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml b/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml index a9eb85aee47a28..e94bd6e2faa01a 100644 --- a/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml +++ b/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml @@ -1,5 +1,5 @@ identifier: legend@25hdd -name: Legend +name: Legend (25hdd) type: mcu arch: arm ram: 16 diff --git a/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml b/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml index db494bd878cb86..b1aa3766f7728b 100644 --- a/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml +++ b/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml @@ -1,5 +1,5 @@ identifier: legend@25ssd -name: Legend +name: Legend (25sdd) type: mcu arch: arm ram: 16 diff --git a/boards/seagate/legend/legend_stm32f070xb_35.yaml b/boards/seagate/legend/legend_stm32f070xb_35.yaml index 37ed59788d9bba..851fb36a8b41a8 100644 --- a/boards/seagate/legend/legend_stm32f070xb_35.yaml +++ b/boards/seagate/legend/legend_stm32f070xb_35.yaml @@ -1,5 +1,5 @@ identifier: legend@35 -name: Legend +name: Legend (35) type: mcu arch: arm ram: 16 diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml index 5d66048e038805..53055263f34656 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: xiao_esp32s3/esp32s3/appcpu -name: XIAO ESP32S3 +name: XIAO ESP32S3 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml index 8a1ace79ba69af..d438611cb33730 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml @@ -1,5 +1,5 @@ identifier: xiao_esp32s3/esp32s3/procpu -name: XIAO ESP32S3 +name: XIAO ESP32S3 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml index 498333044249e3..29f4404ca95176 100644 --- a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml +++ b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml @@ -1,5 +1,5 @@ identifier: em_starterkit@2.2/emsk_em7d -name: EM Starterkit EM7D +name: EM Starterkit EM7D (rev. 2.2) type: mcu arch: arc toolchain: diff --git a/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml b/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml index 194e1b451993b6..0cdc0e8ee9d2e9 100644 --- a/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml +++ b/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml @@ -1,5 +1,5 @@ identifier: nucleo_f030r8@2 -name: ST Nucleo F030R8 +name: ST Nucleo F030R8 (rev. 2) type: mcu arch: arm toolchain: diff --git a/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml b/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml index 05f3c979f7f0c0..480b81537b678f 100644 --- a/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml +++ b/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml @@ -1,5 +1,5 @@ identifier: stm32f411e_disco@B -name: ST STM32F411E Discovery +name: ST STM32F411E Discovery (rev. B) type: mcu arch: arm toolchain: diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml index 018b3c2b727323..20e2f1a74c6f8a 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml @@ -1,5 +1,5 @@ identifier: yd_esp32/esp32/appcpu -name: ESP32 DEVKITC WROVER APPCPU +name: YD-ESP32 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml index b3fc0cdf97d1a7..7e8e17cf71f081 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml @@ -1,5 +1,5 @@ identifier: yd_esp32/esp32/procpu -name: YD-ESP32 +name: YD-ESP32 PROCPU type: mcu arch: xtensa toolchain: From 7a881324be9c4b9aef898304b3cab43b71d3c81e Mon Sep 17 00:00:00 2001 From: Helmut Lord Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0513/1389] boards: RAK4631: enable DCDC Enables the DCDC converters by default for the RAK4631 Signed-off-by: Helmut Lord --- boards/rak/rak4631/Kconfig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 boards/rak/rak4631/Kconfig diff --git a/boards/rak/rak4631/Kconfig b/boards/rak/rak4631/Kconfig new file mode 100644 index 00000000000000..b313c721fb6a7e --- /dev/null +++ b/boards/rak/rak4631/Kconfig @@ -0,0 +1,18 @@ +# RAKWIRELESS RAK4631 Board configuration + +# Copyright (c) 2024 Kelly Helmut Lord +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RAK4631 + +config BOARD_ENABLE_DCDC + bool "DCDC mode" + select SOC_DCDC_NRF52X + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF52X_HV + default y + +endif # BOARD_RAK4631 From 5c0f4c52aa7e96c0f4a3ff7a84ce71317fc7483e Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0514/1389] cmake: linker_script: Support deferred init with CMAKE_LINKER_GENERATOR The section for deferred devices was missing when CONFIG_CMAKE_LINKER_GENERATOR is enabled. Signed-off-by: Pieter De Gendt --- cmake/linker_script/common/common-rom.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index dfd5ba8b9e3483..af9715fe20b221 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -8,6 +8,9 @@ zephyr_linker_section_obj_level(SECTION init LEVEL POST_KERNEL) zephyr_linker_section_obj_level(SECTION init LEVEL APPLICATION) zephyr_linker_section_obj_level(SECTION init LEVEL SMP) +zephyr_linker_section(NAME deferred_init_list KVMA RAM_REGION GROUP RODATA_REGION) +zephyr_linker_section_configure(SECTION deferred_init_list INPUT ".z_deferred_init*" KEEP SORT NAME) + zephyr_iterable_section(NAME device NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_GEN_SW_ISR_TABLE AND NOT CONFIG_DYNAMIC_INTERRUPTS) From 02f6d486e08152a8a32814838b8675e84dbcdce3 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0515/1389] tests: kernel: device: Add CMAKE_LINKER_GENERATOR test case Add a test case entry with CONFIG_CMAKE_LINKER_GENERATOR enabled. Signed-off-by: Pieter De Gendt --- tests/kernel/device/testcase.yaml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/kernel/device/testcase.yaml b/tests/kernel/device/testcase.yaml index 931f2635d600b5..6946518b2bed0a 100644 --- a/tests/kernel/device/testcase.yaml +++ b/tests/kernel/device/testcase.yaml @@ -1,28 +1,32 @@ common: tags: - device + - kernel - userspace - integration_platforms: - - native_sim tests: kernel.device: - tags: - - kernel - - device + integration_platforms: + - native_sim platform_exclude: xenvm kernel.device.minimallibc: + integration_platforms: + - native_sim filter: CONFIG_MINIMAL_LIBC_SUPPORTED tags: - - kernel - - device - libc extra_configs: - CONFIG_MINIMAL_LIBC=y platform_exclude: xenvm kernel.device.pm: - tags: - - kernel - - device + integration_platforms: + - native_sim platform_exclude: mec15xxevb_assy6853 xenvm extra_configs: - CONFIG_PM_DEVICE=y + kernel.device.linker_generator: + platform_allow: + - qemu_cortex_m3 + tags: + - linker_generator + extra_configs: + - CONFIG_CMAKE_LINKER_GENERATOR=y From 05a75824235ac6070ebbf2c75b6bf2637981ba2d Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:52 +0200 Subject: [PATCH 0516/1389] cmake: linker_script: Fix cmake linker for some networking Iterable sections for CoAP services and network management events were missing. Signed-off-by: Pieter De Gendt --- cmake/linker_script/common/common-rom.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index af9715fe20b221..125d438b58b298 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -209,6 +209,14 @@ if (CONFIG_HTTP_SERVER) zephyr_iterable_section(NAME http_service_desc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() +if (CONFIG_COAP_SERVER) + zephyr_iterable_section(NAME coap_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +endif() + +if (CONFIG_NET_MGMT) + zephyr_iterable_section(NAME net_mgmt_event_static_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +endif() + if(CONFIG_INPUT) zephyr_iterable_section(NAME input_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() From af743541261923f5f00d6a419bc2100432833294 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0517/1389] samples: net: sockets: coap_server: Support CMAKE_LINKER_GENERATOR Add support for the CMake linker generator. Signed-off-by: Pieter De Gendt --- samples/net/sockets/coap_server/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/samples/net/sockets/coap_server/CMakeLists.txt b/samples/net/sockets/coap_server/CMakeLists.txt index 17d207098254be..932e3cfdeebeaa 100644 --- a/samples/net/sockets/coap_server/CMakeLists.txt +++ b/samples/net/sockets/coap_server/CMakeLists.txt @@ -8,4 +8,11 @@ FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) +# Support LD linker template zephyr_linker_sources(DATA_SECTIONS sections-ram.ld) + +# Support CMake linker generator +zephyr_iterable_section( + NAME coap_resource_coap_server + GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} + SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) From f44684b736f0791d31f4b063a89354198c4f1400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0518/1389] dts: common: nordic: add ieee802154 node to nrf54h20 cpuapp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds an ieee802154 node to the list of nRF54H20 application core's peripherals. While it does not translate directly into a physical RADIO peripheral, it represents the capability to use the ieee802154 radio indirectly through cpurad. Signed-off-by: Jędrzej Ciupis --- dts/common/nordic/nrf54h20.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 809dcd62ae426a..7436f9b936db57 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -178,6 +178,11 @@ status = "disabled"; interrupts = <21 NRF_DEFAULT_IRQ_PRIORITY>; }; + + cpuapp_ieee802154: ieee802154 { + compatible = "nordic,nrf-ieee802154"; + status = "disabled"; + }; }; cpurad_peripherals: peripheral@53000000 { From aff4d5b2701c2f225bf9ae7ae47e329dd0b758f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0519/1389] boards: nordic: nrf54h20pdk: add ieee802154 radio to chosen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the ieee802154 node to chosen for nRF54H20 PDK and enables it. Signed-off-by: Jędrzej Ciupis --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 5 +++++ boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index fd838f3757df9e..22877e4e8d3245 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -24,6 +24,7 @@ zephyr,flash = &mram1x; zephyr,sram = &cpuapp_data; zephyr,shell-uart = &uart136; + zephyr,ieee802154 = &cpuapp_ieee802154; zephyr,bt-hci-ipc = &ipc0; }; @@ -224,3 +225,7 @@ ipc0: &cpuapp_cpurad_ipc { t-exit-dpd = <30000>; }; }; + +&cpuapp_ieee802154 { + status = "okay"; +}; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index ad08596f600aad..dba929c04cf1a8 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -25,6 +25,7 @@ zephyr,flash = &mram1x; zephyr,sram = &cpurad_ram0; zephyr,shell-uart = &uart135; + zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; }; }; @@ -98,3 +99,7 @@ ipc0: &cpuapp_cpurad_ipc { pinctrl-1 = <&uart136_sleep>; pinctrl-names = "default", "sleep"; }; + +&cpurad_ieee802154 { + status = "okay"; +}; From a1f530de070fb6e3f15db47de74b97b20cfe4783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0520/1389] drivers: ieee802154: nrf5: fix default value for nRF54H20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default value of IEEE802154_NRF5_DELAY_TRX_ACC Kconfig option is based on a symbol that is undefined for nRF54H20. It evaluates as empty, which leads to compilation errors with very cryptic logs. This commit assures that a sane value for IEEE802154_NRF5_DELAY_TRX_ACC is selected at all times, avoiding the compilation errors. Signed-off-by: Jędrzej Ciupis --- drivers/ieee802154/Kconfig.nrf5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ieee802154/Kconfig.nrf5 b/drivers/ieee802154/Kconfig.nrf5 index 9acb811e6b6025..43217f8d37a3f5 100644 --- a/drivers/ieee802154/Kconfig.nrf5 +++ b/drivers/ieee802154/Kconfig.nrf5 @@ -72,7 +72,7 @@ config IEEE802154_NRF5_FCS_IN_LENGTH config IEEE802154_NRF5_DELAY_TRX_ACC int "Clock accuracy for delayed operations" - default CLOCK_CONTROL_NRF_ACCURACY if CLOCK_CONTROL_NRF_ACCURACY < 255 + default CLOCK_CONTROL_NRF_ACCURACY if (CLOCK_CONTROL_NRF && (CLOCK_CONTROL_NRF_ACCURACY < 255)) default 255 help Accuracy of the clock used for scheduling radio delayed operations (delayed transmission From 3d1726ef4638acc19c0ee168df5933394ae88462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0521/1389] modules: hal_nordic: add missing glue for nRF54H20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing #ifdef in nrfx_glue for nRF54H20. Signed-off-by: Jędrzej Ciupis --- modules/hal_nordic/nrfx/nrfx_glue.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 593aff6fcc7a3a..15a1f076063d2b 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -368,6 +368,10 @@ void nrfx_busy_wait(uint32_t usec_to_wait); #include <../src/nrf_802154_peripherals_nrf54l.h> #define NRFX_PPI_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK #define NRFX_PPI_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#elif defined(NRF54H_SERIES) +#include <../src/nrf_802154_peripherals_nrf54h.h> +#define NRFX_PPI_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_PPI_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK #else #error Unsupported chip family #endif From d0cf1bdabc55bcdf2637fa20f138016de3defcb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0522/1389] boards: nordic: nrf54h20dk: enable 802.15.4 IPC by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable hardware necessary for 802.15.4 IPC on nRF54H20 DK by default. Signed-off-by: Jędrzej Ciupis --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 1 + boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 22877e4e8d3245..476c076fae115f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -26,6 +26,7 @@ zephyr,shell-uart = &uart136; zephyr,ieee802154 = &cpuapp_ieee802154; zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; }; aliases { diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index dba929c04cf1a8..20109b66180e6f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -27,6 +27,7 @@ zephyr,shell-uart = &uart135; zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; }; }; From 175cbc4d1a6bda16f3ff6e4859dd4d4607818619 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0523/1389] tests: misc: iterable_sections: Add CMake linker test case Add a test with CONFIG_CMAKE_LINKER_GENERATOR enabled. Signed-off-by: Pieter De Gendt --- tests/misc/iterable_sections/testcase.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/misc/iterable_sections/testcase.yaml b/tests/misc/iterable_sections/testcase.yaml index eeba6274530c07..f193cdb6c54368 100644 --- a/tests/misc/iterable_sections/testcase.yaml +++ b/tests/misc/iterable_sections/testcase.yaml @@ -1,4 +1,12 @@ +common: + tags: iterable_sections + tests: linker.iterable_sections: - tags: iterable_sections arch_exclude: xtensa + + linker.iterable_sections.linker_generator: + platform_allow: qemu_cortex_m3 + tags: linker_generator + extra_configs: + - CONFIG_CMAKE_LINKER_GENERATOR=y From 2b715d2eb6b66e64b31c988582bd65efc5dc37cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0524/1389] dts: bindings: serial: nrf-uart: current-speed shall be required MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding required flag to the current-speed as without this driver does not compile. Signed-off-by: Krzysztof Chruściński --- dts/bindings/serial/nordic,nrf-uart-common.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/bindings/serial/nordic,nrf-uart-common.yaml b/dts/bindings/serial/nordic,nrf-uart-common.yaml index fa68a195cd6875..b985b7bc96309f 100644 --- a/dts/bindings/serial/nordic,nrf-uart-common.yaml +++ b/dts/bindings/serial/nordic,nrf-uart-common.yaml @@ -17,6 +17,7 @@ properties: if CONFIG_PINCTRL is enabled). current-speed: + required: true description: | Initial baud rate setting for UART. Only a fixed set of baud rates are selectable on these devices. From 2bbc9baf546637479cf59afcd6c0ce0d0765f372 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0525/1389] ITE: soc: Kconfig: Cleanup it8xxx2 Kconfig The ILM_MAX_SIZE of different chip variants can be declared in the Kconfig of the respective variant. Signed-off-by: Tim Lin --- soc/ite/ec/it8xxx2/Kconfig | 1 - soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202cx | 3 +++ soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302cx | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/soc/ite/ec/it8xxx2/Kconfig b/soc/ite/ec/it8xxx2/Kconfig index 5043f1fa3b233e..0e7e4751b5e23a 100644 --- a/soc/ite/ec/it8xxx2/Kconfig +++ b/soc/ite/ec/it8xxx2/Kconfig @@ -193,7 +193,6 @@ config SOC_IT8XXX2_FLASH_SIZE_BYTES config ILM_MAX_SIZE int "ILM Size in kB" - default 60 if SOC_IT81202CX || SOC_IT81302CX default SRAM_SIZE endif # SOC_SERIES_IT8XXX2 diff --git a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202cx b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202cx index 91f992f076ef72..abbeecd53d6ab0 100644 --- a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202cx +++ b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202cx @@ -3,6 +3,9 @@ if SOC_IT81202CX +config ILM_MAX_SIZE + default 60 + config SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN default y diff --git a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302cx b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302cx index 85e1a212f6a1ab..c6d9608490d397 100644 --- a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302cx +++ b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302cx @@ -3,6 +3,9 @@ if SOC_IT81302CX +config ILM_MAX_SIZE + default 60 + config SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN default n From 5409de98775dda034f117bc5e6cd54eeafc91a31 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0526/1389] ITE: soc: Add the variant of it81202dx Add the variant of it81202dx Signed-off-by: Tim Lin --- dts/riscv/ite/it81202dx.dtsi | 16 ++++++++++++++++ soc/ite/ec/it8xxx2/Kconfig | 4 ++++ soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202dx | 12 ++++++++++++ soc/ite/ec/it8xxx2/Kconfig.soc | 5 +++++ soc/ite/ec/soc.yml | 1 + 5 files changed, 38 insertions(+) create mode 100644 dts/riscv/ite/it81202dx.dtsi create mode 100644 soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202dx diff --git a/dts/riscv/ite/it81202dx.dtsi b/dts/riscv/ite/it81202dx.dtsi new file mode 100644 index 00000000000000..73f577d814a46d --- /dev/null +++ b/dts/riscv/ite/it81202dx.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + sram0: memory@80100000 { + compatible = "mmio-sram"; + reg = <0x80100000 DT_SIZE_K(128)>; + }; + }; +}; diff --git a/soc/ite/ec/it8xxx2/Kconfig b/soc/ite/ec/it8xxx2/Kconfig index 0e7e4751b5e23a..ad8a06a3d8e0db 100644 --- a/soc/ite/ec/it8xxx2/Kconfig +++ b/soc/ite/ec/it8xxx2/Kconfig @@ -59,6 +59,10 @@ config SOC_IT81202CX select SOC_IT8XXX2_REG_SET_V1 select SOC_IT8XXX2_USBPD_PHY_V2 +config SOC_IT81202DX + select SOC_IT8XXX2_REG_SET_V1 + select SOC_IT8XXX2_USBPD_PHY_V2 + config SOC_IT82202AX select SOC_IT8XXX2_REG_SET_V2 select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED diff --git a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202dx b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202dx new file mode 100644 index 00000000000000..48fed80f1c2977 --- /dev/null +++ b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81202dx @@ -0,0 +1,12 @@ +# Copyright (c) 2024 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_IT81202DX + +config ILM_MAX_SIZE + default 60 + +config SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN + default y + +endif diff --git a/soc/ite/ec/it8xxx2/Kconfig.soc b/soc/ite/ec/it8xxx2/Kconfig.soc index 2ff1bc17953fd2..2f272533e95260 100644 --- a/soc/ite/ec/it8xxx2/Kconfig.soc +++ b/soc/ite/ec/it8xxx2/Kconfig.soc @@ -27,6 +27,10 @@ config SOC_IT81202CX bool select SOC_IT8XXX2 +config SOC_IT81202DX + bool + select SOC_IT8XXX2 + config SOC_IT82202AX bool select SOC_IT8XXX2 @@ -53,6 +57,7 @@ config SOC_SERIES config SOC default "it81202bx" if SOC_IT81202BX default "it81202cx" if SOC_IT81202CX + default "it81202dx" if SOC_IT81202DX default "it81302bx" if SOC_IT81302BX default "it81302cx" if SOC_IT81302CX default "it82002aw" if SOC_IT82002AW diff --git a/soc/ite/ec/soc.yml b/soc/ite/ec/soc.yml index b462d75ecd360e..dc0ab56669e11d 100644 --- a/soc/ite/ec/soc.yml +++ b/soc/ite/ec/soc.yml @@ -5,6 +5,7 @@ family: socs: - name: it81202bx - name: it81202cx + - name: it81202dx - name: it81302bx - name: it81302cx - name: it82002aw From 90bbbfbf3835b8e04f9c000c6b6c6151799c0a09 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0527/1389] ITE: soc: Add the variant of it81302dx Add the variant of it81302dx Signed-off-by: Tim Lin --- dts/riscv/ite/it81302dx.dtsi | 16 ++++++++++++++++ soc/ite/ec/it8xxx2/Kconfig | 4 ++++ soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302dx | 12 ++++++++++++ soc/ite/ec/it8xxx2/Kconfig.soc | 5 +++++ soc/ite/ec/soc.yml | 1 + 5 files changed, 38 insertions(+) create mode 100644 dts/riscv/ite/it81302dx.dtsi create mode 100644 soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302dx diff --git a/dts/riscv/ite/it81302dx.dtsi b/dts/riscv/ite/it81302dx.dtsi new file mode 100644 index 00000000000000..73f577d814a46d --- /dev/null +++ b/dts/riscv/ite/it81302dx.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + sram0: memory@80100000 { + compatible = "mmio-sram"; + reg = <0x80100000 DT_SIZE_K(128)>; + }; + }; +}; diff --git a/soc/ite/ec/it8xxx2/Kconfig b/soc/ite/ec/it8xxx2/Kconfig index ad8a06a3d8e0db..089115dc4898fd 100644 --- a/soc/ite/ec/it8xxx2/Kconfig +++ b/soc/ite/ec/it8xxx2/Kconfig @@ -59,6 +59,10 @@ config SOC_IT81202CX select SOC_IT8XXX2_REG_SET_V1 select SOC_IT8XXX2_USBPD_PHY_V2 +config SOC_IT81302DX + select SOC_IT8XXX2_REG_SET_V1 + select SOC_IT8XXX2_USBPD_PHY_V2 + config SOC_IT81202DX select SOC_IT8XXX2_REG_SET_V1 select SOC_IT8XXX2_USBPD_PHY_V2 diff --git a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302dx b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302dx new file mode 100644 index 00000000000000..d774e6a455b109 --- /dev/null +++ b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it81302dx @@ -0,0 +1,12 @@ +# Copyright (c) 2024 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_IT81302DX + +config ILM_MAX_SIZE + default 60 + +config SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN + default n + +endif diff --git a/soc/ite/ec/it8xxx2/Kconfig.soc b/soc/ite/ec/it8xxx2/Kconfig.soc index 2f272533e95260..0da984253c81e4 100644 --- a/soc/ite/ec/it8xxx2/Kconfig.soc +++ b/soc/ite/ec/it8xxx2/Kconfig.soc @@ -27,6 +27,10 @@ config SOC_IT81202CX bool select SOC_IT8XXX2 +config SOC_IT81302DX + bool + select SOC_IT8XXX2 + config SOC_IT81202DX bool select SOC_IT8XXX2 @@ -60,6 +64,7 @@ config SOC default "it81202dx" if SOC_IT81202DX default "it81302bx" if SOC_IT81302BX default "it81302cx" if SOC_IT81302CX + default "it81302dx" if SOC_IT81302DX default "it82002aw" if SOC_IT82002AW default "it82202ax" if SOC_IT82202AX default "it82302ax" if SOC_IT82302AX diff --git a/soc/ite/ec/soc.yml b/soc/ite/ec/soc.yml index dc0ab56669e11d..ff1b221f2ad611 100644 --- a/soc/ite/ec/soc.yml +++ b/soc/ite/ec/soc.yml @@ -8,6 +8,7 @@ family: - name: it81202dx - name: it81302bx - name: it81302cx + - name: it81302dx - name: it82002aw - name: it82202ax - name: it82302ax From b59a7294c9292a416560c2eda9811d31244de3e0 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0528/1389] ITE: soc: Add the variant of it82002bw Add the variant of it82002bw Signed-off-by: Tim Lin --- soc/ite/ec/it8xxx2/Kconfig | 5 +++++ soc/ite/ec/it8xxx2/Kconfig.defconfig.it82002bw | 9 +++++++++ soc/ite/ec/it8xxx2/Kconfig.soc | 5 +++++ soc/ite/ec/soc.yml | 1 + 4 files changed, 20 insertions(+) create mode 100644 soc/ite/ec/it8xxx2/Kconfig.defconfig.it82002bw diff --git a/soc/ite/ec/it8xxx2/Kconfig b/soc/ite/ec/it8xxx2/Kconfig index 089115dc4898fd..38b92c9c6b8ed6 100644 --- a/soc/ite/ec/it8xxx2/Kconfig +++ b/soc/ite/ec/it8xxx2/Kconfig @@ -82,6 +82,11 @@ config SOC_IT82002AW select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED select SOC_IT8XXX2_USBPD_PHY_V2 +config SOC_IT82002BW + select SOC_IT8XXX2_REG_SET_V2 + select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED + select SOC_IT8XXX2_USBPD_PHY_V2 + config SOC_IT82202BW select SOC_IT8XXX2_REG_SET_V2 select SOC_IT8XXX2_EC_BUS_24MHZ if !DT_HAS_ITE_IT82XX2_USB_ENABLED diff --git a/soc/ite/ec/it8xxx2/Kconfig.defconfig.it82002bw b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it82002bw new file mode 100644 index 00000000000000..6bd70e438f97a7 --- /dev/null +++ b/soc/ite/ec/it8xxx2/Kconfig.defconfig.it82002bw @@ -0,0 +1,9 @@ +# Copyright (c) 2024 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_IT82002BW + +config SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN + default y + +endif diff --git a/soc/ite/ec/it8xxx2/Kconfig.soc b/soc/ite/ec/it8xxx2/Kconfig.soc index 0da984253c81e4..96504021f23833 100644 --- a/soc/ite/ec/it8xxx2/Kconfig.soc +++ b/soc/ite/ec/it8xxx2/Kconfig.soc @@ -47,6 +47,10 @@ config SOC_IT82002AW bool select SOC_IT8XXX2 +config SOC_IT82002BW + bool + select SOC_IT8XXX2 + config SOC_IT82202BW bool select SOC_IT8XXX2 @@ -66,6 +70,7 @@ config SOC default "it81302cx" if SOC_IT81302CX default "it81302dx" if SOC_IT81302DX default "it82002aw" if SOC_IT82002AW + default "it82002bw" if SOC_IT82002BW default "it82202ax" if SOC_IT82202AX default "it82302ax" if SOC_IT82302AX default "it82202bw" if SOC_IT82202BW diff --git a/soc/ite/ec/soc.yml b/soc/ite/ec/soc.yml index ff1b221f2ad611..b73270535f931a 100644 --- a/soc/ite/ec/soc.yml +++ b/soc/ite/ec/soc.yml @@ -10,6 +10,7 @@ family: - name: it81302cx - name: it81302dx - name: it82002aw + - name: it82002bw - name: it82202ax - name: it82302ax - name: it82202bw From 5862075aa5701495a39f71560f344d13829b2b98 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0529/1389] twister: Set default coverage platform only when needed Set options.coverage_platform only when running coverage. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/environment.py | 2 +- scripts/pylib/twister/twisterlib/testplan.py | 2 -- scripts/tests/twister/test_testplan.py | 9 --------- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 43c05750bf8456..09ddaa973f8182 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -782,7 +782,7 @@ def parse_arguments(parser, args, options = None): if options.coverage: options.enable_coverage = True - if not options.coverage_platform: + if options.enable_coverage and not options.coverage_platform: options.coverage_platform = options.platform if options.coverage_formats: diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 5fd292fd4bc63b..d27e7196843f04 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -387,8 +387,6 @@ def report_test_list(self): print(" - {}".format(test)) print("{} total.".format(cnt)) - def config(self): - logger.info("coverage platform: {}".format(self.coverage_platform)) # Debug Functions @staticmethod diff --git a/scripts/tests/twister/test_testplan.py b/scripts/tests/twister/test_testplan.py index 600cde4c1a6db6..7f93629922365b 100644 --- a/scripts/tests/twister/test_testplan.py +++ b/scripts/tests/twister/test_testplan.py @@ -1058,15 +1058,6 @@ def test_testplan_report_test_list(capfd): '10 total.' in out -def test_testplan_config(caplog): - testplan = TestPlan(env=mock.Mock()) - testplan.coverage_platform = 'dummy cov' - - testplan.config() - - assert 'coverage platform: dummy cov' in caplog.text - - def test_testplan_info(capfd): TestPlan.info('dummy text') From b71fc785d54dff2f59a885058ccfebd3b0874beb Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0530/1389] boards: st: nucleo_wba55cg: add 'zephyr,bt-c2h-uart' Include 'zephyr,bt-c2h-uart' in 'chosen' node to make it possible to use HCI raw mode over UART. This was tested on real board with 'hci_uart' sample, with Linux machine as a host (kernel 6.8, BlueZ 5.75). Signed-off-by: Piotr Dymacz --- boards/st/nucleo_wba55cg/nucleo_wba55cg.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts index 88dd4083209f4f..f956270a8529a6 100644 --- a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts +++ b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts @@ -19,6 +19,7 @@ #size-cells = <1>; chosen { + zephyr,bt-c2h-uart = &usart1; zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,sram = &sram0; From fc434104c5c770de3bde025c1da215ed97a554ef Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0531/1389] drivers: udc_dwc2: handle interrupt IEPINT before the RXFLVL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During a control read transfer host is able to start status stage as soon as it receives last data packet. The time between last data packet and status stage can be approximately 1 us at High-Speed and 8 us at Full-Speed (exact timing depends on host but it is mostly constrained by bus turnaround time). With sufficient interrupt latency it is therefore possible that both IEPINT (raised at end of Data Stage) and RXFLVL (raised at Status Stage) would be set when dwc2 interrupt handler reads GINTSTS register. When device is operating at High-Speed, the latency introduced by UART logger backend is enough to trigger this condition. If the RXFLVL is handled before IEPINT the stack will trigger "Cannot determine the next stage" error. Handle IEPINT before RXFLVL to make the handler immune to increased interrupt latencies. Co-authored-by: Tomasz Moń Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_dwc2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 0c1463e979801c..8f5547d36c79a4 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -888,16 +888,16 @@ static void udc_dwc2_isr_handler(const struct device *dev) udc_submit_event(dev, UDC_EVT_RESUME, 0); } - if (int_status & USB_DWC2_GINTSTS_RXFLVL) { - /* Handle RxFIFO Non-Empty interrupt */ - dwc2_handle_rxflvl(dev); - } - if (int_status & USB_DWC2_GINTSTS_IEPINT) { /* Handle IN Endpoints interrupt */ dwc2_handle_iepint(dev); } + if (int_status & USB_DWC2_GINTSTS_RXFLVL) { + /* Handle RxFIFO Non-Empty interrupt */ + dwc2_handle_rxflvl(dev); + } + if (int_status & USB_DWC2_GINTSTS_OEPINT) { /* Handle OUT Endpoints interrupt */ dwc2_handle_oepint(dev); From b01d8d329e6c4bf70e5d4cf60ead05cd8c4adf45 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0532/1389] manifest: update quicklogic HAL Update quicklogic HAL to fix compilation errors when C++ support is enabled. Fixes #72604. Signed-off-by: Jordan Yates --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 55bfac7ae334cc..801f1fd6e6794c 100644 --- a/west.yml +++ b/west.yml @@ -203,7 +203,7 @@ manifest: groups: - hal - name: hal_quicklogic - revision: b3a66fe6d04d87fd1533a5c8de51d0599fcd08d0 + revision: bad894440fe72c814864798c8e3a76d13edffb6c path: modules/hal/quicklogic repo-path: hal_quicklogic groups: From db7d733d494ea532914bee86592b03d295cdfda2 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0533/1389] board: mimx93_evk_a55: disable gpio expander by default This commit is to fix some GPIO test case build issue: https://github.com/zephyrproject-rtos/zephyr/issues/72619 In fact, the issue is introduce by expander GPIO PR: https://github.com/zephyrproject-rtos/zephyr/pull/69330 It is used to add GPIO expander support, in this PR, dts node layout is: lpi2c { MFD driver { gpio driver { } } } The initial idea is to disable all these node by default in order to keep a minimal default image, but expander GPIO PR only disabled lpi2c and MFD driver node, but enabled gpio driver node, so gpio driver will report building error as it depends on expander and i2c which are disabled, so this fix is to disable gpio node. If we want to use expander gpio, we need to enable i2c, expander and gpio nodes simultaneously. Some GPIO test cases have been enabled on i.mx93 EVK board by enabling onchip GPIO controller in the overlay, for example: tests/drivers/gpio/gpio_basic_api/boards/imx93_evk_mimx9352_a55.overlay Signed-off-by: Jiafei Pan --- boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts index 40faba8411719d..cd025a547e717f 100644 --- a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts +++ b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts @@ -119,6 +119,7 @@ line-name = "exp_sel"; output-low; }; + status = "disabled"; }; }; }; From 69249c2fdf98804944cbad8240572e0956eb446a Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:53 +0200 Subject: [PATCH 0534/1389] tests: flash_simulator: fix devicetree indentation Fix the mix of spaces and tabs in the `nucleo_f411re.overlay` file. Signed-off-by: Jordan Yates --- .../boards/nucleo_f411re.overlay | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/drivers/flash_simulator/boards/nucleo_f411re.overlay b/tests/drivers/flash_simulator/boards/nucleo_f411re.overlay index bbe0f8dabe1035..60ce2f36e21879 100644 --- a/tests/drivers/flash_simulator/boards/nucleo_f411re.overlay +++ b/tests/drivers/flash_simulator/boards/nucleo_f411re.overlay @@ -5,35 +5,35 @@ */ / { - sram_2001C000:sram@2001C000 { + sram_2001C000:sram@2001C000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x2001C000 0x4000>; zephyr,memory-region = "FlashSim"; status = "okay"; - }; + }; - soc { - sim_flash_controller: sim-flash-controller@0 { - compatible = "zephyr,sim-flash"; - reg = <0x0 0x1>; + soc { + sim_flash_controller: sim-flash-controller@0 { + compatible = "zephyr,sim-flash"; + reg = <0x0 0x1>; #address-cells = <1>; - #size-cells = <1>; - erase-value = <0xff>; - memory-region = <&sram_2001C000>; + #size-cells = <1>; + erase-value = <0xff>; + memory-region = <&sram_2001C000>; flash_sim0: flash_sim@0 { - status = "okay"; - compatible = "soc-nv-flash"; - erase-block-size = <512>; + status = "okay"; + compatible = "soc-nv-flash"; + erase-block-size = <512>; /* the flash_simulator test uses a write block * size of 4 for alignment test, so set it to 4. */ - write-block-size = <4>; - reg = <0x00000000 DT_SIZE_K(16)>; - }; - }; - }; + write-block-size = <4>; + reg = <0x00000000 DT_SIZE_K(16)>; + }; + }; + }; }; &flash_sim0 { From 88c7c2d09d71ef97d38b07b569c3b89bf80ce55f Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0535/1389] tests: flash_simulator: move to subfolder Move the implementation test to a subfolder so an additional test can be added. Signed-off-by: Jordan Yates --- tests/drivers/flash_simulator/{ => flash_sim_impl}/CMakeLists.txt | 0 .../{ => flash_sim_impl}/boards/native_64_ev_0x00.overlay | 0 .../{ => flash_sim_impl}/boards/native_ev_0x00.overlay | 0 .../{ => flash_sim_impl}/boards/native_posix.overlay | 0 .../{ => flash_sim_impl}/boards/native_posix_native_64.overlay | 0 .../{ => flash_sim_impl}/boards/native_sim.overlay | 0 .../{ => flash_sim_impl}/boards/native_sim_native_64.overlay | 0 .../{ => flash_sim_impl}/boards/nucleo_f411re.overlay | 0 .../{ => flash_sim_impl}/boards/qemu_x86_ev_0x00.overlay | 0 tests/drivers/flash_simulator/{ => flash_sim_impl}/prj.conf | 0 tests/drivers/flash_simulator/{ => flash_sim_impl}/src/main.c | 0 tests/drivers/flash_simulator/{ => flash_sim_impl}/testcase.yaml | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/CMakeLists.txt (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/native_64_ev_0x00.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/native_ev_0x00.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/native_posix.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/native_posix_native_64.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/native_sim.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/native_sim_native_64.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/nucleo_f411re.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/boards/qemu_x86_ev_0x00.overlay (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/prj.conf (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/src/main.c (100%) rename tests/drivers/flash_simulator/{ => flash_sim_impl}/testcase.yaml (100%) diff --git a/tests/drivers/flash_simulator/CMakeLists.txt b/tests/drivers/flash_simulator/flash_sim_impl/CMakeLists.txt similarity index 100% rename from tests/drivers/flash_simulator/CMakeLists.txt rename to tests/drivers/flash_simulator/flash_sim_impl/CMakeLists.txt diff --git a/tests/drivers/flash_simulator/boards/native_64_ev_0x00.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/native_64_ev_0x00.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/native_64_ev_0x00.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/native_64_ev_0x00.overlay diff --git a/tests/drivers/flash_simulator/boards/native_ev_0x00.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/native_ev_0x00.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/native_ev_0x00.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/native_ev_0x00.overlay diff --git a/tests/drivers/flash_simulator/boards/native_posix.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/native_posix.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/native_posix.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/native_posix.overlay diff --git a/tests/drivers/flash_simulator/boards/native_posix_native_64.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/native_posix_native_64.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/native_posix_native_64.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/native_posix_native_64.overlay diff --git a/tests/drivers/flash_simulator/boards/native_sim.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/native_sim.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/native_sim.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/native_sim.overlay diff --git a/tests/drivers/flash_simulator/boards/native_sim_native_64.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/native_sim_native_64.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/native_sim_native_64.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/native_sim_native_64.overlay diff --git a/tests/drivers/flash_simulator/boards/nucleo_f411re.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/nucleo_f411re.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/nucleo_f411re.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/nucleo_f411re.overlay diff --git a/tests/drivers/flash_simulator/boards/qemu_x86_ev_0x00.overlay b/tests/drivers/flash_simulator/flash_sim_impl/boards/qemu_x86_ev_0x00.overlay similarity index 100% rename from tests/drivers/flash_simulator/boards/qemu_x86_ev_0x00.overlay rename to tests/drivers/flash_simulator/flash_sim_impl/boards/qemu_x86_ev_0x00.overlay diff --git a/tests/drivers/flash_simulator/prj.conf b/tests/drivers/flash_simulator/flash_sim_impl/prj.conf similarity index 100% rename from tests/drivers/flash_simulator/prj.conf rename to tests/drivers/flash_simulator/flash_sim_impl/prj.conf diff --git a/tests/drivers/flash_simulator/src/main.c b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c similarity index 100% rename from tests/drivers/flash_simulator/src/main.c rename to tests/drivers/flash_simulator/flash_sim_impl/src/main.c diff --git a/tests/drivers/flash_simulator/testcase.yaml b/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml similarity index 100% rename from tests/drivers/flash_simulator/testcase.yaml rename to tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml From 6d045c8c146ba62aff696af3e5d10a70a9705c4c Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0536/1389] tests: flash_simulator: reboot: added Add a test for the flash simulator preserving memory across a `sys_reboot` through the use of memory regions. Signed-off-by: Jordan Yates --- .../flash_sim_reboot/CMakeLists.txt | 12 +++++ .../boards/mps2_an385.overlay | 27 ++++++++++ .../flash_simulator/flash_sim_reboot/prj.conf | 4 ++ .../flash_sim_reboot/src/main.c | 54 +++++++++++++++++++ .../flash_sim_reboot/testcase.yaml | 10 ++++ 5 files changed, 107 insertions(+) create mode 100644 tests/drivers/flash_simulator/flash_sim_reboot/CMakeLists.txt create mode 100644 tests/drivers/flash_simulator/flash_sim_reboot/boards/mps2_an385.overlay create mode 100644 tests/drivers/flash_simulator/flash_sim_reboot/prj.conf create mode 100644 tests/drivers/flash_simulator/flash_sim_reboot/src/main.c create mode 100644 tests/drivers/flash_simulator/flash_sim_reboot/testcase.yaml diff --git a/tests/drivers/flash_simulator/flash_sim_reboot/CMakeLists.txt b/tests/drivers/flash_simulator/flash_sim_reboot/CMakeLists.txt new file mode 100644 index 00000000000000..6f4d8151e35191 --- /dev/null +++ b/tests/drivers/flash_simulator/flash_sim_reboot/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2018 Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(flash_simulator_reboot) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/flash_simulator/flash_sim_reboot/boards/mps2_an385.overlay b/tests/drivers/flash_simulator/flash_sim_reboot/boards/mps2_an385.overlay new file mode 100644 index 00000000000000..8672ce0e8eb5a4 --- /dev/null +++ b/tests/drivers/flash_simulator/flash_sim_reboot/boards/mps2_an385.overlay @@ -0,0 +1,27 @@ +#include + +/ { + sram_203F0000:sram@203F0000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x203F0000 0x10000>; + zephyr,memory-region = "FlashSim"; + status = "okay"; + }; + + sim_flash_controller: sim_flash_controller { + compatible = "zephyr,sim-flash"; + + #address-cells = <1>; + #size-cells = <1>; + erase-value = <0xff>; + memory-region = <&sram_203F0000>; + + flash_sim0: flash_sim@0 { + compatible = "soc-nv-flash"; + reg = <0x00000000 0x10000>; + + erase-block-size = <1024>; + write-block-size = <4>; + }; + }; +}; diff --git a/tests/drivers/flash_simulator/flash_sim_reboot/prj.conf b/tests/drivers/flash_simulator/flash_sim_reboot/prj.conf new file mode 100644 index 00000000000000..4e78174c5c6ca2 --- /dev/null +++ b/tests/drivers/flash_simulator/flash_sim_reboot/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y +CONFIG_FLASH=y +CONFIG_FLASH_SIMULATOR=y +CONFIG_REBOOT=y diff --git a/tests/drivers/flash_simulator/flash_sim_reboot/src/main.c b/tests/drivers/flash_simulator/flash_sim_reboot/src/main.c new file mode 100644 index 00000000000000..93c0b9c9654010 --- /dev/null +++ b/tests/drivers/flash_simulator/flash_sim_reboot/src/main.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define MAGIC_WORD 0xABDE2134 + +#define SOC_NV_FLASH_NODE DT_CHILD(DT_INST(0, zephyr_sim_flash), flash_sim_0) +#define FLASH_SIMULATOR_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE) + +static const struct device *const flash_dev = DEVICE_DT_GET(DT_NODELABEL(sim_flash_controller)); +static uint32_t boot_count __noinit; + +ZTEST(flash_sim_reboot, test_preserve_over_reboot) +{ + uint32_t word = MAGIC_WORD; + int rc; + + if (boot_count == 0) { + printk("First boot, erasing flash\n"); + rc = flash_erase(flash_dev, 0, FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "Failed to erase flash"); + printk("Writing magic word to offset 0\n"); + rc = flash_write(flash_dev, 0, &word, sizeof(word)); + zassert_equal(0, rc, "Failed to write flash"); + printk("Rebooting device...\n"); + boot_count += 1; + sys_reboot(SYS_REBOOT_WARM); + zassert_unreachable("Failed to reboot"); + } else if (boot_count == 1) { + printk("Second boot, reading magic word\n"); + rc = flash_read(flash_dev, 0, &word, sizeof(word)); + zassert_equal(0, rc, "Failed to read flash"); + zassert_equal(MAGIC_WORD, word, "Magic word not preserved"); + } else { + zassert_unreachable("Unexpected boot_count value %d", boot_count); + } +} + +void *flash_sim_setup(void) +{ + zassert_true(device_is_ready(flash_dev), "Simulated flash device not ready"); + + return NULL; +} + +ZTEST_SUITE(flash_sim_reboot, NULL, flash_sim_setup, NULL, NULL, NULL); diff --git a/tests/drivers/flash_simulator/flash_sim_reboot/testcase.yaml b/tests/drivers/flash_simulator/flash_sim_reboot/testcase.yaml new file mode 100644 index 00000000000000..069bbac09c936b --- /dev/null +++ b/tests/drivers/flash_simulator/flash_sim_reboot/testcase.yaml @@ -0,0 +1,10 @@ +common: + tags: + - drivers + - flash +tests: + drivers.flash.flash_simulator.boot_no_erase: + timeout: 5 + platform_allow: mps2/an385 + integration_platforms: + - mps2/an385 From ce67742c05f6354484ac93967b3083d7260ee510 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0537/1389] drivers: nsos: fcntl: prefer Zephyr-specific macros over libc Definitions of fcntl flags are different between native libc and Zephyr. In order to correctly map those values to the host, include Zephyr's fcntl.h header, instead of the one bundled with libc. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_fcntl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/nsos_fcntl.c b/drivers/net/nsos_fcntl.c index be49d3ec63e579..ab4d22ce51a245 100644 --- a/drivers/net/nsos_fcntl.c +++ b/drivers/net/nsos_fcntl.c @@ -16,7 +16,14 @@ * symbols. */ +/* + * When building for Zephyr, use Zephyr specific fcntl definitions. + */ +#ifdef __ZEPHYR__ +#include +#else #include +#endif #include "nsos_errno.h" #include "nsos_fcntl.h" From 8b197374d16db4a45975afc93ece8f68fad8caca Mon Sep 17 00:00:00 2001 From: Arkadiusz Cholewinski Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0538/1389] CI: Fix coverage reporting The fix applies to parse_testplan function. Signed-off-by: Arkadiusz Cholewinski --- scripts/ci/coverage/coverage_analysis.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/ci/coverage/coverage_analysis.py b/scripts/ci/coverage/coverage_analysis.py index 34ce99c98549e3..1d446aded78819 100644 --- a/scripts/ci/coverage/coverage_analysis.py +++ b/scripts/ci/coverage/coverage_analysis.py @@ -69,7 +69,8 @@ def parse_testplan(self, testplan_path): break sub_component_name = testcase_name[testcase_name.find('.'):] sub_component_name = sub_component_name[1:] - sub_component_name = sub_component_name[:sub_component_name.find(".")] + if sub_component_name.find(".") > 0: + sub_component_name = sub_component_name[:sub_component_name.find(".")] if known_component_flag is False: sub_component = { From 8f28d1a3aaf1d5d0f922e42216948ff6239611d5 Mon Sep 17 00:00:00 2001 From: Noah Pendleton Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0539/1389] buildsystem: Add an option to compress debug sections Compressing debug sections can reduce the output ELF file size substantially. Signed-off-by: Noah Pendleton --- CMakeLists.txt | 11 +++++++++++ Kconfig.zephyr | 5 +++++ cmake/bintools/bintools_template.cmake | 2 ++ cmake/bintools/gnu/target_bintools.cmake | 3 +++ cmake/bintools/llvm/target_bintools.cmake | 3 +++ 5 files changed, 24 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f654bf224b8d1..ad65b6a1d1f8fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1792,6 +1792,17 @@ if(CONFIG_BUILD_OUTPUT_STRIPPED) ) endif() +if(CONFIG_BUILD_OUTPUT_COMPRESS_DEBUG_SECTIONS) + list(APPEND + post_build_commands + COMMAND $ + $ + $ + $${KERNEL_ELF_NAME} + $ +) +endif() + if(CONFIG_BUILD_OUTPUT_EXE) if (NOT CONFIG_NATIVE_LIBRARY) list(APPEND diff --git a/Kconfig.zephyr b/Kconfig.zephyr index fd9076a38d94f6..e44cd327cb5f08 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -784,6 +784,11 @@ config BUILD_OUTPUT_STRIPPED Build a stripped binary zephyr/zephyr.strip in the build directory. The name of this file can be customized with CONFIG_KERNEL_BIN_NAME. +config BUILD_OUTPUT_COMPRESS_DEBUG_SECTIONS + bool "Compress debug sections in the ELF file" + help + Compress debug sections in the ELF file to reduce the file size. + config BUILD_OUTPUT_ADJUST_LMA string help diff --git a/cmake/bintools/bintools_template.cmake b/cmake/bintools/bintools_template.cmake index 4b48ffe005ad12..6fa63080dd9215 100644 --- a/cmake/bintools/bintools_template.cmake +++ b/cmake/bintools/bintools_template.cmake @@ -66,6 +66,7 @@ # elfconvert_flag_final : Flags that must always be applied last at the elfconvert command # elfconvert_flag_strip_all : Flag that is used for stripping all symbols when converting # elfconvert_flag_strip_debug : Flag that is used to strip debug symbols when converting +# elfconvert_flag_compress_debug_sections: Flag that is used to compress debug sections when converting # elfconvert_flag_intarget : Flag for specifying target used for infile # elfconvert_flag_outtarget : Flag for specifying target to use for converted file. # Target value must be one of those listed described by: elfconvert_formats @@ -141,6 +142,7 @@ set_property(TARGET bintools PROPERTY elfconvert_command ${CMAKE_COMMAND} -E ech set_property(TARGET bintools PROPERTY elfconvert_formats "") set_property(TARGET bintools PROPERTY elfconvert_flag "") set_property(TARGET bintools PROPERTY elfconvert_flag_final "") +set_property(TARGET bintools PROPERTY elfconvert_flag_compress_debug_sections "") set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "") set_property(TARGET bintools PROPERTY elfconvert_flag_section_remove "") set_property(TARGET bintools PROPERTY elfconvert_flag_gapfill "") diff --git a/cmake/bintools/gnu/target_bintools.cmake b/cmake/bintools/gnu/target_bintools.cmake index 8aac55b0400cdc..f61860b31da555 100644 --- a/cmake/bintools/gnu/target_bintools.cmake +++ b/cmake/bintools/gnu/target_bintools.cmake @@ -7,6 +7,7 @@ # elfconvert_flag_final : empty # elfconvert_flag_strip_all : -S # elfconvert_flag_strip_debug : -g +# elfconvert_flag_compress_debug_sections: --compress-debug-sections # elfconvert_flag_intarget : --input-target= # elfconvert_flag_outtarget : --output-target= # elfconvert_flag_section_remove: --remove-section= @@ -34,6 +35,8 @@ set_property(TARGET bintools PROPERTY elfconvert_flag_final "") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-S") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_debug "-g") +set_property(TARGET bintools PROPERTY elfconvert_flag_compress_debug_sections "--compress-debug-sections") + set_property(TARGET bintools PROPERTY elfconvert_flag_intarget "--input-target=") set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "--output-target=") diff --git a/cmake/bintools/llvm/target_bintools.cmake b/cmake/bintools/llvm/target_bintools.cmake index 3a3e04e4388c18..cd3d55342b5d87 100644 --- a/cmake/bintools/llvm/target_bintools.cmake +++ b/cmake/bintools/llvm/target_bintools.cmake @@ -7,6 +7,7 @@ # elfconvert_flag_final : empty # elfconvert_flag_strip_all : -S # elfconvert_flag_strip_debug : -g +# elfconvert_flag_compress_debug_sections: --compress-debug-sections # elfconvert_flag_intarget : --input-target= # elfconvert_flag_outtarget : --output-target= # elfconvert_flag_section_remove: --remove-section= @@ -34,6 +35,8 @@ set_property(TARGET bintools PROPERTY elfconvert_flag_final "") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-S") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_debug "-g") +set_property(TARGET bintools PROPERTY elfconvert_flag_compress_debug_sections "--compress-debug-sections") + set_property(TARGET bintools PROPERTY elfconvert_flag_intarget "--input-target=") set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "--output-target=") From dcd9b2ec14d2e88e185af50fdc4dd294c8e11264 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0540/1389] cmake: Set C compile features early for modules If modules require C compiler features, these need to be set before calling add_subdirectory. Signed-off-by: Pieter De Gendt --- CMakeLists.txt | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad65b6a1d1f8fa..b589ac43159bb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,26 @@ if(CONFIG_LTO) add_link_options($) endif() +if(CONFIG_STD_C23) + set(CSTD c2x) +elseif(CONFIG_STD_C17) + set(CSTD c17) +elseif(CONFIG_STD_C11) + set(CSTD c11) +elseif(CONFIG_STD_C99) + set(CSTD c99) +elseif(CONFIG_STD_C90) + set(CSTD c90) +else() + message(FATAL_ERROR "Unreachable code. Expected C standard to have been chosen.") +endif() + +if(CONFIG_GNU_C_EXTENSIONS) + string(REPLACE "c" "gnu" CSTD "${CSTD}") +endif() + +list(APPEND CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}}) + # @Intent: Obtain compiler specific flags related to C++ that are not influenced by kconfig zephyr_compile_options($<$:$>) @@ -956,35 +976,19 @@ if(CONFIG_USERSPACE) set(PROCESS_GPERF ${ZEPHYR_BASE}/scripts/build/process_gperf.py) endif() -get_property(CSTD GLOBAL PROPERTY CSTD) -if(NOT DEFINED CSTD) - if(CONFIG_STD_C23) - set(CSTD c2x) - elseif(CONFIG_STD_C17) - set(CSTD c17) - elseif(CONFIG_STD_C11) - set(CSTD c11) - elseif(CONFIG_STD_C99) - set(CSTD c99) - elseif(CONFIG_STD_C90) - set(CSTD c90) - else() - message(FATAL_ERROR "Unreachable code. Expected C standard to have been chosen.") - endif() - - if(CONFIG_GNU_C_EXTENSIONS) - string(REPLACE "c" "gnu" CSTD "${CSTD}") - endif() -else() +get_property(GLOBAL_CSTD GLOBAL PROPERTY CSTD) +if(DEFINED GLOBAL_CSTD) message(DEPRECATION "Global CSTD property is deprecated, see Kconfig.zephyr for C Standard options.") + set(CSTD ${GLOBAL_CSTD}) + list(APPEND CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}}) endif() # @Intent: Obtain compiler specific flag for specifying the c standard zephyr_compile_options( $<$:$${CSTD}> ) -set(CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}} PARENT_SCOPE) +set(CMAKE_C_COMPILE_FEATURES ${CMAKE_C_COMPILE_FEATURES} PARENT_SCOPE) # @Intent: Configure linker scripts, i.e. generate linker scripts with variables substituted toolchain_ld_configure_files() From 2fa79952c7d161649eb30d4a4865a77b27249a93 Mon Sep 17 00:00:00 2001 From: Daniel Apperloo Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0541/1389] linker: decouple KERNEL_WHOLE_ARCHIVE from LLEXT Dynamic code execution applications not using LLEXT for "extension" loading are subject to the same linker optimization symbol resolution issue described in commit 321e395 (in summary, libkernel.a syscalls not used directly by the application result in weak symbol resolution of their z_mrsh_ wrapper). To support usecases where an application is using alternative methods to load and execute code calling syscalls (likely from userspace) or is using a mechanism where the linker may not be aware, the configuration option has been decoupled from CONFIG_LLEXT (who is now a selector) to KERNEL_WHOLE_ARCHIVE. Signed-off-by: Daniel Apperloo --- CMakeLists.txt | 2 +- kernel/Kconfig | 6 ++++++ subsys/llext/Kconfig | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b589ac43159bb4..2fa2d371c4ab8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -906,7 +906,7 @@ foreach(zephyr_lib ${ZEPHYR_LIBS_PROPERTY}) add_dependencies(${zephyr_lib} zephyr_generated_headers) endforeach() -if(CONFIG_LLEXT) +if(CONFIG_KERNEL_WHOLE_ARCHIVE) set(WHOLE_ARCHIVE_LIBS ${ZEPHYR_LIBS_PROPERTY} kernel) else() set(WHOLE_ARCHIVE_LIBS ${ZEPHYR_LIBS_PROPERTY}) diff --git a/kernel/Kconfig b/kernel/Kconfig index af51267edbf1fc..767c04f94fe47c 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -1020,6 +1020,12 @@ config THREAD_LOCAL_STORAGE help This option enables thread local storage (TLS) support in kernel. +config KERNEL_WHOLE_ARCHIVE + bool + help + This option forces every object file in the libkernel.a archive + to be included, rather than searching the archive for required object files. + endmenu rsource "Kconfig.device" diff --git a/subsys/llext/Kconfig b/subsys/llext/Kconfig index c96017c79c9f14..085ef775569591 100644 --- a/subsys/llext/Kconfig +++ b/subsys/llext/Kconfig @@ -4,6 +4,7 @@ menuconfig LLEXT bool "Linkable loadable extensions" select CACHE_MANAGEMENT if DCACHE + select KERNEL_WHOLE_ARCHIVE help Enable the linkable loadable extension subsystem From 225164b6eba86505a1a998da972dd88db17c4d87 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0542/1389] west.yaml: hal_stm32: STM32Cube packages update Update STM32Cube packages: update stm32u5 to cube version V1.5.0 update stm32wb to cube version V1.19.0 update stm32f4 to cube version V1.28.0 update stm32g0 to cube version V1.6.2 update stm32h5 to cube version V1.2.0 update stm32l5 to cube version V1.5.1 update stm32g4 to cube version V1.5.2 update stm32h7 to cube version V1.11.2 Update of lib/stm32/stm32wb package to version V1.19.0 Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 801f1fd6e6794c..825f15f4c4d261 100644 --- a/west.yml +++ b/west.yml @@ -229,7 +229,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: 60c9634f61c697e1c310ec648d33529712806069 + revision: ed93098718d5c727d2fac5ef27023a2a14763e32 path: modules/hal/stm32 groups: - hal From bf535a75a93511d97ae4e6317fd0d564d99d1424 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0543/1389] drivers: pwm: pwm_stm32: F4X changes Use "const LL_TIM_IC_GetCaptureCHx" & "const LL_TIM_IsActiveFlag_CCx" with STM32F4X series, following changes in stm32cube:stm32f4xx:drivers: include:stm32f4xx_ll_tim.h Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/pwm/pwm_stm32.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index c8e44633ad5f9c..8a589261aa3d20 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -141,8 +141,7 @@ static void (*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to capture get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ +#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t __maybe_unused (*const get_channel_capture[])(const TIM_TypeDef *) = { #else @@ -166,8 +165,7 @@ static void __maybe_unused (*const disable_capture_interrupt[])(TIM_TypeDef *) = }; /** Channel to is capture active flag mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ +#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t __maybe_unused (*const is_capture_active[])(const TIM_TypeDef *) = { #else From 5116ba22c577de0ab51ac00f2a889b4e35b0396e Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0544/1389] drivers: counter: ll_stm32_timer: F4X changes Use "const LL_TIM_OC_GetCompareCHx" & "const LL_TIM_IsEnabledIT_CCx" with STM32F4X series, following changes in stm32cube:stm32f4xx:drivers: include:stm32f4xx_ll_tim.h Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/counter/counter_ll_stm32_timer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/counter/counter_ll_stm32_timer.c b/drivers/counter/counter_ll_stm32_timer.c index 869b31a31f7a05..0a061d777a9224 100644 --- a/drivers/counter/counter_ll_stm32_timer.c +++ b/drivers/counter/counter_ll_stm32_timer.c @@ -42,8 +42,7 @@ static void(*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to compare get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ +#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const get_timer_compare[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_OC_GetCompareCH1, LL_TIM_OC_GetCompareCH2, @@ -69,8 +68,7 @@ static void(*const disable_it[TIMER_MAX_CH])(TIM_TypeDef *) = { #ifdef CONFIG_ASSERT /** Channel to interrupt enable check function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ +#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const check_it_enabled[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_IsEnabledIT_CC1, LL_TIM_IsEnabledIT_CC2, From f9caf637d4176b28b639acef2fedea40880660ff Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0545/1389] drivers: dma: G0X changes Use "const LL_DMA_IsActiveFlag_HTx", "const LL_DMA_IsActiveFlag_TEx", "const LL_DMA_IsActiveFlag_TCx" and "const LL_DMA_IsActiveFlag_GIx" with STM32G0X series, following changes in stm32cube:stm32g0xx:drivers: include:stm32g0xx_ll_dma.h Use "const LL_DMAMUX_IsActiveFlag_SOx","const LL_DMAMUX_IsActiveFlag_RGOx" "const LL_DMAMUX_ClearFlag_SOx" and "const LL_DMAMUX_ClearFlag_RGOx" with STM32G0X series, following changes in stm32cube:stm32g0xx:drivers: include:stm32g0xx_ll_dmamux.h Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/dma/dma_stm32.h | 4 ++++ drivers/dma/dmamux_stm32.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/dma/dma_stm32.h b/drivers/dma/dma_stm32.h index f21cb07e1834c1..553e09838d84d2 100644 --- a/drivers/dma/dma_stm32.h +++ b/drivers/dma/dma_stm32.h @@ -52,7 +52,11 @@ uint32_t dma_stm32_slot_to_channel(uint32_t id); #endif typedef void (*dma_stm32_clear_flag_func)(DMA_TypeDef *DMAx); +#if !defined(CONFIG_SOC_SERIES_STM32G0X) typedef uint32_t (*dma_stm32_check_flag_func)(DMA_TypeDef *DMAx); +#else +typedef uint32_t (*dma_stm32_check_flag_func)(const DMA_TypeDef *DMAx); +#endif bool dma_stm32_is_tc_active(DMA_TypeDef *DMAx, uint32_t id); void dma_stm32_clear_tc(DMA_TypeDef *DMAx, uint32_t id); diff --git a/drivers/dma/dmamux_stm32.c b/drivers/dma/dmamux_stm32.c index bca6514190e64c..d12a294eb7ff13 100644 --- a/drivers/dma/dmamux_stm32.c +++ b/drivers/dma/dmamux_stm32.c @@ -70,19 +70,24 @@ uint32_t table_ll_channel[] = { LISTIFY(DT_INST_PROP(0, dma_channels), DMAMUX_CHANNEL, (,)) }; -uint32_t (*func_ll_is_active_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +#if !defined(CONFIG_SOC_SERIES_STM32G0X) +#define dmamux_channel_typedef DMAMUX_Channel_TypeDef +#else +#define dmamux_channel_typedef const DMAMUX_Channel_TypeDef +#endif +uint32_t (*func_ll_is_active_so[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_channels), IS_ACTIVE_FLAG_SOX, (,)) }; -void (*func_ll_clear_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +void (*func_ll_clear_so[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_channels), CLEAR_FLAG_SOX, (,)) }; -uint32_t (*func_ll_is_active_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +uint32_t (*func_ll_is_active_rgo[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_generators), IS_ACTIVE_FLAG_RGOX, (,)) }; -void (*func_ll_clear_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +void (*func_ll_clear_rgo[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_generators), CLEAR_FLAG_RGOX, (,)) }; From 3b94c1afe545a5b5c5b66bfa17d66b5e001c6958 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0546/1389] drivers: pwm: pwm_stm32: G4X changes Use "const LL_TIM_IC_GetCaptureCHx" & "const LL_TIM_IsActiveFlag_CCx" with STM32G4X series, following changes in stm32cube:stm32g4xx:drivers: include:stm32g4xx_ll_tim.h Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/pwm/pwm_stm32.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index 8a589261aa3d20..70006e377b1b07 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -141,8 +141,7 @@ static void (*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to capture get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t __maybe_unused (*const get_channel_capture[])(const TIM_TypeDef *) = { #else static uint32_t __maybe_unused (*const get_channel_capture[])(TIM_TypeDef *) = { @@ -165,8 +164,7 @@ static void __maybe_unused (*const disable_capture_interrupt[])(TIM_TypeDef *) = }; /** Channel to is capture active flag mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t __maybe_unused (*const is_capture_active[])(const TIM_TypeDef *) = { #else static uint32_t __maybe_unused (*const is_capture_active[])(TIM_TypeDef *) = { From d2b946e7707c30a3ab317eb453672a4989813283 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0547/1389] drivers: counter: ll_stm32_timer: G4X changes Use "const LL_TIM_OC_GetCompareCHx" & "const LL_TIM_IsEnabledIT_CCx" with STM32G4X series, following changes in stm32cube:stm32g4xx:drivers: include:stm32g4xx_ll_tim.h Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/counter/counter_ll_stm32_timer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/counter/counter_ll_stm32_timer.c b/drivers/counter/counter_ll_stm32_timer.c index 0a061d777a9224..8f6b1ffd1f43ab 100644 --- a/drivers/counter/counter_ll_stm32_timer.c +++ b/drivers/counter/counter_ll_stm32_timer.c @@ -42,8 +42,7 @@ static void(*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to compare get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const get_timer_compare[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_OC_GetCompareCH1, LL_TIM_OC_GetCompareCH2, LL_TIM_OC_GetCompareCH3, LL_TIM_OC_GetCompareCH4, @@ -68,8 +67,7 @@ static void(*const disable_it[TIMER_MAX_CH])(TIM_TypeDef *) = { #ifdef CONFIG_ASSERT /** Channel to interrupt enable check function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const check_it_enabled[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_IsEnabledIT_CC1, LL_TIM_IsEnabledIT_CC2, LL_TIM_IsEnabledIT_CC3, LL_TIM_IsEnabledIT_CC4, From b3f7af0691977513f1c4b31fd85a66e66f026cd2 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0548/1389] samples: modules: canopennode: make sample configurations depend on nvs Make two of the CANopenNode sample configurations depend on "nvs" instead of trying to establish a local rule for which boards have the needed functionality. Signed-off-by: Henrik Brix Andersen --- samples/modules/canopennode/sample.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/samples/modules/canopennode/sample.yaml b/samples/modules/canopennode/sample.yaml index 7cc95c0ed179c3..f85c50138bda5c 100644 --- a/samples/modules/canopennode/sample.yaml +++ b/samples/modules/canopennode/sample.yaml @@ -15,15 +15,10 @@ common: - "(.*)CANopen stack initialized" tests: sample.modules.canopennode: - filter: dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") - and dt_chosen_enabled("zephyr,flash-controller") and CONFIG_FLASH_HAS_DRIVER_ENABLED - platform_exclude: - - nucleo_h723zg - - nucleo_h743zi - - nucleo_h745zi_q/stm32h745xx/m7 - - nucleo_h753zi + depends_on: nvs sample.modules.canopennode.program_download: sysbuild: true + depends_on: nvs platform_allow: - frdm_k64f - twr_ke18f From 3aadaeab29b668d45acf0dd0e16fbbc48683fb83 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Sun, 26 May 2024 22:38:54 +0200 Subject: [PATCH 0549/1389] bluetooth: host: conn: Fix assertion failure in wait_for_tx_work Calling bt_disable in system workqueue context while BLE connected may lead to calling wait_for_tx_work in this context. Fix check in code to avoid assertion failure. Signed-off-by: Marek Pieta --- subsys/bluetooth/host/conn.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 76686ce996569e..8caebcc4c3c347 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -383,18 +383,13 @@ static void wait_for_tx_work(struct bt_conn *conn) #if defined(CONFIG_BT_CONN_TX) LOG_DBG("conn %p", conn); - if (IS_ENABLED(CONFIG_BT_RECV_WORKQ_SYS)) { + if (IS_ENABLED(CONFIG_BT_RECV_WORKQ_SYS) || + k_current_get() == k_work_queue_thread_get(&k_sys_work_q)) { tx_notify(conn); } else { struct k_work_sync sync; int err; - /* API docs mention undefined behavior if syncing on work item - * from wq execution context. - */ - __ASSERT_NO_MSG(k_current_get() != - k_work_queue_thread_get(&k_sys_work_q)); - err = k_work_submit(&conn->tx_complete_work); __ASSERT(err >= 0, "couldn't submit (err %d)", err); From 8a0d2ed042d1cc8b608bda021537a37466d28a60 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0550/1389] tests: net: sockets: tls: Add missing teardown delays A few tests involving TCP were missing TCP teardown delay. Adding these improves tests stability when testing in a loop for longer periods (i. e. with CONFIG_ZTEST_SHUFFLE enabled). Signed-off-by: Robert Lubos --- tests/net/socket/tls/src/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/net/socket/tls/src/main.c b/tests/net/socket/tls/src/main.c index 59bad541f1c5b3..f532060f8f555b 100644 --- a/tests/net/socket/tls/src/main.c +++ b/tests/net/socket/tls/src/main.c @@ -842,6 +842,7 @@ ZTEST(net_socket_tls, test_close_while_accept) zassert_equal(errno, EINTR, "Unexpected errno value: %d", errno); test_work_wait(&close_work_data.work); + k_sleep(TCP_TEARDOWN_TIMEOUT); } ZTEST(net_socket_tls, test_close_while_recv) @@ -1057,6 +1058,7 @@ ZTEST(net_socket_tls, test_accept_non_block) zassert_equal(errno, EAGAIN, "Unexpected errno value: %d", errno); test_sockets_close(); + k_sleep(TCP_TEARDOWN_TIMEOUT); } ZTEST(net_socket_tls, test_accept_invalid_handshake_data) @@ -1081,6 +1083,7 @@ ZTEST(net_socket_tls, test_accept_invalid_handshake_data) zassert_equal(errno, ECONNABORTED, "Unexpected errno value: %d", errno); test_sockets_close(); + k_sleep(TCP_TEARDOWN_TIMEOUT); } ZTEST(net_socket_tls, test_recv_non_block) From 9c6bc05f5d1e2efa2def88755637fb19621bf2c8 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0551/1389] drivers: flash: RRAMC regions Adding definition of regions granularity to Kconfig. Signed-off-by: Mateusz Michalek --- drivers/flash/Kconfig.nrf_rram | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index 025b0791010fe9..a729b57bc288db 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -67,4 +67,17 @@ config SOC_FLASH_NRF_TIMEOUT_MULTIPLIER the multiplication would allow erasing all nRF flash pages in blocking mode. +config NRF_RRAM_REGION_ADDRESS_RESOLUTION + hex + default 0x400 + help + RRAMC's region protection address resolution. + Applies to region with configurable start address. + +config NRF_RRAM_REGION_SIZE_UNIT + hex + default 0x400 + help + Base unit for the size of RRAMC's region protection. + endif # SOC_FLASH_NRF_RRAM From 8873704f9cc1176b26a682e8480835d0cb9d4625 Mon Sep 17 00:00:00 2001 From: Balaji Srinivasan Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0552/1389] drivers: regulator: npm6001: Fix compiler warning This patch fixes a compiler warning about the val being used uninitialized. The previously present if check did not seem to satisfy compiler. Hence the val is now explictly initialized. Signed-off-by: Balaji Srinivasan --- drivers/regulator/regulator_npm6001.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/regulator_npm6001.c b/drivers/regulator/regulator_npm6001.c index 1b854cbf830595..2ade708271adcb 100644 --- a/drivers/regulator/regulator_npm6001.c +++ b/drivers/regulator/regulator_npm6001.c @@ -211,7 +211,7 @@ static int regulator_npm6001_ldo0_set_voltage(const struct device *dev, int32_t int32_t max_uv) { const struct regulator_npm6001_config *config = dev->config; - uint8_t val; + uint8_t val = 0U; size_t i; for (i = 0U; i < ARRAY_SIZE(ldo0_voltages); i++) { From 24cec56eb7ee09da76c2488a2534dacc60b8fb92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0553/1389] net: http: client: mark as unstable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the http client API is currently used by two applications (websocket and hawkbit), it should be marked as unstable, according to the docs: https://docs.zephyrproject.org/latest/develop/api/api_lifecycle.html Signed-off-by: Fin Maaß --- include/zephyr/net/http/client.h | 2 ++ subsys/net/lib/http/Kconfig | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/zephyr/net/http/client.h b/include/zephyr/net/http/client.h index e1ff3e63b9a86b..6a95004001f42b 100644 --- a/include/zephyr/net/http/client.h +++ b/include/zephyr/net/http/client.h @@ -16,6 +16,8 @@ /** * @brief HTTP client API * @defgroup http_client HTTP client API + * @since 2.1 + * @version 0.2.0 * @ingroup networking * @{ */ diff --git a/subsys/net/lib/http/Kconfig b/subsys/net/lib/http/Kconfig index 3df70b84a84a13..9926b9b1d383a1 100644 --- a/subsys/net/lib/http/Kconfig +++ b/subsys/net/lib/http/Kconfig @@ -23,10 +23,9 @@ config HTTP_PARSER_STRICT This option enables the strict parsing option config HTTP_CLIENT - bool "HTTP client API [EXPERIMENTAL]" + bool "HTTP client API" select HTTP_PARSER select HTTP_PARSER_URL - select EXPERIMENTAL help HTTP client API From 67e460cf27025ae4918bd248e3cdc9f7491e92bc Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0554/1389] doc: releases: Enforce linking to Pull Requests in migration guide In order to provide additional context and information to Zephyr users, ensure that each entry in the migration guide contains a link to the GitHub Pull Request that introduced the corresponding change. Signed-off-by: Carles Cufi --- doc/releases/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/releases/index.rst b/doc/releases/index.rst index 544f721994bf3e..4310b11d5d8c34 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -103,6 +103,10 @@ in the migration guide. This includes: - Anything else that can affect the compilation or runtime behavior of an existing application +Each entry in the migration guide must include a brief explanation of the change +as well as refer to the Pull Request that introduced it, in order for the user +to be able to understand the context of the change. + .. toctree:: :maxdepth: 1 :glob: From f283a627899a384fc5d9bef8f71f1833df1b7673 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0555/1389] doc: migration: 3.7: Add missing links to GitHub Pull Requests To provide further context for users. Signed-off-by: Carles Cufi --- doc/releases/migration-guide-3.7.rst | 73 ++++++++++++++-------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 3471a1a9a9d2dd..73f3e5ccaf809b 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -20,7 +20,7 @@ Build System * Completely overhauled the way SoCs and boards are defined. This requires all out-of-tree SoCs and boards to be ported to the new model. See the - :ref:`hw_model_v2` for more detailed information. + :ref:`hw_model_v2` for more detailed information. (:github:`69607`) Kernel ****** @@ -29,12 +29,12 @@ Boards ****** * Reordered D1 and D0 in the `pro_micro` connector gpio-map for SparkFun Pro Micro RP2040 to match - original Pro Micro definition. Out-of-tree shields must be updated to reflect this change. + original Pro Micro definition. Out-of-tree shields must be updated to reflect this change. (:github:`69994`) * ITE: Rename all SoC variant Kconfig options, e.g., ``CONFIG_SOC_IT82202_AX`` is renamed to ``CONFIG_SOC_IT82202AX``. All symbols are renamed as follows: ``SOC_IT81202BX``, ``SOC_IT81202CX``, ``SOC_IT81302BX``, ``SOC_IT81302CX``, ``SOC_IT82002AW``, ``SOC_IT82202AX``, ``SOC_IT82302AX``. - And, rename the ``SOC_SERIES_ITE_IT8XXX2`` to ``SOC_SERIES_IT8XXX2``. + And, rename the ``SOC_SERIES_ITE_IT8XXX2`` to ``SOC_SERIES_IT8XXX2``. (:github:`71680`) Modules ******* @@ -60,7 +60,7 @@ Device Drivers and Devicetree compatible :dtcompatible:`nxp,pit-channel` and configure as below. The :kconfig:option:`CONFIG_COUNTER_MCUX_PIT` has also been renamed to :kconfig:option:`CONFIG_COUNTER_NXP_PIT` with regards to the renaming - of the binding for the pit. + of the binding for the pit. (:github:`66336`) example: .. code-block:: devicetree @@ -87,8 +87,8 @@ Device Drivers and Devicetree in DT, which also comes with a different version driver. Alternatively, the Ethernet node can be deleted and redefined as the old binding to use the deprecated legacy driver. The primary advantage of the new binding - is to be able to abstract an arbitrary phy through the mdio API. Example - of a basic board level ENET DT definition: + is to be able to abstract an arbitrary phy through the mdio API. (:github:`70400`) + Example of a basic board level ENET DT definition: .. code-block:: devicetree @@ -112,7 +112,7 @@ Device Drivers and Devicetree }; }; -* Some of the driver API structs have been rename to have the required ``_driver_api`` suffix. +* Some of the driver API structs have been rename to have the required ``_driver_api`` suffix. (:github:`72182`) The following types have been renamed: * ``emul_sensor_backend_api`` to :c:struct:`emul_sensor_driver_api` @@ -120,8 +120,8 @@ Device Drivers and Devicetree * ``usbc_ppc_drv`` to :c:struct:`usbc_ppc_driver_api` * The driver for :dtcompatible:`maxim,max31790` got split up into a MFD and an - actual PWM driver. Previously, an instance of this device could have been - defined like this: + actual PWM driver. (:github:`68433`) + Previously, an instance of this device could have been defined like this: .. code-block:: devicetree @@ -160,10 +160,10 @@ Charger ======= * Dropped ``constant-charge-current-max-microamp`` property in ``charger_max20335`` driver because - it did not reflect real chip functionality. + it did not reflect real chip functionality. (:github:`69910`) * Added enum key to ``constant-charge-voltage-max-microvolt`` property in ``maxim,max20335-charger`` - binding to indicate invalid devicetree values at build time. + binding to indicate invalid devicetree values at build time. (:github:`69910`) Controller Area Network (CAN) ============================= @@ -181,7 +181,9 @@ Controller Area Network (CAN) * ``phase-seg1-data`` * ``phase-seg1-data`` -* Support for manual bus-off recovery was reworked: + (:github:`68714`) + +* Support for manual bus-off recovery was reworked (:github:`69460`): * Automatic bus recovery will always be enabled upon driver initialization regardless of Kconfig options. Since CAN controllers are initialized in "stopped" state, no unwanted bus-off recovery @@ -204,14 +206,15 @@ Display Enhanced Serial Peripheral Interface (eSPI) =========================================== - * The macros ``ESPI_SLAVE_TO_MASTER`` and ``ESPI_MASTER_TO_SLAVE`` were renamed to - ``ESPI_TARGET_TO_CONTROLLER`` and ``ESPI_CONTROLLER_TO_TARGET`` respectively to reflect - the new terminology in eSPI 1.5 specification. - * The enum values ``ESPI_VWIRE_SIGNAL_SLV_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE`` and - all ``ESPI_VWIRE_SIGNAL_SLV_GPIO_`` signals were renamed to - ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE`` and - ``ESPI_VWIRE_SIGNAL_TARGET_GPIO_`` respectively to reflect the new terminology - in eSPI 1.5 specification. + +* The macros ``ESPI_SLAVE_TO_MASTER`` and ``ESPI_MASTER_TO_SLAVE`` were renamed to + ``ESPI_TARGET_TO_CONTROLLER`` and ``ESPI_CONTROLLER_TO_TARGET`` respectively to reflect + the new terminology in eSPI 1.5 specification. + The enum values ``ESPI_VWIRE_SIGNAL_SLV_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE`` and + all ``ESPI_VWIRE_SIGNAL_SLV_GPIO_`` signals were renamed to + ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE`` and + ``ESPI_VWIRE_SIGNAL_TARGET_GPIO_`` respectively to reflect the new terminology + in eSPI 1.5 specification. (:github:`68492`) Flash ===== @@ -225,7 +228,7 @@ GNSS * Basic power management support has been added to the ``gnss-nmea-generic`` driver. If ``CONFIG_PM_DEVICE=y`` the driver is now initialized in suspended mode and the application needs to call :c:func:`pm_device_action_run` with :c:macro:`PM_DEVICE_ACTION_RESUME` - to start up the driver. + to start up the driver. (:github:`71774`) Input ===== @@ -234,11 +237,11 @@ Input relative to the raw ADC values, similarly to min and max. The data structures and properties have been renamed to reflect that (from ``out-deadzone`` to ``in-deadzone``) and when migrating to the new definition the value should be - scaled accordingly. + scaled accordingly. (:github:`70377`) * The ``holtek,ht16k33-keyscan`` driver has been converted to use the :ref:`input` subsystem, callbacks have to be migrated to use the input APIs, - :dtcompatible:`zephyr,kscan-input` can be used for backward compatibility. + :dtcompatible:`zephyr,kscan-input` can be used for backward compatibility. (:github:`69875`) Interrupt Controller ==================== @@ -247,7 +250,7 @@ LED Strip ========= * The property ``in-gpios`` defined in :dtcompatible:`worldsemi,ws2812-gpio` has been - renamed to ``gpios``. + renamed to ``gpios``. (:github:`68514`) Sensors ======= @@ -272,10 +275,10 @@ Bluetooth Mesh * The model metadata pointer declaration of :c:struct:`bt_mesh_model` has been changed to a single ``const *`` and redundant metadata pointer from :c:struct:`bt_mesh_health_srv` is removed. Consequently, :code:`BT_MESH_MODEL_HEALTH_SRV` definition is changed - to use variable argument notation. (:github:`71281`). Now, when your implementation + to use variable argument notation. Now, when your implementation supports :kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_SRV` and when you need to specify metadata for Health Server model, simply pass metadata as the last argument - to the :code:`BT_MESH_MODEL_HEALTH_SRV` macro, otherwise omit the last argument. + to the :code:`BT_MESH_MODEL_HEALTH_SRV` macro, otherwise omit the last argument. (:github:`71281`) Bluetooth Audio =============== @@ -324,8 +327,7 @@ Networking * The zperf zperf_results struct is changed to support 64 bits transferred bytes (total_len) and test duration (time_in_us and client_time_in_us), instead of 32 bits. This will make - the long-duration zperf test show with correct throughput result. - (:github:`69500`) + the long-duration zperf test show with correct throughput result. (:github:`69500`) * Each IPv4 address assigned to a network interface has an IPv4 netmask tied to it instead of being set for the whole interface. @@ -365,10 +367,9 @@ Other Subsystems hawkBit ======= - * :kconfig:option:`CONFIG_HAWKBIT_PORT` is now an int instead of a string. - - * :kconfig:option:`CONFIG_SETTINGS` needs to be enabled to use hawkBit, as it now uses the - settings subsystem to store the hawkBit configuration. +* :kconfig:option:`CONFIG_HAWKBIT_PORT` is now an int instead of a string. + :kconfig:option:`CONFIG_SETTINGS` needs to be enabled to use hawkBit, as it now uses the + settings subsystem to store the hawkBit configuration. (:github:`68806`) LoRaWAN ======= @@ -386,7 +387,7 @@ Modem ===== * The ``CONFIG_MODEM_CHAT_LOG_BUFFER`` Kconfig option was - renamed to :kconfig:option:`MODEM_CHAT_LOG_BUFFER_SIZE`. + renamed to :kconfig:option:`CONFIG_MODEM_CHAT_LOG_BUFFER_SIZE`. (:github:`70405`) Shell ===== @@ -408,19 +409,19 @@ Userspace Architectures ************* -* Function :c:func:`arch_start_cpu` has been renamed to :c:func:`arch_cpu_start`. +* Function :c:func:`arch_start_cpu` has been renamed to :c:func:`arch_cpu_start`. (:github:`64987`) * x86 * Kconfigs ``CONFIG_DISABLE_SSBD`` and ``CONFIG_ENABLE_EXTENDED_IBRS`` are deprecated. Use :kconfig:option:`CONFIG_X86_DISABLE_SSBD` and - :kconfig:option:`CONFIG_X86_ENABLE_EXTENDED_IBRS` instead. + :kconfig:option:`CONFIG_X86_ENABLE_EXTENDED_IBRS` instead. (:github:`69690`) * POSIX arch: * LLVM fuzzing support has been refactored. A test application now needs to provide its own ``LLVMFuzzerTestOneInput()`` hook instead of relying on a board provided one. Check - ``samples/subsys/debug/fuzz/`` for an example. + ``samples/subsys/debug/fuzz/`` for an example. (:github:`71378`) Xtensa ====== From 0f09fd3e746b6581e754dc71a1f05346337dd50c Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0556/1389] kernel: mmu: abstract access to page frame flags and address Introduce z_page_frame_set() and z_page_frame_clear() to manipulate flags. Obtain the virtual address using the existing z_page_frame_to_virt(). This will make changes to the page frame structure easier. Signed-off-by: Nicolas Pitre --- arch/x86/core/x86_mmu.c | 4 +- arch/xtensa/core/ptables.c | 5 +-- include/zephyr/kernel/mm/demand_paging.h | 8 ++-- kernel/include/mmu.h | 10 +++++ kernel/mmu.c | 45 ++++++++++--------- soc/intel/intel_socfpga_std/cyclonev/soc.c | 2 +- .../backing_store_qemu_x86_tiny.c | 2 +- subsys/demand_paging/eviction/nru.c | 4 +- 8 files changed, 44 insertions(+), 36 deletions(-) diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index 8591e0a8ba4454..313afbb7922e16 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -2008,9 +2008,7 @@ static void mark_addr_page_reserved(uintptr_t addr, size_t len) continue; } - struct z_page_frame *pf = z_phys_to_page_frame(pos); - - pf->flags |= Z_PAGE_FRAME_RESERVED; + z_page_frame_set(z_phys_to_page_frame(pos), Z_PAGE_FRAME_RESERVED); } } diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index d4da8366cf22f1..0628879d93302c 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -337,15 +337,12 @@ void xtensa_mmu_init(void) __weak void arch_reserved_pages_update(void) { uintptr_t page; - struct z_page_frame *pf; int idx; for (page = CONFIG_SRAM_BASE_ADDRESS, idx = 0; page < (uintptr_t)z_mapped_start; page += CONFIG_MMU_PAGE_SIZE, idx++) { - pf = &z_page_frames[idx]; - - pf->flags |= Z_PAGE_FRAME_RESERVED; + z_page_frame_set(&z_page_frames[idx], Z_PAGE_FRAME_RESERVED); } } #endif /* CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES */ diff --git a/include/zephyr/kernel/mm/demand_paging.h b/include/zephyr/kernel/mm/demand_paging.h index 35dae90a2356db..343c10478b93c8 100644 --- a/include/zephyr/kernel/mm/demand_paging.h +++ b/include/zephyr/kernel/mm/demand_paging.h @@ -267,10 +267,10 @@ void k_mem_paging_eviction_init(void); * a loaded data page may be selected, in which case its associated page frame * will have the Z_PAGE_FRAME_BACKED bit cleared (as it is no longer cached). * - * pf->addr will indicate the virtual address the page is currently mapped to. - * Large, sparse backing stores which can contain the entire address space - * may simply generate location tokens purely as a function of pf->addr with no - * other management necessary. + * z_page_frame_to_virt(pf) will indicate the virtual address the page is + * currently mapped to. Large, sparse backing stores which can contain the + * entire address space may simply generate location tokens purely as a + * function of that virtual address with no other management necessary. * * This function distinguishes whether it was called on behalf of a page * fault. A free backing store location must always be reserved in order for diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index 4afb828f4a7fcc..e1b8e3ed26c8bc 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -162,6 +162,16 @@ static inline bool z_page_frame_is_available(struct z_page_frame *page) return page->flags == 0U; } +static inline void z_page_frame_set(struct z_page_frame *pf, uint8_t flags) +{ + pf->flags |= flags; +} + +static inline void z_page_frame_clear(struct z_page_frame *pf, uint8_t flags) +{ + pf->flags &= ~flags; +} + static inline void z_assert_phys_aligned(uintptr_t phys) { __ASSERT(phys % CONFIG_MMU_PAGE_SIZE == 0U, diff --git a/kernel/mmu.c b/kernel/mmu.c index 7b283733edd6b2..47a41f242666ee 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -450,10 +450,12 @@ static void frame_mapped_set(struct z_page_frame *pf, void *addr) * Zephyr equivalent of VSDOs */ PF_ASSERT(pf, !z_page_frame_is_mapped(pf) || z_page_frame_is_pinned(pf), - "non-pinned and already mapped to %p", pf->addr); + "non-pinned and already mapped to %p", + z_page_frame_to_virt(pf)); - pf->flags |= Z_PAGE_FRAME_MAPPED; - pf->addr = addr; + z_page_frame_set(pf, Z_PAGE_FRAME_MAPPED); + pf->addr = UINT_TO_POINTER(POINTER_TO_UINT(addr) + & ~(CONFIG_MMU_PAGE_SIZE - 1)); } /* LCOV_EXCL_START */ @@ -475,7 +477,7 @@ static int virt_to_page_frame(void *virt, uintptr_t *phys) Z_PAGE_FRAME_FOREACH(paddr, pf) { if (z_page_frame_is_mapped(pf)) { - if (virt == pf->addr) { + if (virt == z_page_frame_to_virt(pf)) { ret = 0; if (phys != NULL) { *phys = z_page_frame_to_phys(pf); @@ -523,7 +525,8 @@ static int map_anon_page(void *addr, uint32_t flags) pf = k_mem_paging_eviction_select(&dirty); __ASSERT(pf != NULL, "failed to get a page frame"); - LOG_DBG("evicting %p at 0x%lx", pf->addr, + LOG_DBG("evicting %p at 0x%lx", + z_page_frame_to_virt(pf), z_page_frame_to_phys(pf)); ret = page_frame_prepare_locked(pf, &dirty, false, &location); if (ret != 0) { @@ -542,7 +545,7 @@ static int map_anon_page(void *addr, uint32_t flags) arch_mem_map(addr, phys, CONFIG_MMU_PAGE_SIZE, flags | K_MEM_CACHE_WB); if (lock) { - pf->flags |= Z_PAGE_FRAME_PINNED; + z_page_frame_set(pf, Z_PAGE_FRAME_PINNED); } frame_mapped_set(pf, addr); @@ -930,9 +933,9 @@ static void mark_linker_section_pinned(void *start_addr, void *end_addr, frame_mapped_set(pf, addr); if (pin) { - pf->flags |= Z_PAGE_FRAME_PINNED; + z_page_frame_set(pf, Z_PAGE_FRAME_PINNED); } else { - pf->flags &= ~Z_PAGE_FRAME_PINNED; + z_page_frame_clear(pf, Z_PAGE_FRAME_PINNED); } } } @@ -975,7 +978,7 @@ void z_mem_manage_init(void) * structures, and any code used to perform page fault * handling, page-ins, etc. */ - pf->flags |= Z_PAGE_FRAME_PINNED; + z_page_frame_set(pf, Z_PAGE_FRAME_PINNED); } #endif /* CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT */ @@ -1177,7 +1180,7 @@ static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr, LOG_ERR("out of backing store memory"); return -ENOMEM; } - arch_mem_page_out(pf->addr, *location_ptr); + arch_mem_page_out(z_page_frame_to_virt(pf), *location_ptr); } else { /* Shouldn't happen unless this function is mis-used */ __ASSERT(!dirty, "un-mapped page determined to be dirty"); @@ -1186,7 +1189,7 @@ static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr, /* Mark as busy so that z_page_frame_is_evictable() returns false */ __ASSERT(!z_page_frame_is_busy(pf), "page frame 0x%lx is already busy", phys); - pf->flags |= Z_PAGE_FRAME_BUSY; + z_page_frame_set(pf, Z_PAGE_FRAME_BUSY); #endif /* CONFIG_DEMAND_PAGING_ALLOW_IRQ */ /* Update dirty parameter, since we set to true if it wasn't backed * even if otherwise clean @@ -1222,7 +1225,7 @@ static int do_mem_evict(void *addr) dirty = (flags & ARCH_DATA_PAGE_DIRTY) != 0; pf = z_phys_to_page_frame(phys); - __ASSERT(pf->addr == addr, "page frame address mismatch"); + __ASSERT(z_page_frame_to_virt(pf) == addr, "page frame address mismatch"); ret = page_frame_prepare_locked(pf, &dirty, false, &location); if (ret != 0) { goto out; @@ -1294,7 +1297,7 @@ int z_page_frame_evict(uintptr_t phys) ret = 0; goto out; } - flags = arch_page_info_get(pf->addr, NULL, false); + flags = arch_page_info_get(z_page_frame_to_virt(pf), NULL, false); /* Shouldn't ever happen */ __ASSERT((flags & ARCH_DATA_PAGE_LOADED) != 0, "data page not loaded"); dirty = (flags & ARCH_DATA_PAGE_DIRTY) != 0; @@ -1480,7 +1483,7 @@ static bool do_page_fault(void *addr, bool pin) uintptr_t phys = page_in_location; pf = z_phys_to_page_frame(phys); - pf->flags |= Z_PAGE_FRAME_PINNED; + z_page_frame_set(pf, Z_PAGE_FRAME_PINNED); } /* This if-block is to pin the page if it is @@ -1500,7 +1503,8 @@ static bool do_page_fault(void *addr, bool pin) /* Need to evict a page frame */ pf = do_eviction_select(&dirty); __ASSERT(pf != NULL, "failed to get a page frame"); - LOG_DBG("evicting %p at 0x%lx", pf->addr, + LOG_DBG("evicting %p at 0x%lx", + z_page_frame_to_virt(pf), z_page_frame_to_phys(pf)); paging_stats_eviction_inc(faulting_thread, dirty); @@ -1522,14 +1526,13 @@ static bool do_page_fault(void *addr, bool pin) #ifdef CONFIG_DEMAND_PAGING_ALLOW_IRQ key = irq_lock(); - pf->flags &= ~Z_PAGE_FRAME_BUSY; + z_page_frame_clear(pf, Z_PAGE_FRAME_BUSY); #endif /* CONFIG_DEMAND_PAGING_ALLOW_IRQ */ + z_page_frame_clear(pf, Z_PAGE_FRAME_MAPPED); + frame_mapped_set(pf, addr); if (pin) { - pf->flags |= Z_PAGE_FRAME_PINNED; + z_page_frame_set(pf, Z_PAGE_FRAME_PINNED); } - pf->flags |= Z_PAGE_FRAME_MAPPED; - pf->addr = UINT_TO_POINTER(POINTER_TO_UINT(addr) - & ~(CONFIG_MMU_PAGE_SIZE - 1)); arch_mem_page_in(addr, z_page_frame_to_phys(pf)); k_mem_paging_backing_store_page_finalize(pf, page_in_location); @@ -1593,7 +1596,7 @@ static void do_mem_unpin(void *addr) "invalid data page at %p", addr); if ((flags & ARCH_DATA_PAGE_LOADED) != 0) { pf = z_phys_to_page_frame(phys); - pf->flags &= ~Z_PAGE_FRAME_PINNED; + z_page_frame_clear(pf, Z_PAGE_FRAME_PINNED); } irq_unlock(key); } diff --git a/soc/intel/intel_socfpga_std/cyclonev/soc.c b/soc/intel/intel_socfpga_std/cyclonev/soc.c index 73f7617d792e11..3adcfbab33a262 100644 --- a/soc/intel/intel_socfpga_std/cyclonev/soc.c +++ b/soc/intel/intel_socfpga_std/cyclonev/soc.c @@ -31,7 +31,7 @@ void arch_reserved_pages_update(void) } struct z_page_frame *pf = z_phys_to_page_frame(pos); - pf->flags |= Z_PAGE_FRAME_RESERVED; + z_page_frame_set(pf, Z_PAGE_FRAME_RESERVED); } } diff --git a/subsys/demand_paging/backing_store/backing_store_qemu_x86_tiny.c b/subsys/demand_paging/backing_store/backing_store_qemu_x86_tiny.c index 9f100649d49d46..28fb66fec4b474 100644 --- a/subsys/demand_paging/backing_store/backing_store_qemu_x86_tiny.c +++ b/subsys/demand_paging/backing_store/backing_store_qemu_x86_tiny.c @@ -45,7 +45,7 @@ int k_mem_paging_backing_store_location_get(struct z_page_frame *pf, bool page_fault) { /* Simply returns the virtual address */ - *location = POINTER_TO_UINT(pf->addr); + *location = POINTER_TO_UINT(z_page_frame_to_virt(pf)); return 0; } diff --git a/subsys/demand_paging/eviction/nru.c b/subsys/demand_paging/eviction/nru.c index 83c4a3b53d7651..7429b4e3fdb4d7 100644 --- a/subsys/demand_paging/eviction/nru.c +++ b/subsys/demand_paging/eviction/nru.c @@ -36,7 +36,7 @@ static void nru_periodic_update(struct k_timer *timer) } /* Clear accessed bit in page tables */ - (void)arch_page_info_get(pf->addr, NULL, true); + (void)arch_page_info_get(z_page_frame_to_virt(pf), NULL, true); } irq_unlock(key); @@ -58,7 +58,7 @@ struct z_page_frame *k_mem_paging_eviction_select(bool *dirty_ptr) continue; } - flags = arch_page_info_get(pf->addr, NULL, false); + flags = arch_page_info_get(z_page_frame_to_virt(pf), NULL, false); accessed = (flags & ARCH_DATA_PAGE_ACCESSED) != 0UL; dirty = (flags & ARCH_DATA_PAGE_DIRTY) != 0UL; From b4bc69ef9665c0d2d0fe9094428d0bea00ba4ada Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0557/1389] kernel: mmu: shrink and align struct z_page_frame The struct z_page_frame is marked __packed to avoid extra padding as such padding may represent significant memory waste when lots of page frames are used. However this is a bad strategy. The code contained this somewhat dubious comment and code in free_page_frame_list_put(): /* The structure is packed, which ensures that this is true */ void *node = pf; sys_slist_append(&free_page_frame_list, node); This is bad for many reasons: - type checking is completely bypassed; - if the sys_snode_t node member is no longer located at the front of struct z_page_frame then the code will still compile and possibly run but be broken with memory corruption as a likely outcome; - the sys_slist_append() code is completely unaware of the packed attribute which breaks architectures with alignment restrictions. Let's improve code efficiency as well as memory usage by removing the packed attribute and manually packing the flags in the unused virtual address bits. This way the page frame array remains naturally aligned, data access becomes optimal and the actual array size gets even smaller. Signed-off-by: Nicolas Pitre --- .../memory_management/demand_paging.rst | 4 + kernel/include/mmu.h | 98 +++++++++++-------- kernel/mmu.c | 37 ++++--- 3 files changed, 85 insertions(+), 54 deletions(-) diff --git a/doc/kernel/memory_management/demand_paging.rst b/doc/kernel/memory_management/demand_paging.rst index 13a04cd2833272..e870c8740e2510 100644 --- a/doc/kernel/memory_management/demand_paging.rst +++ b/doc/kernel/memory_management/demand_paging.rst @@ -53,6 +53,10 @@ Page Frame addresses. For every page frame, a ``struct z_page_frame`` is instantiated to store metadata. Flags for each page frame: + * ``Z_PAGE_FRAME_FREE`` indicates a page frame is unused and on the list of + free page frames. When this flag is set, none of the other flags are + meaningful and they must not be modified. + * ``Z_PAGE_FRAME_PINNED`` indicates a page frame is pinned in memory and should never be paged out. diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index e1b8e3ed26c8bc..ddfbdd2e16e1d8 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -9,7 +9,7 @@ #ifdef CONFIG_MMU #include -#include +#include #include #include #include @@ -64,31 +64,38 @@ /* * z_page_frame flags bits + * + * Requirements: + * - Z_PAGE_FRAME_FREE must be one of the possible sfnode flag bits + * - All bit values must be lower than CONFIG_MMU_PAGE_SIZE */ -/** This page contains critical kernel data and will never be swapped */ -#define Z_PAGE_FRAME_PINNED BIT(0) +/** This physical page is free and part of the free list */ +#define Z_PAGE_FRAME_FREE BIT(0) /** This physical page is reserved by hardware; we will never use it */ #define Z_PAGE_FRAME_RESERVED BIT(1) +/** This page contains critical kernel data and will never be swapped */ +#define Z_PAGE_FRAME_PINNED BIT(2) + /** * This physical page is mapped to some virtual memory address * * Currently, we just support one mapping per page frame. If a page frame * is mapped to multiple virtual pages then it must be pinned. */ -#define Z_PAGE_FRAME_MAPPED BIT(2) +#define Z_PAGE_FRAME_MAPPED BIT(3) /** * This page frame is currently involved in a page-in/out operation */ -#define Z_PAGE_FRAME_BUSY BIT(3) +#define Z_PAGE_FRAME_BUSY BIT(4) /** * This page frame has a clean copy in the backing store */ -#define Z_PAGE_FRAME_BACKED BIT(4) +#define Z_PAGE_FRAME_BACKED BIT(5) /** * Data structure for physical page frames @@ -98,78 +105,89 @@ */ struct z_page_frame { union { - /* If mapped, virtual address this page is mapped to */ - void *addr; - - /* If unmapped and available, free pages list membership. */ - sys_snode_t node; + /* + * If mapped, Z_PAGE_FRAME_* flags and virtual address + * this page is mapped to. + */ + uintptr_t va_and_flags; + + /* + * If unmapped and available, free pages list membership + * with the Z_PAGE_FRAME_FREE flag. + */ + sys_sfnode_t node; }; - /* Z_PAGE_FRAME_* flags */ - uint8_t flags; - - /* TODO: Backing store and eviction algorithms may both need to - * introduce custom members for accounting purposes. Come up with - * a layer of abstraction for this. They may also want additional - * flags bits which shouldn't clobber each other. At all costs - * the total size of struct z_page_frame must be minimized. + /* Backing store and eviction algorithms may both need to + * require additional per-frame custom data for accounting purposes. + * They should declare their own array with indices matching + * z_page_frames[] ones whenever possible. + * They may also want additional flags bits that could be stored here + * and they shouldn't clobber each other. At all costs the total + * size of struct z_page_frame must be minimized. */ +}; - /* On Xtensa we can't pack this struct because of the memory alignment. - */ -#ifdef CONFIG_XTENSA -} __aligned(4); -#else -} __packed; -#endif /* CONFIG_XTENSA */ +/* Note: this must be false for the other flag bits to be valid */ +static inline bool z_page_frame_is_free(struct z_page_frame *pf) +{ + return (pf->va_and_flags & Z_PAGE_FRAME_FREE) != 0U; +} static inline bool z_page_frame_is_pinned(struct z_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_PINNED) != 0U; + return (pf->va_and_flags & Z_PAGE_FRAME_PINNED) != 0U; } static inline bool z_page_frame_is_reserved(struct z_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_RESERVED) != 0U; + return (pf->va_and_flags & Z_PAGE_FRAME_RESERVED) != 0U; } static inline bool z_page_frame_is_mapped(struct z_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_MAPPED) != 0U; + return (pf->va_and_flags & Z_PAGE_FRAME_MAPPED) != 0U; } static inline bool z_page_frame_is_busy(struct z_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_BUSY) != 0U; + return (pf->va_and_flags & Z_PAGE_FRAME_BUSY) != 0U; } static inline bool z_page_frame_is_backed(struct z_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_BACKED) != 0U; + return (pf->va_and_flags & Z_PAGE_FRAME_BACKED) != 0U; } static inline bool z_page_frame_is_evictable(struct z_page_frame *pf) { - return (!z_page_frame_is_reserved(pf) && z_page_frame_is_mapped(pf) && - !z_page_frame_is_pinned(pf) && !z_page_frame_is_busy(pf)); + return (!z_page_frame_is_free(pf) && + !z_page_frame_is_reserved(pf) && + z_page_frame_is_mapped(pf) && + !z_page_frame_is_pinned(pf) && + !z_page_frame_is_busy(pf)); } -/* If true, page is not being used for anything, is not reserved, is a member - * of some free pages list, isn't busy, and may be mapped in memory +/* If true, page is not being used for anything, is not reserved, is not + * a member of some free pages list, isn't busy, and is ready to be mapped + * in memory */ static inline bool z_page_frame_is_available(struct z_page_frame *page) { - return page->flags == 0U; + return page->va_and_flags == 0U; } static inline void z_page_frame_set(struct z_page_frame *pf, uint8_t flags) { - pf->flags |= flags; + pf->va_and_flags |= flags; } static inline void z_page_frame_clear(struct z_page_frame *pf, uint8_t flags) { - pf->flags &= ~flags; + /* ensure bit inversion to follow is done on the proper type width */ + uintptr_t wide_flags = flags; + + pf->va_and_flags &= ~wide_flags; } static inline void z_assert_phys_aligned(uintptr_t phys) @@ -190,7 +208,9 @@ static inline uintptr_t z_page_frame_to_phys(struct z_page_frame *pf) /* Presumes there is but one mapping in the virtual address space */ static inline void *z_page_frame_to_virt(struct z_page_frame *pf) { - return pf->addr; + uintptr_t flags_mask = CONFIG_MMU_PAGE_SIZE - 1; + + return (void *)(pf->va_and_flags & ~flags_mask); } static inline bool z_is_page_frame(uintptr_t phys) diff --git a/kernel/mmu.c b/kernel/mmu.c index 47a41f242666ee..f74b8c7cf44540 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -81,7 +81,10 @@ static bool page_frames_initialized; /* LCOV_EXCL_START */ static void page_frame_dump(struct z_page_frame *pf) { - if (z_page_frame_is_reserved(pf)) { + if (z_page_frame_is_free(pf)) { + COLOR(GREY); + printk("-"); + } else if (z_page_frame_is_reserved(pf)) { COLOR(CYAN); printk("R"); } else if (z_page_frame_is_busy(pf)) { @@ -381,7 +384,7 @@ static void *virt_region_alloc(size_t size, size_t align) * This implies in the future there may be multiple slists managing physical * pages. Each page frame will still just have one snode link. */ -static sys_slist_t free_page_frame_list; +static sys_sflist_t free_page_frame_list; /* Number of unused and available free page frames. * This information may go stale immediately. @@ -395,15 +398,16 @@ static size_t z_free_page_count; /* Get an unused page frame. don't care which one, or NULL if there are none */ static struct z_page_frame *free_page_frame_list_get(void) { - sys_snode_t *node; + sys_sfnode_t *node; struct z_page_frame *pf = NULL; - node = sys_slist_get(&free_page_frame_list); + node = sys_sflist_get(&free_page_frame_list); if (node != NULL) { z_free_page_count--; pf = CONTAINER_OF(node, struct z_page_frame, node); - PF_ASSERT(pf, z_page_frame_is_available(pf), - "unavailable but somehow on free list"); + PF_ASSERT(pf, z_page_frame_is_free(pf), + "on free list but not free"); + pf->va_and_flags = 0; } return pf; @@ -414,21 +418,20 @@ static void free_page_frame_list_put(struct z_page_frame *pf) { PF_ASSERT(pf, z_page_frame_is_available(pf), "unavailable page put on free list"); - /* The structure is packed, which ensures that this is true */ - void *node = pf; - sys_slist_append(&free_page_frame_list, node); + sys_sfnode_init(&pf->node, Z_PAGE_FRAME_FREE); + sys_sflist_append(&free_page_frame_list, &pf->node); z_free_page_count++; } static void free_page_frame_list_init(void) { - sys_slist_init(&free_page_frame_list); + sys_sflist_init(&free_page_frame_list); } static void page_frame_free_locked(struct z_page_frame *pf) { - pf->flags = 0; + pf->va_and_flags = 0; free_page_frame_list_put(pf); } @@ -441,6 +444,8 @@ static void page_frame_free_locked(struct z_page_frame *pf) */ static void frame_mapped_set(struct z_page_frame *pf, void *addr) { + PF_ASSERT(pf, !z_page_frame_is_free(pf), + "attempted to map a page frame on the free list"); PF_ASSERT(pf, !z_page_frame_is_reserved(pf), "attempted to map a reserved page frame"); @@ -453,9 +458,11 @@ static void frame_mapped_set(struct z_page_frame *pf, void *addr) "non-pinned and already mapped to %p", z_page_frame_to_virt(pf)); - z_page_frame_set(pf, Z_PAGE_FRAME_MAPPED); - pf->addr = UINT_TO_POINTER(POINTER_TO_UINT(addr) - & ~(CONFIG_MMU_PAGE_SIZE - 1)); + uintptr_t flags_mask = CONFIG_MMU_PAGE_SIZE - 1; + uintptr_t va = (uintptr_t)addr & ~flags_mask; + + pf->va_and_flags &= flags_mask; + pf->va_and_flags |= va | Z_PAGE_FRAME_MAPPED; } /* LCOV_EXCL_START */ @@ -535,7 +542,7 @@ static int map_anon_page(void *addr, uint32_t flags) if (dirty) { do_backing_store_page_out(location); } - pf->flags = 0; + pf->va_and_flags = 0; #else return -ENOMEM; #endif /* CONFIG_DEMAND_PAGING */ From 4ec8674048dcf0f3fba9a7cb908403a227607953 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0558/1389] scripts: size_report: Fix underflow on a section end address Fix integer underflow bug on a section end address calculation causing incorrect address range for zero length sections and potential mistakes on symbol to memory area match. Signed-off-by: Dmitrii Golovanov --- scripts/footprint/size_report | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index becabeb25a98d6..a1f5c737b79787 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -185,7 +185,7 @@ def get_section_ranges(elf): for section in elf.iter_sections(): size = section['sh_size'] sec_start = section['sh_addr'] - sec_end = sec_start + size - 1 + sec_end = sec_start + (size - 1 if size else 0) bound = {'start': sec_start, 'end': sec_end} if section['sh_type'] == 'SHT_NOBITS': From d6b8a84f7190ad57f0ba7ea4ef75af956f541793 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0559/1389] scripts: size_report: Fix pylint warning on unused import Remove unused import to resolve pylint warning. Signed-off-by: Dmitrii Golovanov --- scripts/footprint/size_report | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index a1f5c737b79787..eff3d49c59103c 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -28,7 +28,6 @@ from anytree.exporter import DictExporter import elftools from elftools.elf.elffile import ELFFile -from elftools.elf.relocation import RelocationSection from elftools.elf.sections import SymbolTableSection from elftools.dwarf.descriptions import describe_form_class from elftools.dwarf.descriptions import ( From 5033883f174c0a83a639b8bedf07e0395b5118de Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0560/1389] scripts: size_report: Optimize ELF headers reading Read ELF headers only once for the size_report scirpt called for 'all' memory areas, consequently it executes 30-50% faster. Signed-off-by: Dmitrii Golovanov --- scripts/footprint/size_report | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index eff3d49c59103c..dc6791587ebb9e 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (c) 2016, 2020 Intel Corporation +# Copyright (c) 2016, 2020-2024 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 @@ -248,7 +248,7 @@ def get_die_filename(die, lineprog): return path -def do_simple_name_matching(elf, symbol_dict, processed): +def do_simple_name_matching(dwarfinfo, symbol_dict, processed): """ Sequentially process DIEs in compiler units with direct file mappings within the DIEs themselves, and do simply matching between DIE names @@ -259,7 +259,6 @@ def do_simple_name_matching(elf, symbol_dict, processed): unmapped_symbols = processed['unmapped_symbols'] newly_mapped_syms = set() - dwarfinfo = elf.get_dwarf_info() location_lists = dwarfinfo.location_lists() location_parser = LocationParser(location_lists) @@ -369,7 +368,7 @@ def mark_address_aliases(symbol_dict, processed): processed['unmapped_symbols'] = unmapped_symbols -def do_address_range_matching(elf, symbol_dict, processed): +def do_address_range_matching(dwarfinfo, symbol_dict, processed): """ Match symbols indirectly using address ranges. @@ -390,7 +389,6 @@ def do_address_range_matching(elf, symbol_dict, processed): unmapped_symbols = processed['unmapped_symbols'] newly_mapped_syms = set() - dwarfinfo = elf.get_dwarf_info() location_lists = dwarfinfo.location_lists() location_parser = LocationParser(location_lists) @@ -754,23 +752,20 @@ def main(): elif args.target == 'all': targets = ['rom', 'ram'] - for t in targets: - - elf = ELFFile(open(args.kernel, "rb")) + elf = ELFFile(open(args.kernel, "rb")) + assert elf.has_dwarf_info(), "ELF file has no DWARF information" - assert elf.has_dwarf_info(), "ELF file has no DWARF information" - - set_global_machine_arch(elf.get_machine_arch()) + set_global_machine_arch(elf.get_machine_arch()) + addr_ranges = get_section_ranges(elf) + dwarfinfo = elf.get_dwarf_info() - addr_ranges = get_section_ranges(elf) + for t in targets: symbols = get_symbols(elf, addr_ranges) for sym in symbols['unassigned'].values(): print("WARN: Symbol '{0}' is not in RAM or ROM".format(sym['name'])) - symbol_dict = None - if args.json: jsonout = args.json else: @@ -785,9 +780,9 @@ def main(): "mapped_addr": set(), "unmapped_symbols": set(symbol_dict.keys())} - do_simple_name_matching(elf, symbol_dict, processed) + do_simple_name_matching(dwarfinfo, symbol_dict, processed) mark_address_aliases(symbol_dict, processed) - do_address_range_matching(elf, symbol_dict, processed) + do_address_range_matching(dwarfinfo, symbol_dict, processed) mark_address_aliases(symbol_dict, processed) common_path_prefix = find_common_path_prefix(symbol_dict) set_root_path_for_unmapped_symbols(symbol_dict, ranges, processed) From 39bc1cb0a84e3457a070357d707d626a901ae3d2 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0561/1389] scripts: size_report: Don't set non-terminal node address Don't set 'address' property for non-terminal nodes which are also shown in JSON footprint reports, thus to avoid confusion that a file or directory node has a continuous memory area allocated at some address and with the total size of all its associated child nodes which are likely scattered over different memory sections. Signed-off-by: Dmitrii Golovanov --- scripts/footprint/size_report | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index dc6791587ebb9e..a2e481f02f9bb0 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -529,13 +529,14 @@ class TreeNode(NodeMixin): A symbol node. """ - def __init__(self, name, identifier, size=0, parent=None, children=None, address=0): + def __init__(self, name, identifier, size=0, parent=None, children=None, address=None): super().__init__() self._name = name self._size = size self.parent = parent self._identifier = identifier - self.address = address + if address is not None: + self.address = address if children: self.children = children @@ -599,7 +600,10 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): else: if node: parent = node - node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent, address=addr) + node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent) + # Set memory block address only on terminal symbol nodes, don't do it at file or directory level. + node.address = addr + # # Mapping paths to tree nodes path_node_map = [ @@ -691,7 +695,7 @@ def print_any_tree(root, total_size, depth): hex_addr = "-" cc = cr = "" if not row.node.children: - if row.node._name != "(hidden)": + if hasattr(row.node, 'address'): hex_addr = "0x{:08x}".format(row.node.address) cc = Fore.CYAN cr = Fore.RESET From 8c8668c46a37a39da2e055ae6b84cb461709f420 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0562/1389] scripts: size_report: Report section name for symbols Report section name for symbols: both at json and text reports. Signed-off-by: Dmitrii Golovanov --- scripts/footprint/size_report | 94 +++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index a2e481f02f9bb0..a8d671ef61985b 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -68,9 +68,9 @@ def is_symbol_in_ranges(sym, ranges): """ for bound in ranges: if bound['start'] <= sym['st_value'] <= bound['end']: - return True + return bound - return False + return None def get_die_mapped_address(die, parser, dwarfinfo): @@ -127,7 +127,7 @@ def match_symbol_address(symlist, die, parser, dwarfinfo): def get_symbols(elf, addr_ranges): """ Fetch the symbols from the symbol table and put them - into ROM, RAM buckets. + into ROM, RAM, unassigned buckets. """ rom_syms = dict() ram_syms = dict() @@ -135,6 +135,7 @@ def get_symbols(elf, addr_ranges): rom_addr_ranges = addr_ranges['rom'] ram_addr_ranges = addr_ranges['ram'] + unassigned_addr_ranges = addr_ranges['unassigned'] for section in elf.iter_sections(): if isinstance(section, SymbolTableSection): @@ -146,24 +147,34 @@ def get_symbols(elf, addr_ranges): found_sec = False entry = {'name': sym.name, 'symbol': sym, - 'mapped_files': set()} + 'mapped_files': set(), + 'section': None} # If symbol is in ROM area? - if is_symbol_in_ranges(sym, rom_addr_ranges): + bound = is_symbol_in_ranges(sym, rom_addr_ranges) + if bound: if sym.name not in rom_syms: rom_syms[sym.name] = list() + entry['section'] = bound['name'] rom_syms[sym.name].append(entry) found_sec = True # If symbol is in RAM area? - if is_symbol_in_ranges(sym, ram_addr_ranges): + bound = is_symbol_in_ranges(sym, ram_addr_ranges) + if bound: if sym.name not in ram_syms: ram_syms[sym.name] = list() + entry['section'] = bound['name'] ram_syms[sym.name].append(entry) found_sec = True if not found_sec: - unassigned_syms['sym_name'] = entry + bound = is_symbol_in_ranges(sym, unassigned_addr_ranges) + if bound: + entry['section'] = bound['name'] + if sym.name not in unassigned_syms: + unassigned_syms[sym.name] = list() + unassigned_syms[sym.name].append(entry) ret = {'rom': rom_syms, 'ram': ram_syms, @@ -171,6 +182,18 @@ def get_symbols(elf, addr_ranges): return ret +def print_section_info(section, descr=""): + if args.verbose: + sec_size = section['sh_size'] + sec_start = section['sh_addr'] + sec_end = sec_start + (sec_size - 1 if sec_size else 0) + print(f"DEBUG: " + f"0x{sec_start:08x}-0x{sec_end:08x} " + f"{descr} '{section.name}': size={sec_size}, " + f"{section['sh_type']}, 0x{section['sh_flags']:08x}") +# + + def get_section_ranges(elf): """ Parse ELF header to find out the address ranges of ROM or RAM sections @@ -178,19 +201,26 @@ def get_section_ranges(elf): """ rom_addr_ranges = list() ram_addr_ranges = list() + unassigned_addr_ranges = list() + rom_size = 0 ram_size = 0 + unassigned_size = 0 for section in elf.iter_sections(): size = section['sh_size'] sec_start = section['sh_addr'] sec_end = sec_start + (size - 1 if size else 0) - bound = {'start': sec_start, 'end': sec_end} + bound = {'start': sec_start, 'end': sec_end, 'name': section.name} + is_assigned = False if section['sh_type'] == 'SHT_NOBITS': # BSS and noinit sections ram_addr_ranges.append(bound) ram_size += size + is_assigned = True + print_section_info(section, "RAM bss section") + elif section['sh_type'] == 'SHT_PROGBITS': # Sections to be in flash or memory flags = section['sh_flags'] @@ -198,23 +228,37 @@ def get_section_ranges(elf): # Text section rom_addr_ranges.append(bound) rom_size += size + is_assigned = True + print_section_info(section, "ROM txt section") + elif (flags & SHF_WRITE_ALLOC) == SHF_WRITE_ALLOC: # Data occupies both ROM and RAM # since at boot, content is copied from ROM to RAM rom_addr_ranges.append(bound) rom_size += size - ram_addr_ranges.append(bound) ram_size += size + is_assigned = True + print_section_info(section, "ROM,RAM section") + elif (flags & SHF_ALLOC) == SHF_ALLOC: # Read only data rom_addr_ranges.append(bound) rom_size += size + is_assigned = True + print_section_info(section, "ROM r/o section") + + if not is_assigned: + print_section_info(section, "unassigned section") + unassigned_addr_ranges.append(bound) + unassigned_size += size ret = {'rom': rom_addr_ranges, 'rom_total_size': rom_size, 'ram': ram_addr_ranges, - 'ram_total_size': ram_size} + 'ram_total_size': ram_size, + 'unassigned': unassigned_addr_ranges, + 'unassigned_total_size': unassigned_size} return ret @@ -529,7 +573,7 @@ class TreeNode(NodeMixin): A symbol node. """ - def __init__(self, name, identifier, size=0, parent=None, children=None, address=None): + def __init__(self, name, identifier, size=0, parent=None, children=None, address=None, section=None): super().__init__() self._name = name self._size = size @@ -537,6 +581,8 @@ class TreeNode(NodeMixin): self._identifier = identifier if address is not None: self.address = address + if section is not None: + self.section = section if children: self.children = children @@ -582,7 +628,7 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): # A set of helper function for building a simple tree with a path-like # hierarchy. - def _insert_one_elem(root, path, size, addr): + def _insert_one_elem(root, path, size, addr, section): cur = None node = None parent = root @@ -601,8 +647,10 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): if node: parent = node node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent) - # Set memory block address only on terminal symbol nodes, don't do it at file or directory level. + # Set memory block address and section only on terminal symbol nodes. + # Don't do it on file and directory level nodes. node.address = addr + node.section = section # # Mapping paths to tree nodes @@ -620,6 +668,7 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): for symbol in sym: size = get_symbol_size(symbol['symbol']) addr = get_symbol_addr(symbol['symbol']) + section = symbol['section'] for file in symbol['mapped_files']: path = Path(file, name) if path.is_absolute(): @@ -637,7 +686,7 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): else: dest_node = node_no_paths - _insert_one_elem(dest_node, path, size, addr) + _insert_one_elem(dest_node, path, size, addr, section) if node_zephyr_base is not root: @@ -684,17 +733,20 @@ def print_any_tree(root, total_size, depth): """ Print the symbol tree. """ - print('{:101s} {:7s} {:8s} {:10s}'.format( - Fore.YELLOW + "Path", "Size", "%", "Address" + Fore.RESET)) - print('=' * 126) + print('{:98s} {:>7s} {:>7s} {:11s} {:16s}'.format( + Fore.YELLOW + "Path", "Size", "%", " Address", "Section" + Fore.RESET)) + print('=' * 138) for row in RenderTree(root, childiter=node_sort, maxlevel=depth): f = len(row.pre) + len(row.node._name) s = str(row.node._size).rjust(100-f) percent = 100 * float(row.node._size) / float(total_size) hex_addr = "-" + section_name = "" cc = cr = "" if not row.node.children: + if hasattr(row.node, 'section'): + section_name = row.node.section if hasattr(row.node, 'address'): hex_addr = "0x{:08x}".format(row.node.address) cc = Fore.CYAN @@ -703,8 +755,8 @@ def print_any_tree(root, total_size, depth): cc = Fore.GREEN cr = Fore.RESET - print(f"{row.pre}{cc}{row.node._name} {s} {cr}{Fore.BLUE}{percent:6.2f}%{Fore.RESET} {hex_addr}") - print('=' * 126) + print(f"{row.pre}{cc}{row.node._name} {s} {cr}{Fore.BLUE}{percent:6.2f}%{Fore.RESET} {hex_addr} {section_name}") + print('=' * 138) print(f'{total_size:>101}') @@ -768,7 +820,9 @@ def main(): symbols = get_symbols(elf, addr_ranges) for sym in symbols['unassigned'].values(): - print("WARN: Symbol '{0}' is not in RAM or ROM".format(sym['name'])) + for sym_entry in sym: + print(f"WARN: Symbol '{sym_entry['name']}' section '{sym_entry['section']}' " + "is not in RAM or ROM.") if args.json: jsonout = args.json From 62ddf18c28045eff4c0d05748a2653993a03a1fe Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0563/1389] scripts: size_report: Fix tree build for symbol copies Fix the memory footprint tree build for symbols with copies, e.g. static inline functions which are local per each compilation unit. Copies have the same path and symbol name, but different memory blocks associated, so they have to have separate nodes. Before the fix, these copies were merged into one node, with summary size and memory address of one of the symbols. Signed-off-by: Dmitrii Golovanov --- scripts/footprint/size_report | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index a8d671ef61985b..414665c7641722 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -641,16 +641,27 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): results = findall_by_attr(root, cur, name="_identifier") if results: item = results[0] - item._size += size - parent = item + if not hasattr(item, 'address'): + # Passing down through a non-terminal parent node. + parent = item + parent._size += size + else: + # Another symbol node here with the same name; stick to its parent as well. + parent = item.parent + node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent) else: + # There is no such terminal symbol in the tree yet; let's add it. if node: parent = node node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent) - # Set memory block address and section only on terminal symbol nodes. - # Don't do it on file and directory level nodes. - node.address = addr - node.section = section + if node: + # Set memory block address and section name properties only for terminal symbol nodes. + # Don't do it on file- and directory- level parent nodes. + node.address = addr + node.section = section + else: + # normally this shouldn't happen; just to detect data or logic errors. + print(f"ERROR: no end node created for {root}, {path}, 0x{addr:08x}+{size}@{section}") # # Mapping paths to tree nodes From abae5c7ecb87594e2a0ee1ebbade8502bbc8c03c Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0564/1389] logging: log_cache: ensure cache contains an entry Return an error if the provided cache configuration is not large enough to hold a single entry. An empty `active` and `idle` list causes NULL dereferences in `log_cache_get`. Signed-off-by: Jordan Yates --- subsys/logging/log_cache.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subsys/logging/log_cache.c b/subsys/logging/log_cache.c index 5bc51f3635b9fb..4899a3435d9602 100644 --- a/subsys/logging/log_cache.c +++ b/subsys/logging/log_cache.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include "log_cache.h" #define LOG_CACHE_DBG 0 @@ -29,6 +31,11 @@ int log_cache_init(struct log_cache *cache, const struct log_cache_config *confi uint32_t entry_cnt = config->buf_len / entry_size; struct log_cache_entry *entry = config->buf; + /* Ensure the cache has at least one entry */ + if (entry_cnt == 0) { + return -EINVAL; + } + /* Add all entries to idle list */ for (uint32_t i = 0; i < entry_cnt; i++) { sys_slist_append(&cache->idle, &entry->node); From 7676e7e138d9bc5bf2108e80fbd52ec487abe52a Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0565/1389] drivers: serial: nrfx: Update Kconfig dependencies for RX cache Two Kconfig symbols were tied to a board-specific DT nodelabel - namely the `NRFX_UARTE_CONFIG_RX_CACHE_ENABLED` and `UART__RX_CACHE_SIZE` were tied to `shared_ram3x_region` - but this is not necessary. That DT node is where the UARTE driver RX/TX cache buffers are placed in the default nRF54H20 DK memory map, but on another board, they could be located somewhere else. The exact memory sub-regions used for this purpose are indicated using the `memory-regions` property on each UARTE instance, which should be generic enough already, so let's use that instead. Signed-off-by: Grzegorz Swiderski --- drivers/serial/Kconfig.nrfx_uart_instance | 9 ++++++++- modules/hal_nordic/nrfx/Kconfig | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance index b8a62084ce5fbb..71b25dbeba07f0 100644 --- a/drivers/serial/Kconfig.nrfx_uart_instance +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -76,6 +76,13 @@ config UART_$(nrfx_uart_num)_NRF_HW_ASYNC_TIMER int "Timer instance" depends on UART_$(nrfx_uart_num)_NRF_HW_ASYNC +config UART_$(nrfx_uart_num)_HAS_RX_CACHE_SECTION + def_bool $(dt_nodelabel_has_prop,uart$(nrfx_uart_num),memory-regions) + imply NRFX_UARTE_CONFIG_RX_CACHE_ENABLED + help + This helper symbol indicates the existence of a linker section which + can be dedicated to an RX cache buffer. + config UART_$(nrfx_uart_num)_TX_CACHE_SIZE int "TX cache buffer size" depends on !UART_NRFX_UARTE_LEGACY_SHIM @@ -87,7 +94,7 @@ config UART_$(nrfx_uart_num)_TX_CACHE_SIZE config UART_$(nrfx_uart_num)_RX_CACHE_SIZE int "RX cache buffer size" depends on !UART_NRFX_UARTE_LEGACY_SHIM - default 32 if $(dt_nodelabel_has_compat,shared_ram3x_region,$(DT_COMPAT_NORDIC_OWNED_MEMORY)) + default 32 if UART_$(nrfx_uart_num)_HAS_RX_CACHE_SECTION default 5 range 5 255 help diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 549abb138fbecc..10ecd585ef3f49 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -950,7 +950,6 @@ config NRFX_UARTE_CONFIG_TX_LINK config NRFX_UARTE_CONFIG_RX_CACHE_ENABLED bool "UARTE RX caching support" - default y if $(dt_nodelabel_has_compat,shared_ram3x_region,$(DT_COMPAT_NORDIC_OWNED_MEMORY)) depends on NRFX_UARTE help Feature might be enabled on platforms which has limitations regarding addresses From ee9a0f14add16382d95d69c5af1b035ec5dab6c7 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:38:55 +0200 Subject: [PATCH 0566/1389] coding guidelines: comply with MISRA Rule 12.1. -added parentheses verifying lack of ambiguities Signed-off-by: Hess Nathan --- drivers/pcie/host/pcie.c | 14 +++++++------- drivers/serial/uart_ns16550.c | 24 ++++++++++++------------ drivers/timer/apic_tsc.c | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 0a98d8e8e069ac..9acca131a98d20 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -179,8 +179,8 @@ static bool pcie_get_bar(pcie_bdf_t bdf, reg++; phys_addr |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32; - if (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL64 || - PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE) { + if ((PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL64) || + (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE)) { /* Discard on invalid address */ goto err_exit; } @@ -188,8 +188,8 @@ static bool pcie_get_bar(pcie_bdf_t bdf, pcie_conf_write(bdf, reg, 0xFFFFFFFFU); size |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32; pcie_conf_write(bdf, reg, (uint32_t)((uint64_t)phys_addr >> 32)); - } else if (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL || - PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE) { + } else if ((PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL) || + (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE)) { /* Discard on invalid address */ goto err_exit; } @@ -253,7 +253,7 @@ static bool pcie_probe_bar(pcie_bdf_t bdf, uint32_t reg; for (reg = PCIE_CONF_BAR0; - index > 0 && reg <= PCIE_CONF_BAR5; reg++, index--) { + (index > 0) && (reg <= PCIE_CONF_BAR5); reg++, index--) { uintptr_t addr = pcie_conf_read(bdf, reg); if (PCIE_CONF_BAR_MEM(addr) && PCIE_CONF_BAR_64(addr)) { @@ -306,8 +306,8 @@ unsigned int pcie_alloc_irq(pcie_bdf_t bdf) data = pcie_conf_read(bdf, PCIE_CONF_INTR); irq = PCIE_CONF_INTR_IRQ(data); - if (irq == PCIE_CONF_INTR_IRQ_NONE || - irq >= CONFIG_MAX_IRQ_LINES || + if ((irq == PCIE_CONF_INTR_IRQ_NONE) || + (irq >= CONFIG_MAX_IRQ_LINES) || arch_irq_is_used(irq)) { /* In some platforms, PCI interrupts are hardwired to specific interrupt inputs diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 9b98ce8c52ec17..a9515d8c7a5cf1 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -242,18 +242,18 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define MSR_RI 0x40 /* complement of ring signal */ #define MSR_DCD 0x80 /* complement of dcd */ -#define THR(dev) (get_port(dev) + REG_THR * reg_interval(dev)) -#define RDR(dev) (get_port(dev) + REG_RDR * reg_interval(dev)) -#define BRDL(dev) (get_port(dev) + REG_BRDL * reg_interval(dev)) -#define BRDH(dev) (get_port(dev) + REG_BRDH * reg_interval(dev)) -#define IER(dev) (get_port(dev) + REG_IER * reg_interval(dev)) -#define IIR(dev) (get_port(dev) + REG_IIR * reg_interval(dev)) -#define FCR(dev) (get_port(dev) + REG_FCR * reg_interval(dev)) -#define LCR(dev) (get_port(dev) + REG_LCR * reg_interval(dev)) -#define MDC(dev) (get_port(dev) + REG_MDC * reg_interval(dev)) -#define LSR(dev) (get_port(dev) + REG_LSR * reg_interval(dev)) -#define MSR(dev) (get_port(dev) + REG_MSR * reg_interval(dev)) -#define MDR1(dev) (get_port(dev) + REG_MDR1 * reg_interval(dev)) +#define THR(dev) (get_port(dev) + (REG_THR * reg_interval(dev))) +#define RDR(dev) (get_port(dev) + (REG_RDR * reg_interval(dev))) +#define BRDL(dev) (get_port(dev) + (REG_BRDL * reg_interval(dev))) +#define BRDH(dev) (get_port(dev) + (REG_BRDH * reg_interval(dev))) +#define IER(dev) (get_port(dev) + (REG_IER * reg_interval(dev))) +#define IIR(dev) (get_port(dev) + (REG_IIR * reg_interval(dev))) +#define FCR(dev) (get_port(dev) + (REG_FCR * reg_interval(dev))) +#define LCR(dev) (get_port(dev) + (REG_LCR * reg_interval(dev))) +#define MDC(dev) (get_port(dev) + (REG_MDC * reg_interval(dev))) +#define LSR(dev) (get_port(dev) + (REG_LSR * reg_interval(dev))) +#define MSR(dev) (get_port(dev) + (REG_MSR * reg_interval(dev))) +#define MDR1(dev) (get_port(dev) + (REG_MDR1 * reg_interval(dev))) #define DLF(dev) (get_port(dev) + REG_DLF) #define PCP(dev) (get_port(dev) + REG_PCP) diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 59b0017375c3db..6b4035d976da69 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -64,7 +64,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) uint64_t now = rdtsc(); k_spinlock_key_t key = k_spin_lock(&lock); - uint64_t expires = now + MAX(ticks - 1, 0) * CYC_PER_TICK; + uint64_t expires = now + (MAX(ticks - 1, 0) * CYC_PER_TICK); expires = last_announce + (((expires - last_announce + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK); @@ -77,7 +77,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) * real hardware it requires more than a century of uptime, * but this is cheap and safe. */ - if (ticks == K_TICKS_FOREVER || expires < last_announce) { + if ((ticks == K_TICKS_FOREVER) || (expires < last_announce)) { expires = UINT64_MAX; } From d6380a84a898dc2bebebe72713912744ad3cc8c4 Mon Sep 17 00:00:00 2001 From: Corey Wharton Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0567/1389] logging: fix logging.async test Test has code to test conditions where CONFIG_LOG_PROCESS_THREAD=y but this option was not enabled in any of the tests. This code was using removed APIs and did not build anymore. This change enables the log thread for the logging.async and fixes the tests. Signed-off-by: Corey Wharton --- .../log_core_additional/log_thread.conf | 18 ++++++++++++++++++ .../logging/log_core_additional/src/log_test.c | 18 ++++++------------ .../logging/log_core_additional/testcase.yaml | 5 +++++ 3 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 tests/subsys/logging/log_core_additional/log_thread.conf diff --git a/tests/subsys/logging/log_core_additional/log_thread.conf b/tests/subsys/logging/log_core_additional/log_thread.conf new file mode 100644 index 00000000000000..6940a607ee5a0b --- /dev/null +++ b/tests/subsys/logging/log_core_additional/log_thread.conf @@ -0,0 +1,18 @@ +CONFIG_MAIN_THREAD_PRIORITY=5 +CONFIG_ZTEST=y +CONFIG_TEST_LOGGING_DEFAULTS=n +CONFIG_LOG=y +CONFIG_LOG_OUTPUT=y +CONFIG_LOG_PRINTK=n +CONFIG_LOG_SPEED=y +CONFIG_LOG_BUFFER_SIZE=1024 +CONFIG_CBPRINTF_FP_SUPPORT=y +CONFIG_CBPRINTF_LIBC_SUBSTS=y +CONFIG_ZTEST_STACK_SIZE=4096 +CONFIG_LOG_MODE_DEFERRED=y +CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=200 +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_MPSC_CLEAR_ALLOCATED=y +CONFIG_LOG_BACKEND_UART=y +CONFIG_THREAD_MONITOR=y diff --git a/tests/subsys/logging/log_core_additional/src/log_test.c b/tests/subsys/logging/log_core_additional/src/log_test.c index 2542a4887dce71..3b02c29c3ffb71 100644 --- a/tests/subsys/logging/log_core_additional/src/log_test.c +++ b/tests/subsys/logging/log_core_additional/src/log_test.c @@ -409,8 +409,6 @@ ZTEST(test_log_core_additional, test_multiple_backends) #ifdef CONFIG_LOG_PROCESS_THREAD ZTEST(test_log_core_additional, test_log_thread) { - uint32_t slabs_free, used, max; - TC_PRINT("Logging buffer is configured to %d bytes\n", CONFIG_LOG_BUFFER_SIZE); @@ -420,25 +418,19 @@ ZTEST(test_log_core_additional, test_log_thread) log_setup(false); - slabs_free = log_msg_mem_get_free(); - used = log_msg_mem_get_used(); - max = log_msg_mem_get_max_used(); - zassert_equal(used, 0); + zassert_false(log_data_pending()); LOG_INF("log info to log thread"); LOG_WRN("log warning to log thread"); LOG_ERR("log error to log thread"); - zassert_equal(log_msg_mem_get_used(), 3); - zassert_equal(log_msg_mem_get_free(), slabs_free - 3); - zassert_equal(log_msg_mem_get_max_used(), max); + zassert_true(log_data_pending()); - TC_PRINT("after log, free: %d, used: %d, max: %d\n", slabs_free, used, max); /* wait 2 seconds for logging thread to handle this log message*/ k_sleep(K_MSEC(2000)); zassert_equal(3, backend1_cb.counter, "Unexpected amount of messages received by the backend."); - zassert_equal(log_msg_mem_get_used(), 0); + zassert_false(log_data_pending()); } #else ZTEST(test_log_core_additional, test_log_thread) @@ -491,7 +483,9 @@ ZTEST(test_log_core_additional, test_log_msg_create) Z_LOG_MSG_CREATE(!IS_ENABLED(CONFIG_USERSPACE), mode, Z_LOG_LOCAL_DOMAIN_ID, NULL, - LOG_LEVEL_INTERNAL_RAW_STRING, NULL, 0, TEST_MESSAGE); + LOG_LEVEL_INF, NULL, 0, TEST_MESSAGE); + + backend1_cb.total_logs = 3; while (log_test_process()) { } diff --git a/tests/subsys/logging/log_core_additional/testcase.yaml b/tests/subsys/logging/log_core_additional/testcase.yaml index c643740b1bae5b..3fc9db4902a215 100644 --- a/tests/subsys/logging/log_core_additional/testcase.yaml +++ b/tests/subsys/logging/log_core_additional/testcase.yaml @@ -9,3 +9,8 @@ tests: extra_args: CONF_FILE=log_sync.conf integration_platforms: - native_sim + logging.thread: + tags: logging + extra_args: CONF_FILE=log_thread.conf + integration_platforms: + - native_sim From af9f47672d24cf06fdfb5db46141adcfb212509c Mon Sep 17 00:00:00 2001 From: Corey Wharton Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0568/1389] logging: add API to trigger immediate processing of logs There are use cases where it's beneficial to trigger the log thread to process log messages as soon as able instead of waiting for the processing timer or threshold triggers. An example would be to flush the log buffer before entering the idle thread after forcing a system power state. Signed-off-by: Corey Wharton --- include/zephyr/logging/log_ctrl.h | 6 ++++ subsys/logging/log_core.c | 10 ++++++ .../log_core_additional/src/log_test.c | 35 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/include/zephyr/logging/log_ctrl.h b/include/zephyr/logging/log_ctrl.h index 56b0458c2ecf10..eb8cb5606556ef 100644 --- a/include/zephyr/logging/log_ctrl.h +++ b/include/zephyr/logging/log_ctrl.h @@ -47,6 +47,12 @@ void log_core_init(void); */ void log_init(void); +/** @brief Trigger the log processing thread to process logs immediately. + * + * @note Function has no effect when CONFIG_LOG_MODE_IMMEDIATE is set. + */ +void log_thread_trigger(void); + /** * @brief Function for providing thread which is processing logs. * diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index c05858c1125f6e..3e767092b762ce 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -366,6 +366,16 @@ void log_init(void) (void)z_log_init(true, true); } +void log_thread_trigger(void) +{ + if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) { + return; + } + + k_timer_stop(&log_process_thread_timer); + k_sem_give(&log_process_thread_sem); +} + static void thread_set(k_tid_t process_tid) { proc_tid = process_tid; diff --git a/tests/subsys/logging/log_core_additional/src/log_test.c b/tests/subsys/logging/log_core_additional/src/log_test.c index 3b02c29c3ffb71..1af13cb5622642 100644 --- a/tests/subsys/logging/log_core_additional/src/log_test.c +++ b/tests/subsys/logging/log_core_additional/src/log_test.c @@ -439,6 +439,41 @@ ZTEST(test_log_core_additional, test_log_thread) } #endif +/** + * @brief Process all logging activities using a dedicated thread (trigger immediate processing) + * + * @addtogroup logging + */ + +#ifdef CONFIG_LOG_PROCESS_THREAD +ZTEST(test_log_core_additional, test_log_thread_trigger) +{ + log_setup(false); + + zassert_false(log_data_pending()); + + LOG_INF("log info to log thread"); + LOG_WRN("log warning to log thread"); + LOG_ERR("log error to log thread"); + + zassert_true(log_data_pending()); + + /* Trigger log thread to process messages as soon as possible. */ + log_thread_trigger(); + + /* wait 1ms to give logging thread chance to handle these log messages. */ + k_sleep(K_MSEC(1)); + zassert_equal(3, backend1_cb.counter, + "Unexpected amount of messages received by the backend."); + zassert_false(log_data_pending()); +} +#else +ZTEST(test_log_core_additional, test_log_thread_trigger) +{ + ztest_test_skip(); +} +#endif + static void call_log_generic(const char *fmt, ...) { va_list ap; From 38673123501967790c04414bc19102faa108e51a Mon Sep 17 00:00:00 2001 From: Fredrik Gihl Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0569/1389] drivers: sensors: Add support for ds18s20 Added support for the older ds18s20 inside the (newer) ds18b20. Signed-off-by: Fredrik Gihl --- doc/releases/release-notes-3.7.rst | 1 + drivers/sensor/maxim/ds18b20/Kconfig | 2 +- drivers/sensor/maxim/ds18b20/ds18b20.c | 89 ++++++++++++++++++-------- drivers/sensor/maxim/ds18b20/ds18b20.h | 6 ++ dts/bindings/sensor/maxim,ds18s20.yaml | 8 +++ tests/drivers/build_all/sensor/w1.dtsi | 6 ++ 6 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 dts/bindings/sensor/maxim,ds18s20.yaml diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 2659e536310385..0851c52b7cec17 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -229,6 +229,7 @@ Drivers and Sensors * Sensor * Added TMP114 driver + * Added DS18S20 1-wire temperature sensor driver. * Serial diff --git a/drivers/sensor/maxim/ds18b20/Kconfig b/drivers/sensor/maxim/ds18b20/Kconfig index ac7fe02ac46973..82f5160ff732ed 100644 --- a/drivers/sensor/maxim/ds18b20/Kconfig +++ b/drivers/sensor/maxim/ds18b20/Kconfig @@ -6,7 +6,7 @@ config DS18B20 bool "DS18B20 Temperature Sensor" default y - depends on DT_HAS_MAXIM_DS18B20_ENABLED + depends on DT_HAS_MAXIM_DS18B20_ENABLED || DT_HAS_MAXIM_DS18S20_ENABLED depends on W1_NET help Enable driver for DS18B20 1-Wire temperature sensors. diff --git a/drivers/sensor/maxim/ds18b20/ds18b20.c b/drivers/sensor/maxim/ds18b20/ds18b20.c index 15c7370b8e44a3..35e9a82df0226a 100644 --- a/drivers/sensor/maxim/ds18b20/ds18b20.c +++ b/drivers/sensor/maxim/ds18b20/ds18b20.c @@ -9,9 +9,11 @@ * A datasheet is available at: * https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf * + * Driver also support the older DS18S20 1-Wire temperature sensors. + * https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf + * * Parasite power configuration is not supported by the driver. */ -#define DT_DRV_COMPAT maxim_ds18b20 #include #include @@ -25,15 +27,25 @@ LOG_MODULE_REGISTER(DS18B20, CONFIG_SENSOR_LOG_LEVEL); static int ds18b20_configure(const struct device *dev); /* measure wait time for 9-bit, 10-bit, 11-bit, 12-bit resolution respectively */ -static const uint16_t measure_wait_ms[4] = { 94, 188, 376, 750 }; +static const uint16_t measure_wait_ds18b20_ms[4] = { 94, 188, 376, 750 }; -static inline void ds18b20_temperature_from_raw(uint8_t *temp_raw, +/* ds18s20 always needs 750ms */ +static const uint16_t measure_wait_ds18s20_ms = { 750 }; + +static inline void ds18b20_temperature_from_raw(const struct device *dev, + uint8_t *temp_raw, struct sensor_value *val) { - int16_t temp = sys_get_le16(temp_raw); - - val->val1 = temp / 16; - val->val2 = (temp % 16) * 1000000 / 16; + const struct ds18b20_config *cfg = dev->config; + int16_t temp = sys_get_le16 (temp_raw); + + if (cfg->chip == type_ds18s20) { + val->val1 = temp / 2; + val->val2 = (temp % 2) * 5000000; + } else { + val->val1 = temp / 16; + val->val2 = (temp % 16) * 1000000 / 16; + } } /* @@ -95,10 +107,20 @@ static void ds18b20_set_resolution(const struct device *dev, uint8_t resolution) data->scratchpad.config |= DS18B20_RESOLUTION(resolution); } +static uint16_t measure_wait_ms(const struct device *dev) +{ + const struct ds18b20_config *cfg = dev->config; + + if (cfg->chip == type_ds18s20) { + return measure_wait_ds18s20_ms; + } + + return measure_wait_ds18b20_ms[DS18B20_RESOLUTION_INDEX(cfg->resolution)]; +} + static int ds18b20_sample_fetch(const struct device *dev, enum sensor_channel chan) { - const struct ds18b20_config *cfg = dev->config; struct ds18b20_data *data = dev->data; int status; @@ -118,7 +140,7 @@ static int ds18b20_sample_fetch(const struct device *dev, LOG_DBG("W1 fetch error"); return status; } - k_msleep(measure_wait_ms[DS18B20_RESOLUTION_INDEX(cfg->resolution)]); + k_msleep(measure_wait_ms(dev)); return ds18b20_read_scratchpad(dev, &data->scratchpad); } @@ -132,7 +154,7 @@ static int ds18b20_channel_get(const struct device *dev, return -ENOTSUP; } - ds18b20_temperature_from_raw((uint8_t *)&data->scratchpad.temp, val); + ds18b20_temperature_from_raw(dev, (uint8_t *)&data->scratchpad.temp, val); return 0; } @@ -159,17 +181,19 @@ static int ds18b20_configure(const struct device *dev) } if ((cfg->family != 0) && (cfg->family != data->config.rom.family)) { - LOG_ERR("Found 1-Wire slave is not a DS18B20"); + LOG_ERR("Found 1-Wire slave is not a %s", dev->name); return -EINVAL; } /* write default configuration */ - ds18b20_set_resolution(dev, cfg->resolution); - ret = ds18b20_write_scratchpad(dev, data->scratchpad); - if (ret < 0) { - return ret; + if (cfg->chip == type_ds18b20) { + ds18b20_set_resolution(dev, cfg->resolution); + ret = ds18b20_write_scratchpad(dev, data->scratchpad); + if (ret < 0) { + return ret; + } } - LOG_DBG("Init DS18B20: ROM=%016llx\n", + LOG_DBG("Init %s: ROM=%016llx\n", dev->name, w1_rom_to_uint64(&data->config.rom)); return 0; @@ -214,24 +238,35 @@ static int ds18b20_init(const struct device *dev) return 0; } -#define DS18B20_CONFIG_INIT(inst) \ - { \ +#define DS18B20_CONFIG_INIT(inst, default_family_code, chip_type) \ + { \ .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .family = (uint8_t)DT_INST_PROP_OR(inst, family_code, 0x28), \ - .resolution = DT_INST_PROP(inst, resolution), \ + .family = (uint8_t)DT_INST_PROP_OR(inst, family_code, default_family_code), \ + .resolution = DT_INST_PROP_OR(inst, resolution, 12), \ + .chip = chip_type, \ } -#define DS18B20_DEFINE(inst) \ - static struct ds18b20_data ds18b20_data_##inst; \ - static const struct ds18b20_config ds18b20_config_##inst = \ - DS18B20_CONFIG_INIT(inst); \ +#define DS18B20_DEFINE(inst, name, family_code, chip_type) \ + static struct ds18b20_data data_##name##_##inst; \ + static const struct ds18b20_config config_##name##_##inst = \ + DS18B20_CONFIG_INIT(inst, family_code, chip_type); \ SENSOR_DEVICE_DT_INST_DEFINE(inst, \ ds18b20_init, \ NULL, \ - &ds18b20_data_##inst, \ - &ds18b20_config_##inst, \ + &data_##name##_##inst, \ + &config_##name##_##inst, \ POST_KERNEL, \ CONFIG_SENSOR_INIT_PRIORITY, \ &ds18b20_driver_api); -DT_INST_FOREACH_STATUS_OKAY(DS18B20_DEFINE) +#define DT_DRV_COMPAT maxim_ds18b20 +DT_INST_FOREACH_STATUS_OKAY_VARGS(DS18B20_DEFINE, DT_DRV_COMPAT, + DS18B20_FAMILYCODE, + type_ds18b20) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_ds18s20 +DT_INST_FOREACH_STATUS_OKAY_VARGS(DS18B20_DEFINE, DT_DRV_COMPAT, + DS18S20_FAMILYCODE, + type_ds18s20) +#undef DT_DRV_COMPAT diff --git a/drivers/sensor/maxim/ds18b20/ds18b20.h b/drivers/sensor/maxim/ds18b20/ds18b20.h index cf318cb9f9f20c..a85e91c58ae5bc 100644 --- a/drivers/sensor/maxim/ds18b20/ds18b20.h +++ b/drivers/sensor/maxim/ds18b20/ds18b20.h @@ -31,6 +31,11 @@ /* convert resolution in bits to array index (for resolution specific elements) */ #define DS18B20_RESOLUTION_INDEX(res) (res - 9) +#define DS18B20_FAMILYCODE 0x28 +#define DS18S20_FAMILYCODE 0x10 + +enum chip_type {type_ds18b20, type_ds18s20}; + struct ds18b20_scratchpad { int16_t temp; uint8_t alarm_temp_high; @@ -44,6 +49,7 @@ struct ds18b20_config { const struct device *bus; uint8_t family; uint8_t resolution; + enum chip_type chip; }; struct ds18b20_data { diff --git a/dts/bindings/sensor/maxim,ds18s20.yaml b/dts/bindings/sensor/maxim,ds18s20.yaml new file mode 100644 index 00000000000000..1e42cd80a9d058 --- /dev/null +++ b/dts/bindings/sensor/maxim,ds18s20.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024, Fredrik Gihl +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim 1-Wire ds18s20 temperature sensor + +compatible: "maxim,ds18s20" + +include: [sensor-device.yaml, w1-slave.yaml] diff --git a/tests/drivers/build_all/sensor/w1.dtsi b/tests/drivers/build_all/sensor/w1.dtsi index a7a6a554eb021d..2566057e5f4f6f 100644 --- a/tests/drivers/build_all/sensor/w1.dtsi +++ b/tests/drivers/build_all/sensor/w1.dtsi @@ -12,3 +12,9 @@ test_w1_ds18b20: ds18b20 { resolution = <12>; status = "okay"; }; + +test_w1_ds18s20: ds18s20 { + compatible = "maxim,ds18s20"; + family-code = <0x10>; + status = "okay"; +}; From 9ef33d7e340fa1e679e369089f54cb61ed3853d9 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0570/1389] arch: x86: remove limitation of number of cpu support in smp Remove the limitation of number of cpu support in x86 arch. Also add support for retrieve cpu informations such as for hybird cores. Signed-off-by: Najumon B.A --- arch/x86/core/Kconfig.intel64 | 3 - arch/x86/core/intel64/cpu.c | 133 ++++---------------- arch/x86/core/intel64/locore.S | 120 ++---------------- arch/x86/include/intel64/kernel_arch_data.h | 41 ++++++ 4 files changed, 77 insertions(+), 220 deletions(-) diff --git a/arch/x86/core/Kconfig.intel64 b/arch/x86/core/Kconfig.intel64 index 913bb0e794d5e8..2e6e7ebd00ab22 100644 --- a/arch/x86/core/Kconfig.intel64 +++ b/arch/x86/core/Kconfig.intel64 @@ -88,7 +88,4 @@ config X86_USERSPACE supporting user-level threads that are protected from each other and from crashing the kernel. -config MP_MAX_NUM_CPUS - range 1 4 - endif # X86_64 diff --git a/arch/x86/core/intel64/cpu.c b/arch/x86/core/intel64/cpu.c index d1aedcd4deca65..8d68afa2a19137 100644 --- a/arch/x86/core/intel64/cpu.c +++ b/arch/x86/core/intel64/cpu.c @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include +#include #include #include #include @@ -12,125 +14,32 @@ #include #include #ifdef CONFIG_ACPI +#include #include #endif -BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS <= 4, "Only supports max 4 CPUs"); - /* * Map of CPU logical IDs to CPU local APIC IDs. By default, * we assume this simple identity mapping, as found in QEMU. * The symbol is weak so that boards/SoC files can override. */ -__weak uint8_t x86_cpu_loapics[] = { 0, 1, 2, 3 }; - -extern char x86_ap_start[]; /* AP entry point in locore.S */ - -extern uint8_t z_x86_exception_stack[]; -extern uint8_t z_x86_exception_stack1[]; -extern uint8_t z_x86_exception_stack2[]; -extern uint8_t z_x86_exception_stack3[]; - -extern uint8_t z_x86_nmi_stack[]; -extern uint8_t z_x86_nmi_stack1[]; -extern uint8_t z_x86_nmi_stack2[]; -extern uint8_t z_x86_nmi_stack3[]; - -#ifdef CONFIG_X86_KPTI -extern uint8_t z_x86_trampoline_stack[]; -extern uint8_t z_x86_trampoline_stack1[]; -extern uint8_t z_x86_trampoline_stack2[]; -extern uint8_t z_x86_trampoline_stack3[]; -#endif /* CONFIG_X86_KPTI */ - -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss0 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[0]) -}; - -#if CONFIG_MP_MAX_NUM_CPUS > 1 -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss1 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack1 + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack1 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack1 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[1]) -}; -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss2 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack2 + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack2 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack2 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[2]) -}; -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss3 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack3 + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack3 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack3 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[3]) -}; +#if defined(CONFIG_ACPI) +__weak uint8_t x86_cpu_loapics[CONFIG_MP_MAX_NUM_CPUS]; +#else +#define INIT_CPUID(n, _) n +__weak uint8_t x86_cpu_loapics[] = { + LISTIFY(CONFIG_MP_MAX_NUM_CPUS, INIT_CPUID, (,)),}; #endif +extern char x86_ap_start[]; /* AP entry point in locore.S */ +LISTIFY(CONFIG_MP_MAX_NUM_CPUS, ACPI_CPU_INIT, (;)); -/* We must put this in a dedicated section, or else it will land into .bss: - * in this case, though locore.S initalizes it relevantly, all will be - * lost when calling z_bss_zero() in z_x86_cpu_init prior to using it. - */ Z_GENERIC_SECTION(.boot_arg) x86_boot_arg_t x86_cpu_boot_arg; struct x86_cpuboot x86_cpuboot[] = { - { - .tr = X86_KERNEL_CPU0_TR, - .gs_base = &tss0, - .sp = (uint64_t) z_interrupt_stacks[0] + - K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), - .stack_size = - K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), - .fn = z_prep_c, - .arg = &x86_cpu_boot_arg, - }, -#if CONFIG_MP_MAX_NUM_CPUS > 1 - { - .tr = X86_KERNEL_CPU1_TR, - .gs_base = &tss1 - }, -#endif -#if CONFIG_MP_MAX_NUM_CPUS > 2 - { - .tr = X86_KERNEL_CPU2_TR, - .gs_base = &tss2 - }, -#endif -#if CONFIG_MP_MAX_NUM_CPUS > 3 - { - .tr = X86_KERNEL_CPU3_TR, - .gs_base = &tss3 - }, -#endif + LISTIFY(CONFIG_MP_MAX_NUM_CPUS, X86_CPU_BOOT_INIT, (,)), }; /* @@ -151,6 +60,12 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, if (lapic != NULL) { /* We update the apic_id, __start will need it. */ x86_cpu_loapics[cpu_num] = lapic->Id; + } else { + /* TODO: kernel need to handle the error scenario if someone config + * CONFIG_MP_MAX_NUM_CPUS more than what platform supported. + */ + __ASSERT(false, "CPU reached more than maximum supported!"); + return; } })); @@ -160,6 +75,7 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, x86_cpuboot[cpu_num].stack_size = sz; x86_cpuboot[cpu_num].fn = fn; x86_cpuboot[cpu_num].arg = arg; + x86_cpuboot[cpu_num].cpu_id = cpu_num; z_loapic_ipi(apic_id, LOAPIC_ICR_IPI_INIT, 0); k_busy_wait(10000); @@ -181,18 +97,19 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, */ FUNC_NORETURN void z_x86_cpu_init(struct x86_cpuboot *cpuboot) { +#if defined(CONFIG_ACPI) + __ASSERT(z_x86_cpuid_get_current_physical_apic_id() == + x86_cpu_loapics[cpuboot->cpu_id], "APIC ID miss match!"); +#endif x86_sse_init(NULL); - /* The internal cpu_number is the index to x86_cpuboot[] */ - unsigned char cpu_num = (unsigned char)(cpuboot - x86_cpuboot); - - if (cpu_num == 0U) { + if (cpuboot->cpu_id == 0U) { /* Only need to do these once per boot */ z_bss_zero(); z_data_copy(); } - z_loapic_enable(cpu_num); + z_loapic_enable(cpuboot->cpu_id); #ifdef CONFIG_USERSPACE /* Set landing site for 'syscall' instruction */ diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index d68e80c423f4d5..68f89c90398f9a 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -80,6 +80,15 @@ movq %rax, %cr0 .endm +.macro DEFINE_TSS_STACK_ARRAY + .irp idx, DEFINE_STACK_ARRAY_IDX + .word __X86_TSS64_SIZEOF-1 + .word tss\idx + .word 0x8900 + .word 0, 0, 0, 0, 0 + .endr +.endm + /* The .locore section begins the page-aligned initialization region * of low memory. The first address is used as the architectural * entry point for auxiliary CPUs being brought up (in real mode!) @@ -113,17 +122,13 @@ __start: nop nop -#if CONFIG_MP_MAX_NUM_CPUS > 1 - .code16 .global x86_ap_start x86_ap_start: - /* * First, we move to 32-bit protected mode, and set up the * same flat environment that the BSP gets from the loader. */ - lgdt gdt48 lidt idt48 movl %cr0, %eax @@ -145,7 +150,7 @@ x86_ap_start: movl LOAPIC_BASE_ADDRESS+LOAPIC_ID, %eax shrl $24, %eax - andl $0x0F, %eax /* local APIC ID -> EAX */ + andl $0xFF, %eax /* local APIC ID -> EAX */ movl $x86_cpuboot, %ebp xorl %ebx, %ebx @@ -160,8 +165,6 @@ x86_ap_start: unknown_loapic_id: jmp unknown_loapic_id -#endif /* CONFIG_MP_MAX_NUM_CPUS > 1 */ - .code32 .globl __start32 __start32: @@ -1094,31 +1097,7 @@ gdt: /* Remaining entries are TSS for each enabled CPU */ - .word __X86_TSS64_SIZEOF-1 /* 0x40: 64-bit TSS (16-byte entry) */ - .word tss0 - .word 0x8900 - .word 0, 0, 0, 0, 0 - -#if CONFIG_MP_MAX_NUM_CPUS > 1 - .word __X86_TSS64_SIZEOF-1 /* 0x50: 64-bit TSS (16-byte entry) */ - .word tss1 - .word 0x8900 - .word 0, 0, 0, 0, 0 -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 - .word __X86_TSS64_SIZEOF-1 /* 0x60: 64-bit TSS (16-byte entry) */ - .word tss2 - .word 0x8900 - .word 0, 0, 0, 0, 0 -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 - .word __X86_TSS64_SIZEOF-1 /* 0x70: 64-bit TSS (16-byte entry) */ - .word tss3 - .word 0x8900 - .word 0, 0, 0, 0, 0 -#endif + DEFINE_TSS_STACK_ARRAY gdt_end: @@ -1129,80 +1108,3 @@ gdt48: /* LGDT descriptor for 32 bit mode */ gdt80: /* LGDT descriptor for long mode */ .word (gdt_end - gdt - 1) .quad gdt -.section .lodata,"ad" - -/* - * Known-good stack for handling CPU exceptions. - */ - -.global z_x86_exception_stack -.align 16 -z_x86_exception_stack: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack -.align 16 -z_x86_nmi_stack: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA - -#if CONFIG_MP_MAX_NUM_CPUS > 1 -.global z_x86_exception_stack1 -.align 16 -z_x86_exception_stack1: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack1 -.align 16 -z_x86_nmi_stack1: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 -.global z_x86_exception_stack2 -.align 16 -z_x86_exception_stack2: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack2 -.align 16 -z_x86_nmi_stack2: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 -.global z_x86_exception_stack3 -.align 16 -z_x86_exception_stack3: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack3 -.align 16 -z_x86_nmi_stack3: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -#endif - -#ifdef CONFIG_X86_KPTI -.section .trampolines,"ad" - -.global z_x86_trampoline_stack -.align 16 -z_x86_trampoline_stack: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA - -#if CONFIG_MP_MAX_NUM_CPUS > 1 -.global z_x86_trampoline_stack1 -.align 16 -z_x86_trampoline_stack1: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 -.global z_x86_trampoline_stack2 -.align 16 -z_x86_trampoline_stack2: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 -.global z_x86_trampoline_stack3 -.align 16 -z_x86_trampoline_stack3: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA -#endif -#endif /* CONFIG_X86_KPTI */ diff --git a/arch/x86/include/intel64/kernel_arch_data.h b/arch/x86/include/intel64/kernel_arch_data.h index 6cbf18a831d879..af3b0d1c8165ed 100644 --- a/arch/x86/include/intel64/kernel_arch_data.h +++ b/arch/x86/include/intel64/kernel_arch_data.h @@ -26,6 +26,7 @@ struct x86_cpuboot { size_t stack_size; /* size of stack */ arch_cpustart_t fn; /* kernel entry function */ void *arg; /* argument for above function */ + uint8_t cpu_id; /* CPU ID */ }; typedef struct x86_cpuboot x86_cpuboot_t; @@ -38,4 +39,44 @@ extern uint8_t x86_cpu_loapics[]; /* CPU logical ID -> local APIC ID */ #define Z_X86_TRAMPOLINE_STACK_SIZE 128 #endif +#ifdef CONFIG_X86_KPTI +#define TRAMPOLINE_STACK(n) \ + uint8_t z_x86_trampoline_stack##n[Z_X86_TRAMPOLINE_STACK_SIZE] \ + __attribute__ ((section(".trampolines"))); + +#define TRAMPOLINE_INIT(n) \ + .ist2 = (uint64_t)z_x86_trampoline_stack##n + Z_X86_TRAMPOLINE_STACK_SIZE, +#else +#define TRAMPOLINE_STACK(n) +#define TRAMPOLINE_INIT(n) +#endif /* CONFIG_X86_KPTI */ + +#define ACPI_CPU_INIT(n, _) \ + uint8_t z_x86_exception_stack##n[CONFIG_X86_EXCEPTION_STACK_SIZE] __aligned(16); \ + uint8_t z_x86_nmi_stack##n[CONFIG_X86_EXCEPTION_STACK_SIZE] __aligned(16); \ + TRAMPOLINE_STACK(n); \ + Z_GENERIC_SECTION(.tss) \ + struct x86_tss64 tss##n = { \ + TRAMPOLINE_INIT(n) \ + .ist6 = (uint64_t)z_x86_nmi_stack##n + CONFIG_X86_EXCEPTION_STACK_SIZE, \ + .ist7 = (uint64_t)z_x86_exception_stack##n + CONFIG_X86_EXCEPTION_STACK_SIZE, \ + .iomapb = 0xFFFF, .cpu = &(_kernel.cpus[n]) \ + } + +#define X86_CPU_BOOT_INIT(n, _) \ + { \ + .tr = (0x40 + (16 * n)), \ + .gs_base = &tss##n, \ + .sp = (uint64_t)z_interrupt_stacks[n] + \ + K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), \ + .stack_size = K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), \ + .fn = z_prep_c, \ + .arg = &x86_cpu_boot_arg, \ + } + +#define STACK_ARRAY_IDX(n, _) n + +#define DEFINE_STACK_ARRAY_IDX\ + LISTIFY(CONFIG_MP_MAX_NUM_CPUS, STACK_ARRAY_IDX, (,)) + #endif /* ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_DATA_H_ */ From 96e314fc2cfbacb8c957ded493db888c1d2e7e63 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0571/1389] tests: arch: x86 : update stack variable name in nmi test case update stack variable name in nmi test case for BSP Signed-off-by: Najumon B.A --- tests/arch/x86/nmi/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/arch/x86/nmi/src/main.c b/tests/arch/x86/nmi/src/main.c index 393d504c7dc6a5..852e949c1150f5 100644 --- a/tests/arch/x86/nmi/src/main.c +++ b/tests/arch/x86/nmi/src/main.c @@ -17,13 +17,13 @@ static volatile int int_handler_executed; -extern uint8_t z_x86_nmi_stack[]; +extern uint8_t z_x86_nmi_stack0[]; extern uint8_t z_x86_nmi_stack1[]; extern uint8_t z_x86_nmi_stack2[]; extern uint8_t z_x86_nmi_stack3[]; uint8_t *nmi_stacks[] = { - z_x86_nmi_stack, + z_x86_nmi_stack0, #if CONFIG_MP_MAX_NUM_CPUS > 1 z_x86_nmi_stack1, #if CONFIG_MP_MAX_NUM_CPUS > 2 From c37e18f5e7fe67c8486bee6c0e7530a40beb4e73 Mon Sep 17 00:00:00 2001 From: Jason Murphy Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0572/1389] boards: arm: fix gpio-led flags on adi_eval_adin1110ebz These LEDs are active-LOW instead of active-HIGH. Signed-off-by: Jason Murphy --- boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts b/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts index 00f00777a23710..171e57963bcd8a 100644 --- a/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts +++ b/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts @@ -34,19 +34,19 @@ leds { /* Respecting pcb silkscreen naming */ compatible = "gpio-leds"; green_led: led_uC0 { - gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; label = "Status uC0"; }; red_led: led_uC1 { - gpios = <&gpioe 2 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 2 GPIO_ACTIVE_LOW>; label = "Status uC1 "; }; yellow_led: led_uC2 { - gpios = <&gpioe 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 6 GPIO_ACTIVE_LOW>; label = "Status uC2"; }; blue_led: led_uC3 { - gpios = <&gpiog 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpiog 15 GPIO_ACTIVE_LOW>; label = "Status uC3"; }; }; From 1a0290d4da52f3e6f85ce7decab64eb5cd70f097 Mon Sep 17 00:00:00 2001 From: Jason Murphy Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0573/1389] boards: arm: fix gpio-led flags on adi_eval_adin2111ebz These LEDs are active-LOW instead of active-HIGH. Signed-off-by: Jason Murphy --- boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts b/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts index 5db24f04e80dac..83a3343ca351d7 100644 --- a/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts +++ b/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts @@ -24,23 +24,23 @@ leds { compatible = "gpio-leds"; blue_led: uC_led1 { - gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpiob 6 GPIO_ACTIVE_LOW>; label = "Debug led uC1"; }; net_red_led: led_NET1 { - gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>; + gpios = <&gpiob 10 GPIO_ACTIVE_LOW>; label = "NET led 1"; }; net_green_led: led_NET2 { - gpios = <&gpiob 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpiob 11 GPIO_ACTIVE_LOW>; label = "NET led 2"; }; mod_red_led: led_MOD1 { - gpios = <&gpioe 2 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 2 GPIO_ACTIVE_LOW>; label = "Mod led 1"; }; mod_green_led: led_MOD2 { - gpios = <&gpioe 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 6 GPIO_ACTIVE_LOW>; label = "Mod led 2"; }; }; From b471c2e475c45612fd569b6f64d83def577c6a3f Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0574/1389] samples: move with_mcuboot sample to samples/sysbuild This creates a new category of samples that demonstrate certain features of sysbuild. "application development" was a very generic name. Signed-off-by: Gerard Marull-Paretas --- MAINTAINERS.yml | 4 ++-- doc/_scripts/redirects.py | 1 + samples/index.rst | 1 + samples/sysbuild/sysbuild.rst | 10 ++++++++++ .../sysbuild/with_mcuboot/CMakeLists.txt | 0 .../sysbuild/with_mcuboot/README.rst | 0 .../sysbuild/with_mcuboot/prj.conf | 0 .../sysbuild/with_mcuboot/sample.yaml | 2 +- .../sysbuild/with_mcuboot/src/main.c | 0 .../sysbuild/with_mcuboot/sysbuild.conf | 0 .../sysbuild/with_mcuboot/sysbuild/mcuboot.conf | 0 11 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 samples/sysbuild/sysbuild.rst rename samples/{application_development => }/sysbuild/with_mcuboot/CMakeLists.txt (100%) rename samples/{application_development => }/sysbuild/with_mcuboot/README.rst (100%) rename samples/{application_development => }/sysbuild/with_mcuboot/prj.conf (100%) rename samples/{application_development => }/sysbuild/with_mcuboot/sample.yaml (90%) rename samples/{application_development => }/sysbuild/with_mcuboot/src/main.c (100%) rename samples/{application_development => }/sysbuild/with_mcuboot/sysbuild.conf (100%) rename samples/{application_development => }/sysbuild/with_mcuboot/sysbuild/mcuboot.conf (100%) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 42e70bdb0b607f..77f9820f681b61 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3761,12 +3761,12 @@ Sysbuild: - "57300" files: - share/sysbuild/ - - samples/application_development/sysbuild/ + - samples/sysbuild/ - doc/build/sysbuild/ labels: - "area: Sysbuild" tests: - - sample.application_development.sysbuild + - sample.sysbuild Task Watchdog: status: maintained diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index bf4f9262749a29..91586470feabdc 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -199,6 +199,7 @@ ('reference/usermode/overview', 'kernel/usermode/overview'), ('reference/usermode/syscalls', 'kernel/usermode/syscalls'), ('reference/util/index', 'kernel/util/index'), + ('samples/application_development/with_mcuboot/README', 'samples/sysbuild/with_mcuboot/README'), ('samples/drivers/adc/README', 'samples/drivers/adc/adc_dt/README'), ('samples/drivers/kscan_touch', 'samples/subsys/input/input'), ('samples/drivers/led_apa102/README', 'samples/drivers/led_strip/README'), diff --git a/samples/index.rst b/samples/index.rst index 8581a330d40a8f..0120c87769d7e9 100644 --- a/samples/index.rst +++ b/samples/index.rst @@ -13,6 +13,7 @@ Samples and Demos classic basic/* userspace/* + sysbuild/* subsys/subsys.rst net/net.rst bluetooth/bluetooth.rst diff --git a/samples/sysbuild/sysbuild.rst b/samples/sysbuild/sysbuild.rst new file mode 100644 index 00000000000000..c959e82a3a3bac --- /dev/null +++ b/samples/sysbuild/sysbuild.rst @@ -0,0 +1,10 @@ +.. _sysbuild-samples: + +Sysbuild samples +################ + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/application_development/sysbuild/with_mcuboot/CMakeLists.txt b/samples/sysbuild/with_mcuboot/CMakeLists.txt similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/CMakeLists.txt rename to samples/sysbuild/with_mcuboot/CMakeLists.txt diff --git a/samples/application_development/sysbuild/with_mcuboot/README.rst b/samples/sysbuild/with_mcuboot/README.rst similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/README.rst rename to samples/sysbuild/with_mcuboot/README.rst diff --git a/samples/application_development/sysbuild/with_mcuboot/prj.conf b/samples/sysbuild/with_mcuboot/prj.conf similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/prj.conf rename to samples/sysbuild/with_mcuboot/prj.conf diff --git a/samples/application_development/sysbuild/with_mcuboot/sample.yaml b/samples/sysbuild/with_mcuboot/sample.yaml similarity index 90% rename from samples/application_development/sysbuild/with_mcuboot/sample.yaml rename to samples/sysbuild/with_mcuboot/sample.yaml index 785bc0d24004d0..e1f456405a7cc8 100644 --- a/samples/application_development/sysbuild/with_mcuboot/sample.yaml +++ b/samples/sysbuild/with_mcuboot/sample.yaml @@ -2,7 +2,7 @@ sample: description: Sample with MCUboot built through sysbuild name: with mcuboot tests: - sample.application_development.sysbuild.with_mcuboot: + sample.sysbuild.with_mcuboot: sysbuild: true # Platform allowed is used as twister using sysbuild still lacks proper # filtering support, see discussion in #49552. diff --git a/samples/application_development/sysbuild/with_mcuboot/src/main.c b/samples/sysbuild/with_mcuboot/src/main.c similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/src/main.c rename to samples/sysbuild/with_mcuboot/src/main.c diff --git a/samples/application_development/sysbuild/with_mcuboot/sysbuild.conf b/samples/sysbuild/with_mcuboot/sysbuild.conf similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/sysbuild.conf rename to samples/sysbuild/with_mcuboot/sysbuild.conf diff --git a/samples/application_development/sysbuild/with_mcuboot/sysbuild/mcuboot.conf b/samples/sysbuild/with_mcuboot/sysbuild/mcuboot.conf similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/sysbuild/mcuboot.conf rename to samples/sysbuild/with_mcuboot/sysbuild/mcuboot.conf From 8b9ef52b8f659cc981a7071624b434d95e8f4d6d Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0575/1389] samples: sysbuild: add hello world for multiple board targets Add a new "hello world" sample that can be built for multiple board targets. This sample can be used to see if Zephyr boots successfully with _minimal_ configuration on SoCs with multiple cores, or boards with multiple SoCs. The following configurations are provided for now: - nRF5340 DK: cpuapp+cpunet - nRF54H20 DK: cpuapp+cpurad, cpuapp+cpuppr, cpuapp+cpuppr(xip) Note that because of a quoting bug somewhere in the build system, SB_CONFIG_REMOTE_BOARD is specified in .conf files (see the sysbuild/ directory). This should be fixed in the near future. Signed-off-by: Gerard Marull-Paretas --- samples/sysbuild/hello_world/CMakeLists.txt | 8 +++ samples/sysbuild/hello_world/Kconfig.sysbuild | 7 ++ samples/sysbuild/hello_world/README.rst | 69 +++++++++++++++++++ .../boards/nrf5340dk_nrf5340_cpuapp.conf | 4 ++ samples/sysbuild/hello_world/prj.conf | 1 + .../hello_world/remote/CMakeLists.txt | 8 +++ samples/sysbuild/hello_world/remote/prj.conf | 1 + samples/sysbuild/hello_world/sample.yaml | 44 ++++++++++++ samples/sysbuild/hello_world/src/main.c | 13 ++++ samples/sysbuild/hello_world/sysbuild.cmake | 15 ++++ .../sysbuild/nrf5340dk_nrf5340_cpunet.conf | 1 + .../sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf | 1 + .../nrf54h20dk_nrf54h20_cpuppr_xip.conf | 1 + .../sysbuild/nrf54h20dk_nrf54h20_cpurad.conf | 1 + 14 files changed, 174 insertions(+) create mode 100644 samples/sysbuild/hello_world/CMakeLists.txt create mode 100644 samples/sysbuild/hello_world/Kconfig.sysbuild create mode 100644 samples/sysbuild/hello_world/README.rst create mode 100644 samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf create mode 100644 samples/sysbuild/hello_world/prj.conf create mode 100644 samples/sysbuild/hello_world/remote/CMakeLists.txt create mode 100644 samples/sysbuild/hello_world/remote/prj.conf create mode 100644 samples/sysbuild/hello_world/sample.yaml create mode 100644 samples/sysbuild/hello_world/src/main.c create mode 100644 samples/sysbuild/hello_world/sysbuild.cmake create mode 100644 samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf create mode 100644 samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf create mode 100644 samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf create mode 100644 samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf diff --git a/samples/sysbuild/hello_world/CMakeLists.txt b/samples/sysbuild/hello_world/CMakeLists.txt new file mode 100644 index 00000000000000..f58082ab8dfd85 --- /dev/null +++ b/samples/sysbuild/hello_world/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(hello_world) +target_sources(app PRIVATE src/main.c) diff --git a/samples/sysbuild/hello_world/Kconfig.sysbuild b/samples/sysbuild/hello_world/Kconfig.sysbuild new file mode 100644 index 00000000000000..edec01b94c98d8 --- /dev/null +++ b/samples/sysbuild/hello_world/Kconfig.sysbuild @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" + +config REMOTE_BOARD + string "The board used for remote target" diff --git a/samples/sysbuild/hello_world/README.rst b/samples/sysbuild/hello_world/README.rst new file mode 100644 index 00000000000000..2cb0208205188f --- /dev/null +++ b/samples/sysbuild/hello_world/README.rst @@ -0,0 +1,69 @@ +.. zephyr:code-sample:: sysbuild_hello_world + :name: Hello World for multiple board targets using Sysbuild + + Run a hello world sample on multiple board targets + +Overview +******** + +The sample demonstrates how to build a Hello World application for two board +targets with :ref:`sysbuild`. This sample can be useful to test, for example, +SoCs with multiple cores as each core is exposed as a board target. Other +scenarios could include boards embedding multiple SoCs. When building with +Zephyr Sysbuild, the build system adds additional images based on the options +selected in the project's additional configuration and build files. + +All images use the same :file:`main.c` that prints the board target on which the +application is programmed. + +Building and Running +******************** + +This sample needs to be built with Sysbuild by using the ``--sysbuild`` option. +The remote board needs to be specified using ``SB_CONFIG_REMOTE_BOARD``. Some +additional settings may be required depending on the platform, for example, +to boot a remote core. + +.. note:: + It is recommended to use sample setups from + :zephyr_file:`samples/basic/multitarget_hello_world/sample.yaml` using the + ``-T`` option. + +Here's an example to build and flash the sample for the +:ref:`nrf54h20dk_nrf54h20`, using application and radio cores: + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/multitarget_hello_world + :board: nrf54h20dk/nrf54h20/cpuapp + :west-args: --sysbuild + :gen-args: -DSB_CONFIG_REMOTE_BOARD='"nrf54h20dk/nrf54h20/cpurad"' + :goals: build flash + :compact: + +The same can be achieved by using the +:zephyr_file:`samples/basic/multitarget_hello_world/sample.yaml` setup: + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/multitarget_hello_world + :board: nrf54h20dk/nrf54h20/cpuapp + :west-args: -T sample.basic.multitarget_hello_world.nrf54h20dk_cpuapp_cpurad + :goals: build flash + :compact: + +After programming the sample to your board, you should observe a hello world +message in the Zephyr console configured on each target. For example, for the +sample above: + +Application core + + .. code-block:: console + + *** Booting Zephyr OS build v3.6.0-274-g466084bd8c5d *** + Hello world from nrf54h20dk/nrf54h20/cpuapp + +Radio core + + .. code-block:: console + + *** Booting Zephyr OS build v3.6.0-274-g466084bd8c5d *** + Hello world from nrf54h20dk/nrf54h20/cpurad diff --git a/samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..046b18c7559ab9 --- /dev/null +++ b/samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ENABLE_CPUNET=y diff --git a/samples/sysbuild/hello_world/prj.conf b/samples/sysbuild/hello_world/prj.conf new file mode 100644 index 00000000000000..becd6a5481915e --- /dev/null +++ b/samples/sysbuild/hello_world/prj.conf @@ -0,0 +1 @@ +# no additional configuration is required diff --git a/samples/sysbuild/hello_world/remote/CMakeLists.txt b/samples/sysbuild/hello_world/remote/CMakeLists.txt new file mode 100644 index 00000000000000..62961aff1840b5 --- /dev/null +++ b/samples/sysbuild/hello_world/remote/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(remote) +target_sources(app PRIVATE ../src/main.c) diff --git a/samples/sysbuild/hello_world/remote/prj.conf b/samples/sysbuild/hello_world/remote/prj.conf new file mode 100644 index 00000000000000..becd6a5481915e --- /dev/null +++ b/samples/sysbuild/hello_world/remote/prj.conf @@ -0,0 +1 @@ +# no additional configuration is required diff --git a/samples/sysbuild/hello_world/sample.yaml b/samples/sysbuild/hello_world/sample.yaml new file mode 100644 index 00000000000000..5add79c52ba826 --- /dev/null +++ b/samples/sysbuild/hello_world/sample.yaml @@ -0,0 +1,44 @@ +sample: + name: Hello World for multiple board targets using Sysbuild + description: | + Hello World application that builds for multiple targets. Both images print + the board target they were run on. + +common: + build_only: true + sysbuild: true + +tests: + sample.sysbuild.hello_world.nrf5340dk_cpuapp_cpunet: + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf5340dk_nrf5340_cpunet.conf + + sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpurad: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf + + sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpuppr: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf + hello_world_SNIPPET=nordic-ppr + + sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpuppr_xip: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf + hello_world_SNIPPET=nordic-ppr-xip diff --git a/samples/sysbuild/hello_world/src/main.c b/samples/sysbuild/hello_world/src/main.c new file mode 100644 index 00000000000000..af5b6fd3dbe747 --- /dev/null +++ b/samples/sysbuild/hello_world/src/main.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +int main(void) +{ + printk("Hello world from %s\n", CONFIG_BOARD_TARGET); + + return 0; +} diff --git a/samples/sysbuild/hello_world/sysbuild.cmake b/samples/sysbuild/hello_world/sysbuild.cmake new file mode 100644 index 00000000000000..b59062d881f171 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild.cmake @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") + message(FATAL_ERROR "REMOTE_BOARD must be set to a valid board name") +endif() + +ExternalZephyrProject_Add( + APPLICATION remote + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_REMOTE_BOARD} +) + +add_dependencies(hello_world remote) +sysbuild_add_dependencies(FLASH hello_world remote) diff --git a/samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf b/samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..b8ae05d4ef6fa6 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf5340dk/nrf5340/cpunet" diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf new file mode 100644 index 00000000000000..f50bc8553a0118 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpuppr" diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf new file mode 100644 index 00000000000000..270c92c09a4f3f --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpuppr/xip" diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000000..dd863e78d99339 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpurad" From 96ab7456d8103c0e05cf62c8ef3fa845a6bba2fd Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0576/1389] drivers: uart_stm32: add DCache support in async DMA mode Adapt the driver to verify if DMA buffers are located in noncacheable memory when DCache is activated, in order to avoid cache coherency issues. This is required until manual cache coherency management is implemented. Signed-off-by: Abderrahmane Jarmouni --- drivers/serial/uart_stm32.c | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index e79ba3bf0f3e91..f5a831f0d2b834 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Open-RnD Sp. z o.o. * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,6 +40,12 @@ #include #endif /* CONFIG_PM */ +#ifdef CONFIG_DCACHE +#include +#include +#include +#endif /* CONFIG_DCACHE */ + #include #include LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL); @@ -1301,6 +1308,32 @@ static void uart_stm32_isr(const struct device *dev) #ifdef CONFIG_UART_ASYNC_API +#ifdef CONFIG_DCACHE +static bool buf_in_nocache(uintptr_t buf, size_t len_bytes) +{ + bool buf_within_nocache = false; + +#ifdef CONFIG_NOCACHE_MEMORY + buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) && + ((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end)); + if (buf_within_nocache) { + return true; + } +#endif /* CONFIG_NOCACHE_MEMORY */ + + buf_within_nocache = mem_attr_check_buf( + (void *)buf, len_bytes, DT_MEM_ARM_MPU_RAM_NOCACHE) == 0; + if (buf_within_nocache) { + return true; + } + + buf_within_nocache = (buf >= ((uintptr_t)__rodata_region_start)) && + ((buf + len_bytes - 1) <= ((uintptr_t)__rodata_region_end)); + + return buf_within_nocache; +} +#endif /* CONFIG_DCACHE */ + static int uart_stm32_async_callback_set(const struct device *dev, uart_callback_t callback, void *user_data) @@ -1512,6 +1545,13 @@ static int uart_stm32_async_tx(const struct device *dev, return -EBUSY; } +#ifdef CONFIG_DCACHE + if (!buf_in_nocache((uintptr_t)tx_data, buf_size)) { + LOG_ERR("Tx buffer should be placed in a nocache memory region"); + return -EFAULT; + } +#endif /* CONFIG_DCACHE */ + data->dma_tx.buffer = (uint8_t *)tx_data; data->dma_tx.buffer_length = buf_size; data->dma_tx.timeout = timeout; @@ -1572,6 +1612,13 @@ static int uart_stm32_async_rx_enable(const struct device *dev, return -EBUSY; } +#ifdef CONFIG_DCACHE + if (!buf_in_nocache((uintptr_t)rx_buf, buf_size)) { + LOG_ERR("Rx buffer should be placed in a nocache memory region"); + return -EFAULT; + } +#endif /* CONFIG_DCACHE */ + data->dma_rx.offset = 0; data->dma_rx.buffer = rx_buf; data->dma_rx.buffer_length = buf_size; @@ -1696,6 +1743,12 @@ static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, } else if (!data->dma_rx.enabled) { err = -EACCES; } else { +#ifdef CONFIG_DCACHE + if (!buf_in_nocache((uintptr_t)buf, len)) { + LOG_ERR("Rx buffer should be placed in a nocache memory region"); + return -EFAULT; + } +#endif /* CONFIG_DCACHE */ data->rx_next_buffer = buf; data->rx_next_buffer_len = len; } From 8c531712be379cbaba0f5255244efd7d88671bb1 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0577/1389] tests: drivers: uart: async_api: support DCache with nocache memory Add support for running tests with DCache enabled & put DMA buffers in a nocache memory region to avoid coherency issues. Signed-off-by: Abderrahmane Jarmouni --- tests/drivers/uart/uart_async_api/Kconfig | 21 ++++++ .../uart/uart_async_api/src/test_uart_async.c | 75 ++++++++++++++++++- 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 tests/drivers/uart/uart_async_api/Kconfig diff --git a/tests/drivers/uart/uart_async_api/Kconfig b/tests/drivers/uart/uart_async_api/Kconfig new file mode 100644 index 00000000000000..6883eb23509676 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/Kconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2024 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "UART Async Test" + +source "Kconfig.zephyr" + +if DCACHE + +config DT_DEFINED_NOCACHE + bool "Enable this if a nocache region is defined in devicetree" + +if DT_DEFINED_NOCACHE + +config DT_DEFINED_NOCACHE_NAME + string "Name of the nocache region defined in devicetree (uppercase)" + +endif # DT_DEFINED_NOCACHE + +endif # DCACHE diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index 26c8de398978bc..15b4b6fba41a9a 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -1,11 +1,22 @@ /* - * Copyright (c) 2019 Nordic Semiconductor ASA + * Copyright (c) 2019 Nordic Semiconductor ASA + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ #include "test_uart.h" +#if defined(CONFIG_DCACHE) && defined(CONFIG_DT_DEFINED_NOCACHE) +#define __NOCACHE __attribute__ ((__section__(CONFIG_DT_DEFINED_NOCACHE_NAME))) +#define NOCACHE_MEM 1 +#elif defined(CONFIG_DCACHE) && defined(CONFIG_NOCACHE_MEMORY) +#define __NOCACHE __nocache +#define NOCACHE_MEM 1 +#else +#define NOCACHE_MEM 0 +#endif /* CONFIG_NOCACHE_MEMORY */ + K_SEM_DEFINE(tx_done, 0, 1); K_SEM_DEFINE(tx_aborted, 0, 1); K_SEM_DEFINE(rx_rdy, 0, 1); @@ -79,14 +90,18 @@ static void uart_async_test_init(void) struct test_data { volatile uint32_t tx_aborted_count; - uint8_t rx_first_buffer[10]; + __aligned(32) uint8_t rx_first_buffer[10]; uint32_t recv_bytes_first_buffer; - uint8_t rx_second_buffer[5]; + __aligned(32) uint8_t rx_second_buffer[5]; uint32_t recv_bytes_second_buffer; bool supply_second_buffer; }; +#if NOCACHE_MEM +static struct test_data tdata __used __NOCACHE; +#else ZTEST_BMEM struct test_data tdata; +#endif /* NOCACHE_MEM */ static void test_single_read_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -308,8 +323,13 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) tdata_check_recv_buffers(tx_buf, sizeof(tx_buf)); } +#if NOCACHE_MEM +static __aligned(32) uint8_t chained_read_buf[2][8] __used __NOCACHE; +static __aligned(32) uint8_t chained_cpy_buf[10] __used __NOCACHE; +#else ZTEST_BMEM uint8_t chained_read_buf[2][8]; ZTEST_BMEM uint8_t chained_cpy_buf[10]; +#endif /* NOCACHE_MEM */ ZTEST_BMEM volatile uint8_t rx_data_idx; ZTEST_BMEM uint8_t rx_buf_idx; @@ -358,7 +378,11 @@ static void *chained_read_setup(void) ZTEST_USER(uart_async_chain_read, test_chained_read) { +#if NOCACHE_MEM + static __aligned(32) uint8_t tx_buf[10] __used __NOCACHE; +#else uint8_t tx_buf[10]; +#endif /* NOCACHE_MEM */ int iter = 6; uint32_t rx_timeout_ms = 50; int err; @@ -390,7 +414,11 @@ ZTEST_USER(uart_async_chain_read, test_chained_read) "RX_DISABLED timeout"); } +#if NOCACHE_MEM +static __aligned(32) uint8_t double_buffer[2][12] __used __NOCACHE; +#else ZTEST_BMEM uint8_t double_buffer[2][12]; +#endif /* NOCACHE_MEM */ ZTEST_DMEM uint8_t *next_buf = double_buffer[1]; static void test_double_buffer_callback(const struct device *dev, @@ -431,7 +459,11 @@ static void *double_buffer_setup(void) ZTEST_USER(uart_async_double_buf, test_double_buffer) { +#if NOCACHE_MEM + static __aligned(32) uint8_t tx_buf[4] __used __NOCACHE; +#else uint8_t tx_buf[4]; +#endif /* NOCACHE_MEM */ zassert_equal(uart_rx_enable(uart_dev, double_buffer[0], @@ -456,8 +488,13 @@ ZTEST_USER(uart_async_double_buf, test_double_buffer) "RX_DISABLED timeout"); } +#if NOCACHE_MEM +static __aligned(32) uint8_t test_read_abort_rx_buf[2][100] __used __NOCACHE; +static __aligned(32) uint8_t test_read_abort_read_buf[100] __used __NOCACHE; +#else ZTEST_BMEM uint8_t test_read_abort_rx_buf[2][100]; ZTEST_BMEM uint8_t test_read_abort_read_buf[100]; +#endif /* NOCACHE_MEM */ ZTEST_BMEM int test_read_abort_rx_cnt; static void test_read_abort_callback(const struct device *dev, @@ -526,8 +563,13 @@ static void *read_abort_setup(void) ZTEST_USER(uart_async_read_abort, test_read_abort) { +#if NOCACHE_MEM + static __aligned(32) uint8_t rx_buf[100] __used __NOCACHE; + static __aligned(32) uint8_t tx_buf[100] __used __NOCACHE; +#else uint8_t rx_buf[100]; uint8_t tx_buf[100]; +#endif /* NOCACHE_MEM */ memset(rx_buf, 0, sizeof(rx_buf)); memset(tx_buf, 1, sizeof(tx_buf)); @@ -568,7 +610,11 @@ ZTEST_USER(uart_async_read_abort, test_read_abort) ZTEST_BMEM volatile size_t sent; ZTEST_BMEM volatile size_t received; +#if NOCACHE_MEM +static __aligned(32) uint8_t test_rx_buf[2][100] __used __NOCACHE; +#else ZTEST_BMEM uint8_t test_rx_buf[2][100]; +#endif /* NOCACHE_MEM */ static void test_write_abort_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -612,7 +658,11 @@ static void *write_abort_setup(void) ZTEST_USER(uart_async_write_abort, test_write_abort) { +#if NOCACHE_MEM + static __aligned(32) uint8_t tx_buf[100] __used __NOCACHE; +#else uint8_t tx_buf[100]; +#endif /* NOCACHE_MEM */ memset(test_rx_buf, 0, sizeof(test_rx_buf)); memset(tx_buf, 1, sizeof(tx_buf)); @@ -681,8 +731,13 @@ static void *forever_timeout_setup(void) ZTEST_USER(uart_async_timeout, test_forever_timeout) { +#if NOCACHE_MEM + static __aligned(32) uint8_t rx_buf[100] __used __NOCACHE; + static __aligned(32) uint8_t tx_buf[100] __used __NOCACHE; +#else uint8_t rx_buf[100]; uint8_t tx_buf[100]; +#endif /* NOCACHE_MEM */ memset(rx_buf, 0, sizeof(rx_buf)); memset(tx_buf, 1, sizeof(tx_buf)); @@ -715,7 +770,11 @@ ZTEST_USER(uart_async_timeout, test_forever_timeout) } +#if NOCACHE_MEM +const uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"}; +#else ZTEST_DMEM uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"}; +#endif /* NOCACHE_MEM */ ZTEST_DMEM bool chained_write_next_buf = true; ZTEST_BMEM volatile uint8_t tx_sent; @@ -761,7 +820,11 @@ static void *chained_write_setup(void) ZTEST_USER(uart_async_chain_write, test_chained_write) { +#if NOCACHE_MEM + static __aligned(32) uint8_t rx_buf[20] __used __NOCACHE; +#else uint8_t rx_buf[20]; +#endif /* NOCACHE_MEM */ memset(rx_buf, 0, sizeof(rx_buf)); @@ -787,9 +850,15 @@ ZTEST_USER(uart_async_chain_write, test_chained_write) "RX_DISABLED timeout"); } +#if NOCACHE_MEM +static __aligned(32) uint8_t long_rx_buf[1024] __used __NOCACHE; +static __aligned(32) uint8_t long_rx_buf2[1024] __used __NOCACHE; +static __aligned(32) uint8_t long_tx_buf[1000] __used __NOCACHE; +#else ZTEST_BMEM uint8_t long_rx_buf[1024]; ZTEST_BMEM uint8_t long_rx_buf2[1024]; ZTEST_BMEM uint8_t long_tx_buf[1000]; +#endif /* NOCACHE_MEM */ ZTEST_BMEM volatile uint8_t evt_num; ZTEST_BMEM size_t long_received[2]; From e01fe74ac089da6e825882211edc2a3c360408f6 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0578/1389] tests: drivers: uart_async: stm32: add test cases with DCache enabled Add test cases/configs for async DMA uart with DCache on STM32F7/H7 boards Signed-off-by: Abderrahmane Jarmouni --- .../boards/nucleo_f746zg_nocachemem.overlay | 17 +++++++++ .../boards/nucleo_h723zg.overlay | 13 +++++-- .../boards/nucleo_h723zg_nocachemem.overlay | 12 +++++++ .../uart_async_api/stm32_nocache_mem_dt.conf | 4 +++ .../drivers/uart/uart_async_api/testcase.yaml | 36 +++++++++++++++++++ 5 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 tests/drivers/uart/uart_async_api/boards/nucleo_f746zg_nocachemem.overlay create mode 100644 tests/drivers/uart/uart_async_api/boards/nucleo_h723zg_nocachemem.overlay create mode 100644 tests/drivers/uart/uart_async_api/stm32_nocache_mem_dt.conf diff --git a/tests/drivers/uart/uart_async_api/boards/nucleo_f746zg_nocachemem.overlay b/tests/drivers/uart/uart_async_api/boards/nucleo_f746zg_nocachemem.overlay new file mode 100644 index 00000000000000..2657a0bf45f422 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nucleo_f746zg_nocachemem.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + /* The async_api.nocache_mem_dt test case expects a non-cachable RAM region */ + sram_nocache: memory@2004c000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2004c000 DT_SIZE_K(16)>; + zephyr,memory-region = "RAM_NOCACHE"; + zephyr,memory-attr = ; + }; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg.overlay b/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg.overlay index 1eef7ad3ae93e9..9ecaf11a0817a6 100644 --- a/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg.overlay @@ -1,11 +1,18 @@ /* + * Copyright (c) 2024 STMicroelectronics + * * SPDX-License-Identifier: Apache-2.0 */ -dut: &usart2 { - dmas = <&dmamux1 2 44 STM32_DMA_PERIPH_TX>, - <&dmamux1 3 43 STM32_DMA_PERIPH_RX>; +/* Arduino Header pins: Tx:D9, Rx:D10 */ +dut: &uart9 { + pinctrl-0 = <&uart9_tx_pd15 &uart9_rx_pd14>; + pinctrl-names = "default"; + current-speed = <115200>; + dmas = <&dmamux1 2 117 STM32_DMA_PERIPH_TX>, + <&dmamux1 3 116 STM32_DMA_PERIPH_RX>; dma-names = "tx", "rx"; + status = "okay"; }; &dma1 { diff --git a/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg_nocachemem.overlay b/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg_nocachemem.overlay new file mode 100644 index 00000000000000..fc9393dcf42479 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nucleo_h723zg_nocachemem.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&sram1 { + zephyr,memory-attr = ; + zephyr,memory-region = "RAM_NOCACHE"; +}; diff --git a/tests/drivers/uart/uart_async_api/stm32_nocache_mem_dt.conf b/tests/drivers/uart/uart_async_api/stm32_nocache_mem_dt.conf new file mode 100644 index 00000000000000..1d24d39f824369 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/stm32_nocache_mem_dt.conf @@ -0,0 +1,4 @@ +CONFIG_DCACHE=y +CONFIG_DT_DEFINED_NOCACHE=y +CONFIG_DT_DEFINED_NOCACHE_NAME="RAM_NOCACHE" +CONFIG_USERSPACE=n diff --git a/tests/drivers/uart/uart_async_api/testcase.yaml b/tests/drivers/uart/uart_async_api/testcase.yaml index a3665f7c570c36..e7a970d4a58abe 100644 --- a/tests/drivers/uart/uart_async_api/testcase.yaml +++ b/tests/drivers/uart/uart_async_api/testcase.yaml @@ -74,3 +74,39 @@ tests: - CONFIG_UART_SAM0_ASYNC=y - CONFIG_DMA=y build_only: true + drivers.uart.async_api.nocache_mem: + # nocache memory region is defined by the linker + filter: CONFIG_SERIAL_SUPPORT_ASYNC and CONFIG_CPU_HAS_DCACHE + harness: ztest + harness_config: + fixture: gpio_loopback + depends_on: gpio + platform_allow: + - nucleo_f746zg + - nucleo_h723zg + extra_configs: + - CONFIG_DCACHE=y + - CONFIG_NOCACHE_MEMORY=y + - CONFIG_USERSPACE=n + drivers.uart.async_api.nocache_mem_dt.nucleo_f746zg: + # nocache memory region is defined in DT + harness: ztest + harness_config: + fixture: gpio_loopback + depends_on: gpio + platform_allow: + - nucleo_f746zg + extra_args: + - DTC_OVERLAY_FILE="boards/nucleo_f746zg.overlay;boards/nucleo_f746zg_nocachemem.overlay" + - EXTRA_CONF_FILE=stm32_nocache_mem_dt.conf + drivers.uart.async_api.nocache_mem_dt.nucleo_h723zg: + # nocache memory region is defined in DT + harness: ztest + harness_config: + fixture: gpio_loopback + depends_on: gpio + platform_allow: + - nucleo_h723zg + extra_args: + - DTC_OVERLAY_FILE="boards/nucleo_h723zg.overlay;boards/nucleo_h723zg_nocachemem.overlay" + - EXTRA_CONF_FILE=stm32_nocache_mem_dt.conf From ed38e27ca34a8345845124a1102554dcc72c19e8 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0579/1389] board: arm: nucleo_f746zg: flashing Add the possibility to flash nucleo-f746zg board using west STM32CubeProgrammer runner. Signed-off-by: Abderrahmane Jarmouni --- boards/st/nucleo_f746zg/board.cmake | 2 ++ boards/st/nucleo_f746zg/doc/index.rst | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/boards/st/nucleo_f746zg/board.cmake b/boards/st/nucleo_f746zg/board.cmake index 8bbeabfe486302..718b783f69df06 100644 --- a/boards/st/nucleo_f746zg/board.cmake +++ b/boards/st/nucleo_f746zg/board.cmake @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") board_runner_args(jlink "--device=STM32F746ZG" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/nucleo_f746zg/doc/index.rst b/boards/st/nucleo_f746zg/doc/index.rst index dcbff3ca0bc37e..f06415451704e8 100644 --- a/boards/st/nucleo_f746zg/doc/index.rst +++ b/boards/st/nucleo_f746zg/doc/index.rst @@ -191,6 +191,17 @@ Nucleo F746ZG board includes an ST-LINK/V2-1 embedded debug tool interface. Flashing an application to Nucleo F746ZG ---------------------------------------- +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its installation is required to be able to flash the board. + +Alternatively, openocd (provided in Zephyr SDK) or JLink can also be used to +flash the board using the ``--runner`` (or ``-r``) option: + +.. code-block:: console + + $ west flash --runner openocd + $ west flash --runner jlink + Here is an example for the :ref:`hello_world` application. Run a serial host program to connect with your Nucleo board. @@ -235,3 +246,6 @@ You can debug an application in the usual way. Here is an example for the .. _STM32F746 reference manual: https://www.st.com/resource/en/reference_manual/dm00124865.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html From 00ca5eabc07dfe2ca472bd13a3d447c7e01427ef Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0580/1389] drivers: serial: bt: Use dedicated Workqueue Stop relying on the system workqueue, as the BT TX APIs should potentially block and now by design this will not work with the Bluetooth Stack (for good reasons). Now the UART NUS driver has a dedicated workqueue, which all NUS instances share. Signed-off-by: Luis Ubieda --- drivers/serial/uart_bt.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/serial/uart_bt.c b/drivers/serial/uart_bt.c index ad450eea9aa236..a68f747f69f1a0 100644 --- a/drivers/serial/uart_bt.c +++ b/drivers/serial/uart_bt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -14,6 +15,9 @@ #include LOG_MODULE_REGISTER(uart_nus, CONFIG_UART_LOG_LEVEL); +K_THREAD_STACK_DEFINE(nus_work_queue_stack, 2048); +static struct k_work_q nus_work_queue; + struct uart_bt_data { struct { struct bt_nus_inst *inst; @@ -47,7 +51,7 @@ static void bt_notif_enabled(bool enabled, void *ctx) LOG_DBG("%s() - %s", __func__, enabled ? "enabled" : "disabled"); if (!ring_buf_is_empty(dev_data->uart.tx_ringbuf)) { - k_work_reschedule(&dev_data->uart.tx_work, K_NO_WAIT); + k_work_reschedule_for_queue(&nus_work_queue, &dev_data->uart.tx_work, K_NO_WAIT); } } @@ -71,7 +75,7 @@ static void bt_received(struct bt_conn *conn, const void *data, uint16_t len, vo LOG_ERR("RX Ring buffer full. received: %d, added to queue: %d", len, put_len); } - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } static void cb_work_handler(struct k_work *work) @@ -113,7 +117,7 @@ static void tx_work_handler(struct k_work *work) } while (len > 0 && !err); if ((ring_buf_space_get(dev_data->uart.tx_ringbuf) > 0) && dev_data->uart.tx_irq_ena) { - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } } @@ -128,7 +132,7 @@ static int uart_bt_fifo_fill(const struct device *dev, const uint8_t *tx_data, i } if (atomic_get(&dev_data->bt.enabled)) { - k_work_reschedule(&dev_data->uart.tx_work, K_NO_WAIT); + k_work_reschedule_for_queue(&nus_work_queue, &dev_data->uart.tx_work, K_NO_WAIT); } return wrote; @@ -169,7 +173,7 @@ static void uart_bt_poll_out(const struct device *dev, unsigned char c) * data, so more than one byte is transmitted (e.g: when poll_out is * called inside a for-loop). */ - k_work_schedule(&dev_data->uart.tx_work, K_MSEC(1)); + k_work_schedule_for_queue(&nus_work_queue, &dev_data->uart.tx_work, K_MSEC(1)); } } @@ -191,7 +195,7 @@ static void uart_bt_irq_tx_enable(const struct device *dev) dev_data->uart.tx_irq_ena = true; if (uart_bt_irq_tx_ready(dev)) { - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } } @@ -219,7 +223,7 @@ static void uart_bt_irq_rx_enable(const struct device *dev) dev_data->uart.rx_irq_ena = true; - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } static void uart_bt_irq_rx_disable(const struct device *dev) @@ -267,6 +271,19 @@ static const struct uart_driver_api uart_bt_driver_api = { .irq_callback_set = uart_bt_irq_callback_set, }; +static int uart_bt_workqueue_init(void) +{ + k_work_queue_init(&nus_work_queue); + k_work_queue_start(&nus_work_queue, nus_work_queue_stack, + K_THREAD_STACK_SIZEOF(nus_work_queue_stack), + K_LOWEST_APPLICATION_THREAD_PRIO, NULL); + + return 0; +} + +/** The work-queue is shared across all instances, hence we initialize it separatedly */ +SYS_INIT(uart_bt_workqueue_init, POST_KERNEL, CONFIG_SERIAL_INIT_PRIORITY); + static int uart_bt_init(const struct device *dev) { int err; From 061054621f5651e52dd002575de7a4149af4f1c0 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0581/1389] serial: bt: Set configurable options for the NUS Work-queue Default priority set to Main Thread's and Stack-size set to 1KiB. This should still allow for the System work-queue, considering this Work-queue could be temporarily blocked on BT TX commands. Signed-off-by: Luis Ubieda --- drivers/serial/Kconfig.bt | 16 ++++++++++++++++ drivers/serial/uart_bt.c | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/serial/Kconfig.bt b/drivers/serial/Kconfig.bt index 500613d6208e89..214109759ae0b6 100644 --- a/drivers/serial/Kconfig.bt +++ b/drivers/serial/Kconfig.bt @@ -11,3 +11,19 @@ config UART_BT help Enable the UART over NUS Bluetooth driver, which can be used to pipe serial data over Bluetooth LE GATT using NUS (Nordic UART Service). + +if UART_BT + +config UART_BT_WORKQUEUE_PRIORITY + int "UART NUS Work-queue Priority" + default MAIN_THREAD_PRIORITY + help + Select UART NUS Work-queue priority based on the application context. + +config UART_BT_WORKQUEUE_STACK_SIZE + int "UART NUS Work-queue Stack Size" + default 1024 + help + Set UART NUS Work-queue Stack-size based on the application context. + +endif diff --git a/drivers/serial/uart_bt.c b/drivers/serial/uart_bt.c index a68f747f69f1a0..9e4a4de593006e 100644 --- a/drivers/serial/uart_bt.c +++ b/drivers/serial/uart_bt.c @@ -15,7 +15,7 @@ #include LOG_MODULE_REGISTER(uart_nus, CONFIG_UART_LOG_LEVEL); -K_THREAD_STACK_DEFINE(nus_work_queue_stack, 2048); +K_THREAD_STACK_DEFINE(nus_work_queue_stack, CONFIG_UART_BT_WORKQUEUE_STACK_SIZE); static struct k_work_q nus_work_queue; struct uart_bt_data { @@ -276,7 +276,7 @@ static int uart_bt_workqueue_init(void) k_work_queue_init(&nus_work_queue); k_work_queue_start(&nus_work_queue, nus_work_queue_stack, K_THREAD_STACK_SIZEOF(nus_work_queue_stack), - K_LOWEST_APPLICATION_THREAD_PRIO, NULL); + CONFIG_UART_BT_WORKQUEUE_PRIORITY, NULL); return 0; } From 182ea5d6ae9752b2bf5e60de1cab3d726d1ca907 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:56 +0200 Subject: [PATCH 0582/1389] soc: nxp: imxrt: allow configuring system pll on iMXRT10xx series Allow configuration of the system pll on the iMXRT10xx series parts, via a fractional pll node under the CCM module. Signed-off-by: Daniel DeGrasse --- dts/arm/nxp/nxp_rt10xx.dtsi | 9 ++++++ dts/bindings/clock/nxp,imx-ccm-fnpll.yaml | 38 +++++++++++++++++++++++ soc/nxp/imxrt/Kconfig | 3 ++ soc/nxp/imxrt/imxrt10xx/soc.c | 14 +++++++++ 4 files changed, 64 insertions(+) create mode 100644 dts/bindings/clock/nxp,imx-ccm-fnpll.yaml diff --git a/dts/arm/nxp/nxp_rt10xx.dtsi b/dts/arm/nxp/nxp_rt10xx.dtsi index 6c827e7ce7fa71..fdc50c2b3e69a9 100644 --- a/dts/arm/nxp/nxp_rt10xx.dtsi +++ b/dts/arm/nxp/nxp_rt10xx.dtsi @@ -297,6 +297,15 @@ #clock-cells = <0>; }; + sys-pll { + compatible = "nxp,imx-ccm-fnpll"; + loop-div = <22>; + numerator = <0>; + denominator = <1>; + src = <0>; + #clock-cells = <0>; + }; + #clock-cells = <3>; }; diff --git a/dts/bindings/clock/nxp,imx-ccm-fnpll.yaml b/dts/bindings/clock/nxp,imx-ccm-fnpll.yaml new file mode 100644 index 00000000000000..cd18246823c892 --- /dev/null +++ b/dts/bindings/clock/nxp,imx-ccm-fnpll.yaml @@ -0,0 +1,38 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + i.MX CCM Fractional PLL. Output frequency is given by the following + formula: Fout = Fin * (loop-div + (numerator/denominator) + +compatible: "nxp,imx-ccm-fnpll" + +include: [clock-controller.yaml, base.yaml] + +properties: + "#clock-cells": + const: 0 + + loop-div: + type: int + required: true + description: | + Loop divider. Divides PLL feedback loop (effectively multiplying output + frequency) + + numerator: + type: int + required: true + description: | + Numerator of PLL multiplier fraction + + denominator: + type: int + required: true + description: | + Denominator of PLL multiplier fraction + + src: + type: int + required: true + description: Sets source for PLL input. SOC specific. diff --git a/soc/nxp/imxrt/Kconfig b/soc/nxp/imxrt/Kconfig index b249dbb312bbc7..ce96362b49d6bb 100644 --- a/soc/nxp/imxrt/Kconfig +++ b/soc/nxp/imxrt/Kconfig @@ -184,6 +184,9 @@ config INIT_ENET_PLL MIMXRT1021 - see commit 17f4d6bec7 ("soc: nxp_imx: fix ENET_PLL selection for MIMXRT1021"). +config INIT_SYS_PLL + bool "Initialize System PLL" + endif # SOC_SERIES_IMXRT10XX || SOC_SERIES_IMXRT11XX endif # SOC_FAMILY_NXP_IMXRT diff --git a/soc/nxp/imxrt/imxrt10xx/soc.c b/soc/nxp/imxrt/imxrt10xx/soc.c index 97e2eba977a493..c26a16bc032294 100644 --- a/soc/nxp/imxrt/imxrt10xx/soc.c +++ b/soc/nxp/imxrt/imxrt10xx/soc.c @@ -40,6 +40,16 @@ const clock_arm_pll_config_t armPllConfig = { }; #endif +#if CONFIG_INIT_SYS_PLL +/* Configure System PLL */ +const clock_sys_pll_config_t sysPllConfig = { + .loopDivider = (DT_PROP(DT_CHILD(CCM_NODE, sys_pll), loop_div) - 20) / 2, + .numerator = DT_PROP(DT_CHILD(CCM_NODE, sys_pll), numerator), + .denominator = DT_PROP(DT_CHILD(CCM_NODE, sys_pll), denominator), + .src = DT_PROP(DT_CHILD(CCM_NODE, sys_pll), src), +}; +#endif + #if CONFIG_USB_DC_NXP_EHCI /* USB PHY condfiguration */ #define BOARD_USB_PHY_D_CAL (0x0CU) @@ -160,6 +170,10 @@ static ALWAYS_INLINE void clock_init(void) CLOCK_InitVideoPll(&videoPllConfig); #endif +#if CONFIG_INIT_SYS_PLL + CLOCK_InitSysPll(&sysPllConfig); +#endif + #if DT_NODE_EXISTS(DT_CHILD(CCM_NODE, arm_podf)) /* Set ARM PODF */ BUILD_ASSERT_PODF_IN_RANGE(arm_podf, 1, 8); From 631aa525d834cca936df9dd14df31f41ee71f47f Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0583/1389] soc: nxp: imxrt: clock imxrt1042 SOC at 528 MHz iMXRT1042 SOC should be clocked at 528 MHz maximum. Correct the clock setup to use the system PLL. Fixes #70755 Signed-off-by: Daniel DeGrasse --- dts/arm/nxp/nxp_rt1040.dtsi | 7 +++++-- soc/nxp/imxrt/imxrt10xx/Kconfig | 1 + soc/nxp/imxrt/imxrt10xx/soc.c | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/dts/arm/nxp/nxp_rt1040.dtsi b/dts/arm/nxp/nxp_rt1040.dtsi index 70dd0b0d4ad287..888d4eb1bd9c61 100644 --- a/dts/arm/nxp/nxp_rt1040.dtsi +++ b/dts/arm/nxp/nxp_rt1040.dtsi @@ -11,7 +11,7 @@ }; &sysclk { - clock-frequency = <500000000>; + clock-frequency = <528000000>; }; &ccm { @@ -20,10 +20,13 @@ }; arm-podf { - clock-div = <2>; + clock-div = <1>; }; }; +&gpt2 { + gptfreq = <33000000>; +}; / { soc { diff --git a/soc/nxp/imxrt/imxrt10xx/Kconfig b/soc/nxp/imxrt/imxrt10xx/Kconfig index b91fbe0b3ec538..aa5e5e705013aa 100644 --- a/soc/nxp/imxrt/imxrt10xx/Kconfig +++ b/soc/nxp/imxrt/imxrt10xx/Kconfig @@ -70,6 +70,7 @@ config SOC_MIMXRT1042 select CPU_HAS_FPU_DOUBLE_PRECISION select CPU_HAS_ARM_MPU select INIT_ARM_PLL + select INIT_SYS_PLL config SOC_MIMXRT1051 select HAS_MCUX_ENET diff --git a/soc/nxp/imxrt/imxrt10xx/soc.c b/soc/nxp/imxrt/imxrt10xx/soc.c index c26a16bc032294..789f02099becad 100644 --- a/soc/nxp/imxrt/imxrt10xx/soc.c +++ b/soc/nxp/imxrt/imxrt10xx/soc.c @@ -186,8 +186,13 @@ static ALWAYS_INLINE void clock_init(void) BUILD_ASSERT_PODF_IN_RANGE(ipg_podf, 1, 4); CLOCK_SetDiv(kCLOCK_IpgDiv, DT_PROP(DT_CHILD(CCM_NODE, ipg_podf), clock_div) - 1); +#ifdef CONFIG_SOC_MIMXRT1042 + /* Set PRE_PERIPH_CLK to SYS_PLL */ + CLOCK_SetMux(kCLOCK_PrePeriphMux, 0x0); +#else /* Set PRE_PERIPH_CLK to PLL1, 1200M */ CLOCK_SetMux(kCLOCK_PrePeriphMux, 0x3); +#endif /* Set PERIPH_CLK MUX to PRE_PERIPH_CLK */ CLOCK_SetMux(kCLOCK_PeriphMux, 0x0); From ec3a00253a57120067ff66a7ccdfa5355a6c87fd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0584/1389] net: websocket: Ignore error during close if we are disconnected No need to return an error during a close if we are already disconnected. Signed-off-by: Jukka Rissanen --- subsys/net/lib/websocket/websocket.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index 9890571ff29ab7..d8c719483ac328 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -441,10 +441,15 @@ static int websocket_close_vmeth(void *obj) ret = websocket_interal_disconnect(ctx); if (ret < 0) { - NET_DBG("[%p] Cannot close (%d)", obj, ret); + /* Ignore error if we are not connected */ + if (ret != -ENOTCONN) { + NET_DBG("[%p] Cannot close (%d)", obj, ret); - errno = -ret; - return -1; + errno = -ret; + return -1; + } + + ret = 0; } return ret; From be618af7052dabe4904522551b061482318487db Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0585/1389] net: websocket: Add a way to unregister a websocket connection Doing a normal close for a websocket does not close the underlying real socket. If we do not have fd for the real socket, then it is not possible to fully close a websocket connection. As we are allocating a websocket using websocket_register() in HTTP server use case, create a websocket_unregister() that will close both the real socket and the websocket socket. Signed-off-by: Jukka Rissanen --- include/zephyr/net/websocket.h | 11 ++++++ subsys/net/lib/websocket/websocket.c | 52 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/include/zephyr/net/websocket.h b/include/zephyr/net/websocket.h index dc0eaf36d185e1..606957e9fd57af 100644 --- a/include/zephyr/net/websocket.h +++ b/include/zephyr/net/websocket.h @@ -201,6 +201,17 @@ int websocket_disconnect(int ws_sock); */ int websocket_register(int http_sock, uint8_t *recv_buf, size_t recv_buf_len); +/** + * @brief Unregister a websocket. This is called when we no longer need + * the underlaying "real" socket. This will close first the websocket + * and then the original socket. + * + * @param ws_sock Websocket connection socket. + * + * @return <0 if error, 0 the websocket connection is now fully closed + */ +int websocket_unregister(int ws_sock); + #if defined(CONFIG_WEBSOCKET_CLIENT) void websocket_init(void); #else diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index d8c719483ac328..c7b896ecb8a68d 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -1193,6 +1193,58 @@ int websocket_register(int sock, uint8_t *recv_buf, size_t recv_buf_len) return ret; } +static struct websocket_context *websocket_search(int sock) +{ + struct websocket_context *ctx = NULL; + int i; + + k_sem_take(&contexts_lock, K_FOREVER); + + for (i = 0; i < ARRAY_SIZE(contexts); i++) { + if (!websocket_context_is_used(&contexts[i])) { + continue; + } + + if (contexts[i].sock != sock) { + continue; + } + + ctx = &contexts[i]; + break; + } + + k_sem_give(&contexts_lock); + + return ctx; +} + +int websocket_unregister(int sock) +{ + struct websocket_context *ctx; + + if (sock < 0) { + return -EINVAL; + } + + ctx = websocket_search(sock); + if (ctx == NULL) { + NET_DBG("[%p] Real socket for websocket sock %d not found!", ctx, sock); + return -ENOENT; + } + + if (ctx->real_sock < 0) { + return -EALREADY; + } + + (void)zsock_close(sock); + (void)zsock_close(ctx->real_sock); + + ctx->real_sock = -1; + ctx->sock = -1; + + return 0; +} + static const struct socket_op_vtable websocket_fd_op_vtable = { .fd_vtable = { .read = websocket_read_vmeth, From d757d346887e09b8d150e433f8567a6a370c0e67 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0586/1389] samples: net: http_server: Close websocket connection properly Use the websocket_unregister() to close both sockets related to a connected websocket. Signed-off-by: Jukka Rissanen --- samples/net/sockets/http_server/src/ws.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/net/sockets/http_server/src/ws.c b/samples/net/sockets/http_server/src/ws.c index 08cdfd1ee29f7c..d62283b5bbc562 100644 --- a/samples/net/sockets/http_server/src/ws.c +++ b/samples/net/sockets/http_server/src/ws.c @@ -12,6 +12,7 @@ #include #include #include +#include #include LOG_MODULE_DECLARE(net_http_server_sample, LOG_LEVEL_DBG); @@ -173,7 +174,7 @@ static void ws_handler(void *ptr1, void *ptr2, void *ptr3) *in_use = false; - (void)close(client); + (void)websocket_unregister(client); cfg->sock = -1; } From 38cc849d257e0d818c278c5d329c16cd2275e185 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0587/1389] sys: time_units: move warning to doxygen command Move the warning about code being autogenerated into the doxygen comment instead of being added as a separate comment that then appears in the `@return` text. Signed-off-by: Jordan Yates --- include/zephyr/sys/time_units.h | 266 +++++++++++++++++++++----------- 1 file changed, 175 insertions(+), 91 deletions(-) diff --git a/include/zephyr/sys/time_units.h b/include/zephyr/sys/time_units.h index 796be1d43a2141..caff1c1fa64787 100644 --- a/include/zephyr/sys/time_units.h +++ b/include/zephyr/sys/time_units.h @@ -278,8 +278,8 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * "cyc" => "hardware cycles", * "ticks" => "ticks"); * my %human_round = ("ceil" => "Rounds up", - * "near" => "Round nearest", - * "floor" => "Truncates"); + * "near" => "Round nearest", + * "floor" => "Truncates"); * * sub big { return $_[0] eq "us" || $_[0] eq "ns"; } * sub prefix { return $_[0] eq "ms" || $_[0] eq "us" || $_[0] eq "ns"; } @@ -301,7 +301,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * * my $hfrom = $human{$from_unit}; * my $hto = $human{$to_unit}; - * my $hround = $human_round{$round}; + * my $hround = $human_round{$round}; * print "/", "** \@brief Convert $hfrom to $hto. $ret32 bits. $hround.\n"; * print " *\n"; * print " * Converts time values in $hfrom to $hto.\n"; @@ -314,12 +314,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * print " * Truncates to the next lowest output unit.\n"; * } * print " *\n"; - * print " * \@param t Source time in $hfrom. uint64_t\n"; - * print " *\n"; + * print " * \@warning Generated. Do not edit. See above.\n"; + * print " *\n"; + * print " * \@param t Source time in $hfrom. uint64_t\n"; + * print " *\n"; * print " * \@return The converted time value in $hto. $type\n"; * print " *", "/\n"; - * - * print "/", "* Generated. Do not edit. See above. *", "/\n"; * print "#define $sym(t) \\\n"; * print "\tz_tmcvt_$ret32(t, Z_HZ_$from_unit, Z_HZ_$to_unit,"; * print " $const_hz, $rup, $roff)\n"; @@ -346,11 +346,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false) @@ -361,11 +362,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false) @@ -376,11 +378,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true) @@ -391,11 +394,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true) @@ -406,11 +410,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false) @@ -421,11 +426,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false) @@ -436,11 +442,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, false, false) @@ -451,11 +458,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, false, false) @@ -466,11 +474,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, false, true) @@ -481,11 +490,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, false, true) @@ -496,11 +506,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, true, false) @@ -511,11 +522,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, true, false) @@ -526,11 +538,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false) @@ -541,11 +554,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false) @@ -556,11 +570,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true) @@ -571,11 +586,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true) @@ -586,11 +602,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false) @@ -601,11 +618,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false) @@ -616,11 +634,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, false, false) @@ -631,11 +650,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, false, false) @@ -646,11 +666,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, false, true) @@ -661,11 +682,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, false, true) @@ -676,11 +698,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, true, false) @@ -691,11 +714,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, true, false) @@ -706,11 +730,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false) @@ -721,11 +746,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false) @@ -736,11 +762,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true) @@ -751,11 +778,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true) @@ -766,11 +794,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false) @@ -781,11 +810,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false) @@ -796,11 +826,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, false, false) @@ -811,11 +842,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, false, false) @@ -826,11 +858,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, false, true) @@ -841,11 +874,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, false, true) @@ -856,11 +890,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) @@ -871,11 +906,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) @@ -886,11 +922,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false) @@ -901,11 +938,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false) @@ -916,11 +954,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true) @@ -931,11 +970,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true) @@ -946,11 +986,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false) @@ -961,11 +1002,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false) @@ -976,11 +1018,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false) @@ -991,11 +1034,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false) @@ -1006,11 +1050,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true) @@ -1021,11 +1066,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true) @@ -1036,11 +1082,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false) @@ -1051,11 +1098,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false) @@ -1066,11 +1114,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false) @@ -1081,11 +1130,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false) @@ -1096,11 +1146,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true) @@ -1111,11 +1162,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true) @@ -1126,11 +1178,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false) @@ -1141,11 +1194,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false) @@ -1156,11 +1210,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false) @@ -1171,11 +1226,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false) @@ -1186,11 +1242,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true) @@ -1201,11 +1258,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true) @@ -1216,11 +1274,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) @@ -1231,11 +1290,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) @@ -1246,11 +1306,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, false, false) @@ -1261,11 +1322,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, false, false) @@ -1276,11 +1338,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, false, true) @@ -1291,11 +1354,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, false, true) @@ -1306,11 +1370,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, true, false) @@ -1321,11 +1386,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, true, false) @@ -1336,11 +1402,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, false, false) @@ -1351,11 +1418,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, false, false) @@ -1366,11 +1434,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, false, true) @@ -1381,11 +1450,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, false, true) @@ -1396,11 +1466,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, true, false) @@ -1411,11 +1482,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, true, false) @@ -1426,11 +1498,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, false, false) @@ -1441,11 +1514,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, false, false) @@ -1456,11 +1530,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, false, true) @@ -1471,11 +1546,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, false, true) @@ -1486,11 +1562,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, true, false) @@ -1501,11 +1578,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, true, false) @@ -1516,11 +1594,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false) @@ -1531,11 +1610,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false) @@ -1546,11 +1626,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true) @@ -1561,11 +1642,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true) @@ -1576,11 +1658,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) @@ -1591,11 +1674,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) From e754be9d978fc0befac3fa50ea454fa6c0246ae7 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0588/1389] sys: time_units: add seconds conversions Add conversions between the existing time units and seconds. Signed-off-by: Jordan Yates --- include/zephyr/sys/time_units.h | 394 +++++++++++++++++++++++++++++++- 1 file changed, 390 insertions(+), 4 deletions(-) diff --git a/include/zephyr/sys/time_units.h b/include/zephyr/sys/time_units.h index caff1c1fa64787..e088099ef91375 100644 --- a/include/zephyr/sys/time_units.h +++ b/include/zephyr/sys/time_units.h @@ -272,7 +272,8 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * #!/usr/bin/perl -w * use strict; * - * my %human = ("ms" => "milliseconds", + * my %human = ("sec" => "seconds", + * "ms" => "milliseconds", * "us" => "microseconds", * "ns" => "nanoseconds", * "cyc" => "hardware cycles", @@ -282,10 +283,10 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * "floor" => "Truncates"); * * sub big { return $_[0] eq "us" || $_[0] eq "ns"; } - * sub prefix { return $_[0] eq "ms" || $_[0] eq "us" || $_[0] eq "ns"; } + * sub prefix { return $_[0] eq "sec" || $_[0] eq "ms" || $_[0] eq "us" || $_[0] eq "ns"; } * - * for my $from_unit ("ms", "us", "ns", "cyc", "ticks") { - * for my $to_unit ("ms", "us", "ns", "cyc", "ticks") { + * for my $from_unit ("sec", "ms", "us", "ns", "cyc", "ticks") { + * for my $to_unit ("sec", "ms", "us", "ns", "cyc", "ticks") { * next if $from_unit eq $to_unit; * next if prefix($from_unit) && prefix($to_unit); * for my $round ("floor", "near", "ceil") { @@ -333,6 +334,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) /* Some more concise declarations to simplify the generator script and * save bytes below */ +#define Z_HZ_sec 1 #define Z_HZ_ms 1000 #define Z_HZ_us 1000000 #define Z_HZ_ns 1000000000 @@ -340,6 +342,198 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) #define Z_HZ_ticks CONFIG_SYS_CLOCK_TICKS_PER_SEC #define Z_CCYC (!IS_ENABLED(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)) +/** @brief Convert seconds to hardware cycles. 32 bits. Truncates. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t + */ +#define k_sec_to_cyc_floor32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, false) + + +/** @brief Convert seconds to hardware cycles. 64 bits. Truncates. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t + */ +#define k_sec_to_cyc_floor64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, false) + + +/** @brief Convert seconds to hardware cycles. 32 bits. Round nearest. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t + */ +#define k_sec_to_cyc_near32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, true) + + +/** @brief Convert seconds to hardware cycles. 64 bits. Round nearest. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t + */ +#define k_sec_to_cyc_near64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, true) + + +/** @brief Convert seconds to hardware cycles. 32 bits. Rounds up. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t + */ +#define k_sec_to_cyc_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, true, false) + + +/** @brief Convert seconds to hardware cycles. 64 bits. Rounds up. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t + */ +#define k_sec_to_cyc_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, true, false) + + +/** @brief Convert seconds to ticks. 32 bits. Truncates. + * + * Converts time values in seconds to ticks. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint32_t + */ +#define k_sec_to_ticks_floor32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_ticks, true, false, false) + + +/** @brief Convert seconds to ticks. 64 bits. Truncates. + * + * Converts time values in seconds to ticks. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint64_t + */ +#define k_sec_to_ticks_floor64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_ticks, true, false, false) + + +/** @brief Convert seconds to ticks. 32 bits. Round nearest. + * + * Converts time values in seconds to ticks. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint32_t + */ +#define k_sec_to_ticks_near32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_ticks, true, false, true) + + +/** @brief Convert seconds to ticks. 64 bits. Round nearest. + * + * Converts time values in seconds to ticks. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint64_t + */ +#define k_sec_to_ticks_near64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_ticks, true, false, true) + + +/** @brief Convert seconds to ticks. 32 bits. Rounds up. + * + * Converts time values in seconds to ticks. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint32_t + */ +#define k_sec_to_ticks_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_ticks, true, true, false) + + +/** @brief Convert seconds to ticks. 64 bits. Rounds up. + * + * Converts time values in seconds to ticks. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint64_t + */ +#define k_sec_to_ticks_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_ticks, true, true, false) + + /** @brief Convert milliseconds to hardware cycles. 32 bits. Truncates. * * Converts time values in milliseconds to hardware cycles. @@ -916,6 +1110,102 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) +/** @brief Convert hardware cycles to seconds. 32 bits. Truncates. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_cyc_to_sec_floor32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, false) + + +/** @brief Convert hardware cycles to seconds. 64 bits. Truncates. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_cyc_to_sec_floor64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, false) + + +/** @brief Convert hardware cycles to seconds. 32 bits. Round nearest. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_cyc_to_sec_near32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, true) + + +/** @brief Convert hardware cycles to seconds. 64 bits. Round nearest. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_cyc_to_sec_near64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, true) + + +/** @brief Convert hardware cycles to seconds. 32 bits. Rounds up. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_cyc_to_sec_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, true, false) + + +/** @brief Convert hardware cycles to seconds. 64 bits. Rounds up. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_cyc_to_sec_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, true, false) + + /** @brief Convert hardware cycles to milliseconds. 32 bits. Truncates. * * Converts time values in hardware cycles to milliseconds. @@ -1300,6 +1590,102 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) +/** @brief Convert ticks to seconds. 32 bits. Truncates. + * + * Converts time values in ticks to seconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_ticks_to_sec_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_sec, true, false, false) + + +/** @brief Convert ticks to seconds. 64 bits. Truncates. + * + * Converts time values in ticks to seconds. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_ticks_to_sec_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_sec, true, false, false) + + +/** @brief Convert ticks to seconds. 32 bits. Round nearest. + * + * Converts time values in ticks to seconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_ticks_to_sec_near32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_sec, true, false, true) + + +/** @brief Convert ticks to seconds. 64 bits. Round nearest. + * + * Converts time values in ticks to seconds. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_ticks_to_sec_near64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_sec, true, false, true) + + +/** @brief Convert ticks to seconds. 32 bits. Rounds up. + * + * Converts time values in ticks to seconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_ticks_to_sec_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_sec, true, true, false) + + +/** @brief Convert ticks to seconds. 64 bits. Rounds up. + * + * Converts time values in ticks to seconds. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_ticks_to_sec_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_sec, true, true, false) + + /** @brief Convert ticks to milliseconds. 32 bits. Truncates. * * Converts time values in ticks to milliseconds. From d2651a8d5e3990295149e7333b5ed32722511ed4 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0589/1389] kernel: add `k_uptime_seconds` Add a helper function for retrieving the system uptime in seconds without having to do a second division. Signed-off-by: Jordan Yates --- doc/releases/release-notes-3.7.rst | 5 +++++ include/zephyr/kernel.h | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 0851c52b7cec17..c778f96d479862 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -71,6 +71,11 @@ Architectures * Xtensa +Kernel +****** + + * Added :c:func:`k_uptime_seconds` function to simplify `k_uptime_get() / 1000` usage. + Bluetooth ********* diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 71277e0b864215..32c554c159da62 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -1774,6 +1774,19 @@ static inline uint32_t k_uptime_get_32(void) return (uint32_t)k_uptime_get(); } +/** + * @brief Get system uptime in seconds. + * + * This routine returns the elapsed time since the system booted, + * in seconds. + * + * @return Current uptime in seconds. + */ +static inline uint32_t k_uptime_seconds(void) +{ + return k_ticks_to_sec_floor32(k_uptime_ticks()); +} + /** * @brief Get elapsed time. * From 3a25adf8cb34638bb831b9adea3603b17a429154 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0590/1389] convert: use `k_uptime_seconds` Replace usage of `k_uptime_get() / MSEC_PER_SEC` and `k_uptime_get() / 1000` with dedicated function. Signed-off-by: Jordan Yates --- samples/basic/hash_map/src/main.c | 6 +++--- subsys/lorawan/services/clock_sync.c | 4 ++-- subsys/net/ip/ipv6_pe.c | 8 +++----- subsys/net/lib/lwm2m/ipso_light_control.c | 6 ++---- subsys/net/lib/lwm2m/lwm2m_obj_device.c | 6 +++--- tests/subsys/lorawan/clock_sync/src/main.c | 4 ++-- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/samples/basic/hash_map/src/main.c b/samples/basic/hash_map/src/main.c index 3c91928396397a..b0861bcbb2e696 100644 --- a/samples/basic/hash_map/src/main.c +++ b/samples/basic/hash_map/src/main.c @@ -47,7 +47,7 @@ int main(void) LOG_DBG("Inserted %zu", i); - if (k_uptime_get() / MSEC_PER_SEC > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { + if (k_uptime_seconds() > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { goto out; } } @@ -60,7 +60,7 @@ int main(void) LOG_DBG("Replaced %zu", i); - if (k_uptime_get() / MSEC_PER_SEC > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { + if (k_uptime_seconds() > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { goto out; } } @@ -72,7 +72,7 @@ int main(void) LOG_DBG("Removed %zu", i - 1); - if (k_uptime_get() / MSEC_PER_SEC > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { + if (k_uptime_seconds() > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { goto out; } } diff --git a/subsys/lorawan/services/clock_sync.c b/subsys/lorawan/services/clock_sync.c index a4532fdee14fe3..c736a396deeedd 100644 --- a/subsys/lorawan/services/clock_sync.c +++ b/subsys/lorawan/services/clock_sync.c @@ -71,7 +71,7 @@ static struct clock_sync_context ctx; */ static int clock_sync_serialize_device_time(uint8_t *buf, size_t size) { - uint32_t device_time = k_uptime_get() / MSEC_PER_SEC + ctx.time_offset; + uint32_t device_time = k_uptime_seconds() + ctx.time_offset; if (size < sizeof(uint32_t)) { return -ENOSPC; @@ -221,7 +221,7 @@ int lorawan_clock_sync_get(uint32_t *gps_time) __ASSERT(gps_time != NULL, "gps_time parameter is required"); if (ctx.synchronized) { - *gps_time = (uint32_t)(k_uptime_get() / MSEC_PER_SEC + ctx.time_offset); + *gps_time = k_uptime_seconds() + ctx.time_offset; return 0; } else { return -EAGAIN; diff --git a/subsys/net/ip/ipv6_pe.c b/subsys/net/ip/ipv6_pe.c index 9aef57181678ce..e31eaa3bae1fe1 100644 --- a/subsys/net/ip/ipv6_pe.c +++ b/subsys/net/ip/ipv6_pe.c @@ -193,8 +193,7 @@ static bool ipv6_pe_prefix_update_lifetimes(struct net_if_ipv6 *ipv6, continue; } - addr_age = (uint32_t)(k_uptime_get() / 1000UL) - - ipv6->unicast[i].addr_create_time; + addr_age = k_uptime_seconds() - ipv6->unicast[i].addr_create_time; new_age = abs(addr_age) + vlifetime; if ((new_age >= TEMP_VALID_LIFETIME) || @@ -382,7 +381,7 @@ void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix, ifaddr->is_temporary = true; ifaddr->addr_preferred_lifetime = preferred_lifetime; ifaddr->addr_timeout = ifaddr->addr_preferred_lifetime - DESYNC_FACTOR(ipv6); - ifaddr->addr_create_time = (uint32_t)(k_uptime_get() / 1000UL); + ifaddr->addr_create_time = k_uptime_seconds(); NET_DBG("Lifetime %d desync %d timeout %d preferred %d valid %d", lifetime, DESYNC_FACTOR(ipv6), ifaddr->addr_timeout, @@ -674,8 +673,7 @@ static void renewal_cb(struct net_if *iface, void *user_data) /* If the address is too old, then generate a new one * and remove the old address. */ - diff = (int32_t)(ipv6->unicast[i].addr_create_time - - ((uint32_t)(k_uptime_get() / 1000UL))); + diff = (int32_t)(ipv6->unicast[i].addr_create_time - k_uptime_seconds()); diff = abs(diff); if (diff < (ipv6->unicast[i].addr_preferred_lifetime - diff --git a/subsys/net/lib/lwm2m/ipso_light_control.c b/subsys/net/lib/lwm2m/ipso_light_control.c index b7f727ff4a4495..55b9f7728cabd7 100644 --- a/subsys/net/lib/lwm2m/ipso_light_control.c +++ b/subsys/net/lib/lwm2m/ipso_light_control.c @@ -78,8 +78,7 @@ static void *on_time_read_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res } if (on_off_value[i]) { - on_time_value[i] = (k_uptime_get() / MSEC_PER_SEC) - - on_time_offset[i]; + on_time_value[i] = k_uptime_seconds() - on_time_offset[i]; } *data_len = sizeof(on_time_value[i]); @@ -109,8 +108,7 @@ static int on_time_post_write_cb(uint16_t obj_inst_id, } if (counter == 0) { - on_time_offset[i] = - (int32_t)(k_uptime_get() / MSEC_PER_SEC); + on_time_offset[i] = k_uptime_seconds(); } return 0; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_device.c b/subsys/net/lib/lwm2m/lwm2m_obj_device.c index 30b3beaca66319..cdebef24532b9d 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_device.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_device.c @@ -176,7 +176,7 @@ static int reset_error_list_cb(uint16_t obj_inst_id, static void *current_time_read_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, size_t *data_len) { - time_temp = time_offset + (k_uptime_get() / 1000); + time_temp = time_offset + k_uptime_seconds(); *data_len = sizeof(time_temp); return &time_temp; @@ -195,10 +195,10 @@ static int current_time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, bool last_block, size_t total_size) { if (data_len == 4U) { - time_offset = *(uint32_t *)data - (uint32_t)(k_uptime_get() / 1000); + time_offset = *(uint32_t *)data - k_uptime_seconds(); return 0; } else if (data_len == 8U) { - time_offset = *(time_t *)data - (time_t)(k_uptime_get() / 1000); + time_offset = *(time_t *)data - (time_t)k_uptime_seconds(); return 0; } diff --git a/tests/subsys/lorawan/clock_sync/src/main.c b/tests/subsys/lorawan/clock_sync/src/main.c index f1557c9fcbae39..3534a0dec6b5f6 100644 --- a/tests/subsys/lorawan/clock_sync/src/main.c +++ b/tests/subsys/lorawan/clock_sync/src/main.c @@ -81,7 +81,7 @@ ZTEST(clock_sync, test_app_time) device_time = sys_get_le32(req.data + 1); token_req = req.data[5] & 0xF; - zassert_within((int)device_time, (int)(k_uptime_get() / 1000), 1); + zassert_within((int)device_time, k_uptime_seconds(), 1); /* apply a time correction of 1000 seconds */ sys_put_le32(1000, ans_data + 1); @@ -90,7 +90,7 @@ ZTEST(clock_sync, test_app_time) lorawan_emul_send_downlink(CLOCK_SYNC_PORT, false, 0, 0, sizeof(ans_data), ans_data); lorawan_clock_sync_get(&gps_time); - zassert_within(gps_time, (k_uptime_get() / 1000) + 1000, 1); + zassert_within(gps_time, k_uptime_seconds() + 1000, 1); } ZTEST(clock_sync, test_device_app_time_periodicity) From 3efec96050a4751359bce69842dbd01179d985e7 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0591/1389] tests: drivers: dma: loop transfer: Avoid fake pass When the needed functionality is not available, its test should be skipped, not passed. Signed-off-by: Reto Schneider --- tests/drivers/dma/loop_transfer/src/test_dma_loop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/drivers/dma/loop_transfer/src/test_dma_loop.c b/tests/drivers/dma/loop_transfer/src/test_dma_loop.c index 31cd058f60fbf8..429c41f1e58a55 100644 --- a/tests/drivers/dma/loop_transfer/src/test_dma_loop.c +++ b/tests/drivers/dma/loop_transfer/src/test_dma_loop.c @@ -252,7 +252,8 @@ static int test_loop_suspend_resume(const struct device *dma) done = 1; TC_PRINT("suspend not supported\n"); dma_stop(dma, chan_id); - return TC_PASS; + ztest_test_skip(); + return TC_SKIP; } tc = transfer_count; irq_unlock(irq_key); From baf9a2cdef909eeb053e46a0399724876b28bc04 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0592/1389] arch: riscv: apply CONFIG_RISCV_MCAUSE_EXCEPTION_MASK to FPU code Some implementations use bits outside of the mcause mask for other purpose. Signed-off-by: Nicolas Pitre --- arch/riscv/core/isr.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index 2a8ed28deae760..e9a3d523127a42 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -203,6 +203,8 @@ SECTION_FUNC(exception.entry, _isr_wrapper) bnez t1, no_fp /* determine if this is an Illegal Instruction exception */ csrr t2, mcause + li t1, CONFIG_RISCV_MCAUSE_EXCEPTION_MASK + and t2, t2, t1 li t1, 2 /* 2 = illegal instruction */ bne t1, t2, no_fp /* determine if we trapped on an FP instruction. */ From e3cd7c5e3be908f4b2c5f2faad4851a24412dbdb Mon Sep 17 00:00:00 2001 From: Samuel Kleiser Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0593/1389] stm32: ospi: make all clk, dqs, ncs pins configurable The clk, dqs and ncs pins can be remapped between OSPI instances, but the driver doesn't support it, yet. Therefore replace hard coded numbers to device tree optional properties. Signed-off-by: Samuel Kleiser --- drivers/flash/flash_stm32_ospi.c | 15 ++++++---- dts/bindings/ospi/st,stm32-ospi.yaml | 45 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index fa9df2937e7b7f..e2a22fba6cf6ed 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -36,6 +36,9 @@ LOG_MODULE_REGISTER(flash_stm32_ospi, CONFIG_FLASH_LOG_LEVEL); (_CONCAT(HAL_OSPIM_, DT_STRING_TOKEN(STM32_OSPI_NODE, prop))), \ ((default_value))) +#define DT_OSPI_PROP_OR(prop, default_value) \ + DT_PROP_OR(STM32_OSPI_NODE, prop, default_value) + /* Get the base address of the flash from the DTS node */ #define STM32_OSPI_BASE_ADDRESS DT_INST_REG_ADDR(0) @@ -2094,17 +2097,17 @@ static int flash_stm32_ospi_init(const struct device *dev) OSPIM_CfgTypeDef ospi_mgr_cfg = {0}; if (dev_data->hospi.Instance == OCTOSPI1) { - ospi_mgr_cfg.ClkPort = 1; - ospi_mgr_cfg.DQSPort = 1; - ospi_mgr_cfg.NCSPort = 1; + ospi_mgr_cfg.ClkPort = DT_OSPI_PROP_OR(clk_port, 1); + ospi_mgr_cfg.DQSPort = DT_OSPI_PROP_OR(dqs_port, 1); + ospi_mgr_cfg.NCSPort = DT_OSPI_PROP_OR(ncs_port, 1); ospi_mgr_cfg.IOLowPort = DT_OSPI_IO_PORT_PROP_OR(io_low_port, HAL_OSPIM_IOPORT_1_LOW); ospi_mgr_cfg.IOHighPort = DT_OSPI_IO_PORT_PROP_OR(io_high_port, HAL_OSPIM_IOPORT_1_HIGH); } else if (dev_data->hospi.Instance == OCTOSPI2) { - ospi_mgr_cfg.ClkPort = 2; - ospi_mgr_cfg.DQSPort = 2; - ospi_mgr_cfg.NCSPort = 2; + ospi_mgr_cfg.ClkPort = DT_OSPI_PROP_OR(clk_port, 2); + ospi_mgr_cfg.DQSPort = DT_OSPI_PROP_OR(dqs_port, 2); + ospi_mgr_cfg.NCSPort = DT_OSPI_PROP_OR(ncs_port, 2); ospi_mgr_cfg.IOLowPort = DT_OSPI_IO_PORT_PROP_OR(io_low_port, HAL_OSPIM_IOPORT_2_LOW); ospi_mgr_cfg.IOHighPort = DT_OSPI_IO_PORT_PROP_OR(io_high_port, diff --git a/dts/bindings/ospi/st,stm32-ospi.yaml b/dts/bindings/ospi/st,stm32-ospi.yaml index aaac4141455f09..b1666d67d91eca 100644 --- a/dts/bindings/ospi/st,stm32-ospi.yaml +++ b/dts/bindings/ospi/st,stm32-ospi.yaml @@ -119,3 +119,48 @@ properties: Note: You might need to enable the OCTOSPI I/O manager clock to use the property. Please refer to Reference Manual. The clock can be enabled in the devicetree. + + clk-port: + type: int + enum: + - 1 + - 2 + description: | + Specifies which port of the OCTOSPI IO Manager is used for the clk pin. + + If absent, then n is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. + + dqs-port: + type: int + enum: + - 1 + - 2 + description: | + Specifies which port of the OCTOSPI IO Manager is used for the dqs pin. + + If absent, then n is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. + + ncs-port: + type: int + enum: + - 1 + - 2 + description: | + Specifies which port of the OCTOSPI IO Manager is used for the ncs pin. + + If absent, then n is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. From 1e5cf03edf34f6e1d6f098643359d0b89037dc56 Mon Sep 17 00:00:00 2001 From: Troels Nilsson Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0594/1389] Bluetooth: Controller: Fix BIS IRC range check Maximum possible value for IRC is 15, not 7 Signed-off-by: Troels Nilsson --- subsys/bluetooth/controller/ll_sw/ull_adv_iso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index 2ca53aaf4c9d37..4c5265b799cffd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -192,7 +192,7 @@ static uint8_t big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bi return BT_HCI_ERR_INVALID_PARAM; } - if (!IN_RANGE(irc, 0x01, 0x07)) { + if (!IN_RANGE(irc, 0x01, 0x0F)) { return BT_HCI_ERR_INVALID_PARAM; } From 4c24eab97d4e220fa2a3c41a28eda88b79d26cbb Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0595/1389] dts: bindings: led_strip: Add common binding Adds a common binding with a chain length and colour ordering property Signed-off-by: Jamie McCrae --- dts/bindings/led_strip/led-strip.yaml | 24 ++++++++++++++++++++++++ dts/bindings/led_strip/ti,tlc5971.yaml | 24 +++--------------------- dts/bindings/led_strip/ws2812.yaml | 20 ++------------------ 3 files changed, 29 insertions(+), 39 deletions(-) create mode 100644 dts/bindings/led_strip/led-strip.yaml diff --git a/dts/bindings/led_strip/led-strip.yaml b/dts/bindings/led_strip/led-strip.yaml new file mode 100644 index 00000000000000..f8ffb62e683149 --- /dev/null +++ b/dts/bindings/led_strip/led-strip.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2019, Linaro Limited +# Copyright (c) 2019, Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Common fields for LED strips + +properties: + chain-length: + type: int + required: true + description: | + The number of devices in the daisy-chain. + + color-mapping: + type: array + required: true + description: | + Channel to color mapping (or pixel order). + + For example a GRB channel to color mapping would be + + color-mapping = ; diff --git a/dts/bindings/led_strip/ti,tlc5971.yaml b/dts/bindings/led_strip/ti,tlc5971.yaml index 2da4f234e64fac..de66dd7d2af288 100644 --- a/dts/bindings/led_strip/ti,tlc5971.yaml +++ b/dts/bindings/led_strip/ti,tlc5971.yaml @@ -6,7 +6,8 @@ description: | Driver bindings for daisy chains of a TLC5971 devices using a single device tree node. Length of daisy chains in pixels is defined by the chain-length - property. + property. Note: chain-length must be a multiple of 4. A single TLC5971 device + supports 4 RGB LEDs. The color order of the TLC5971 is BGR. Applications can provide custom mappings using the color-mapping property. @@ -28,23 +29,4 @@ description: | compatible: "ti,tlc5971" -include: spi-device.yaml - -properties: - chain-length: - type: int - required: true - description: | - The number of RGB LEDs in the daisy-chain. - Must be multiple of 4. A single TLC5971 device supports 4 RGB LEDs. - - color-mapping: - type: array - required: true - description: | - Channel to color mapping (or pixel order). - For example a BGR channel to color mapping would be - - color-mapping = ; +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/ws2812.yaml b/dts/bindings/led_strip/ws2812.yaml index ff594a862cd643..6b8e59b7e9e7e9 100644 --- a/dts/bindings/led_strip/ws2812.yaml +++ b/dts/bindings/led_strip/ws2812.yaml @@ -34,25 +34,9 @@ description: | property. The pixel order depends on the model and it can be configured using the color-mapping property. -properties: - chain-length: - type: int - required: true - description: | - The number of devices in the daisy-chain. - - color-mapping: - type: array - required: true - description: | - Channel to color mapping (or pixel order). - - For example a GRB channel to color mapping would be - - color-mapping = ; +include: led-strip.yaml +properties: reset-delay: type: int default: 8 From 97cf07b9b5ece5b2283515f673d6331e156716f5 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0596/1389] boards: Add chain length and colour mapping to LED strips Adds chain length and colour mapping properties to LED strip devices on boards where these parameters are now required Signed-off-by: Jamie McCrae --- boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts | 5 +++++ boards/adafruit/trinket_m0/adafruit_trinket_m0.dts | 5 +++++ .../plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts | 5 +++++ .../drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay | 6 ++++++ samples/drivers/led_strip/boards/nucleo_l432kc.overlay | 6 ++++++ tests/drivers/build_all/display/app.overlay | 6 ++++++ 6 files changed, 33 insertions(+) diff --git a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts index 56a31b13106947..45827a7bcec827 100644 --- a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts +++ b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts @@ -8,6 +8,7 @@ #include #include "adafruit_itsybitsy_nrf52840-pinctrl.dtsi" #include +#include / { model = "Adafruit ItsyBitsy nRF52840 Express"; @@ -107,6 +108,10 @@ compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <5250000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts b/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts index b94b0e1ed73698..21fc54fb9e9a04 100644 --- a/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts +++ b/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts @@ -8,6 +8,7 @@ #include #include #include "adafruit_trinket_m0-pinctrl.dtsi" +#include / { model = "Adafruit Trinket M0"; @@ -87,6 +88,10 @@ compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <24000000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts b/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts index 48bcacff102c6c..245b2eb1aad23c 100644 --- a/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts +++ b/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts @@ -8,6 +8,7 @@ #include #include "blueclover_plt_demo_v2_nrf52832-pinctrl.dtsi" #include +#include / { model = "Blue Clover PLT Demo Board V2"; @@ -107,6 +108,10 @@ compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <5250000>; + chain-length = <4>; + color-mapping = ; }; }; diff --git a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay index b4be11a83a9e83..49bee930cca93c 100644 --- a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay +++ b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay @@ -4,12 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &spi2 { lpd8806: lpd8806@0 { compatible = "greeled,lpd8806"; reg = <0>; spi-max-frequency = <2000000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/samples/drivers/led_strip/boards/nucleo_l432kc.overlay b/samples/drivers/led_strip/boards/nucleo_l432kc.overlay index 0a7fce2fe75ed5..383637d77173da 100644 --- a/samples/drivers/led_strip/boards/nucleo_l432kc.overlay +++ b/samples/drivers/led_strip/boards/nucleo_l432kc.overlay @@ -4,12 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &spi1 { apa102: apa102@0 { compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <5250000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index cd6669e4516de1..3f71e34d33b7a8 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -10,6 +10,8 @@ * (and be extended to test) real hardware. */ +#include + / { test { #address-cells = <1>; @@ -83,6 +85,10 @@ compatible = "greeled,lpd8806"; reg = <2>; spi-max-frequency = <2000000>; + chain-length = <1>; + color-mapping = ; }; test_led_strip_1: ws2812_spi@3 { From 6fa059358e43febc78b31fdb61610deff4bf2e07 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0597/1389] drivers: led_strip: Add length function Adds a length function which returns the length of the LED strip Signed-off-by: Jamie McCrae --- drivers/led_strip/apa102.c | 10 +++++++++ drivers/led_strip/lpd880x.c | 12 +++++++++- drivers/led_strip/tlc5971.c | 8 +++++++ drivers/led_strip/ws2812_gpio.c | 10 +++++++++ drivers/led_strip/ws2812_i2s.c | 10 +++++++++ drivers/led_strip/ws2812_rpi_pico_pio.c | 10 +++++++++ drivers/led_strip/ws2812_spi.c | 10 +++++++++ dts/bindings/led_strip/apa,apa102.yaml | 2 +- dts/bindings/led_strip/greeled,lpd8803.yaml | 2 +- dts/bindings/led_strip/greeled,lpd8806.yaml | 2 +- include/zephyr/drivers/led_strip.h | 25 +++++++++++++++++++++ 11 files changed, 97 insertions(+), 4 deletions(-) diff --git a/drivers/led_strip/apa102.c b/drivers/led_strip/apa102.c index cea394d79018be..e6bb90fbb4d5ab 100644 --- a/drivers/led_strip/apa102.c +++ b/drivers/led_strip/apa102.c @@ -14,6 +14,7 @@ struct apa102_config { struct spi_dt_spec bus; + size_t length; }; static int apa102_update(const struct device *dev, void *buf, size_t size) @@ -80,6 +81,13 @@ static int apa102_update_channels(const struct device *dev, uint8_t *channels, return -EINVAL; } +static size_t apa102_length(const struct device *dev) +{ + const struct apa102_config *config = dev->config; + + return config->length; +} + static int apa102_init(const struct device *dev) { const struct apa102_config *config = dev->config; @@ -94,6 +102,7 @@ static int apa102_init(const struct device *dev) static const struct led_strip_driver_api apa102_api = { .update_rgb = apa102_update_rgb, .update_channels = apa102_update_channels, + .length = apa102_length, }; #define APA102_DEVICE(idx) \ @@ -102,6 +111,7 @@ static const struct led_strip_driver_api apa102_api = { idx, \ SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), \ 0), \ + .length = DT_INST_PROP(idx, chain_length), \ }; \ \ DEVICE_DT_INST_DEFINE(idx, \ diff --git a/drivers/led_strip/lpd880x.c b/drivers/led_strip/lpd880x.c index a1fa90e6415c55..991e2e3fb57e9a 100644 --- a/drivers/led_strip/lpd880x.c +++ b/drivers/led_strip/lpd880x.c @@ -36,6 +36,7 @@ LOG_MODULE_REGISTER(lpd880x); struct lpd880x_config { struct spi_dt_spec bus; + size_t length; }; static int lpd880x_update(const struct device *dev, void *data, size_t size) @@ -125,6 +126,13 @@ static int lpd880x_strip_update_channels(const struct device *dev, return lpd880x_update(dev, channels, num_channels); } +static size_t lpd880x_strip_length(const struct device *dev) +{ + const struct lpd880x_config *config = dev->config; + + return config->length; +} + static int lpd880x_strip_init(const struct device *dev) { const struct lpd880x_config *config = dev->config; @@ -138,12 +146,14 @@ static int lpd880x_strip_init(const struct device *dev) } static const struct lpd880x_config lpd880x_config = { - .bus = SPI_DT_SPEC_INST_GET(0, LPD880X_SPI_OPERATION, 0) + .bus = SPI_DT_SPEC_INST_GET(0, LPD880X_SPI_OPERATION, 0), + .length = DT_INST_PROP(0, chain_length), }; static const struct led_strip_driver_api lpd880x_strip_api = { .update_rgb = lpd880x_strip_update_rgb, .update_channels = lpd880x_strip_update_channels, + .length = lpd880x_strip_length, }; DEVICE_DT_INST_DEFINE(0, lpd880x_strip_init, NULL, diff --git a/drivers/led_strip/tlc5971.c b/drivers/led_strip/tlc5971.c index 06d36455d5806c..da6bcddbbb461d 100644 --- a/drivers/led_strip/tlc5971.c +++ b/drivers/led_strip/tlc5971.c @@ -269,6 +269,13 @@ static int tlc5971_update_channels(const struct device *dev, uint8_t *channels, return -ENOTSUP; } +static size_t tlc5971_length(const struct device *dev) +{ + const struct tlc5971_config *cfg = dev->config; + + return (size_t)cfg->num_pixels; +} + int tlc5971_set_global_brightness(const struct device *dev, struct led_rgb pixel) { const struct tlc5971_config *cfg = dev->config; @@ -334,6 +341,7 @@ static int tlc5971_init(const struct device *dev) static const struct led_strip_driver_api tlc5971_api = { .update_rgb = tlc5971_update_rgb, .update_channels = tlc5971_update_channels, + .length = tlc5971_length, }; #define TLC5971_DATA_BUFFER_LENGTH(inst) \ diff --git a/drivers/led_strip/ws2812_gpio.c b/drivers/led_strip/ws2812_gpio.c index bba534f1bbe7b5..f53cbf1b3e23fc 100644 --- a/drivers/led_strip/ws2812_gpio.c +++ b/drivers/led_strip/ws2812_gpio.c @@ -28,6 +28,7 @@ struct ws2812_gpio_cfg { struct gpio_dt_spec gpio; uint8_t num_colors; const uint8_t *color_mapping; + size_t length; }; /* @@ -187,9 +188,17 @@ static int ws2812_gpio_update_channels(const struct device *dev, return -ENOTSUP; } +static size_t ws2812_gpio_length(const struct device *dev) +{ + const struct ws2812_gpio_cfg *config = dev->config; + + return config->length; +} + static const struct led_strip_driver_api ws2812_gpio_api = { .update_rgb = ws2812_gpio_update_rgb, .update_channels = ws2812_gpio_update_channels, + .length = ws2812_gpio_length, }; /* @@ -245,6 +254,7 @@ static const uint8_t ws2812_gpio_##idx##_color_mapping[] = \ .gpio = GPIO_DT_SPEC_INST_GET(idx, gpios), \ .num_colors = WS2812_NUM_COLORS(idx), \ .color_mapping = ws2812_gpio_##idx##_color_mapping, \ + .length = DT_INST_PROP(idx, chain_length), \ }; \ \ DEVICE_DT_INST_DEFINE(idx, \ diff --git a/drivers/led_strip/ws2812_i2s.c b/drivers/led_strip/ws2812_i2s.c index 19baefff8e2bf8..b9346a62b4411a 100644 --- a/drivers/led_strip/ws2812_i2s.c +++ b/drivers/led_strip/ws2812_i2s.c @@ -38,6 +38,7 @@ struct ws2812_i2s_cfg { size_t tx_buf_bytes; struct k_mem_slab *mem_slab; uint8_t num_colors; + size_t length; const uint8_t *color_mapping; uint16_t reset_words; uint32_t lrck_period; @@ -170,6 +171,13 @@ static int ws2812_strip_update_channels(const struct device *dev, uint8_t *chann return -ENOTSUP; } +static size_t ws2812_strip_length(const struct device *dev) +{ + const struct ws2812_i2s_cfg *cfg = dev->config; + + return cfg->length; +} + static int ws2812_i2s_init(const struct device *dev) { const struct ws2812_i2s_cfg *cfg = dev->config; @@ -218,6 +226,7 @@ static int ws2812_i2s_init(const struct device *dev) static const struct led_strip_driver_api ws2812_i2s_api = { .update_rgb = ws2812_strip_update_rgb, .update_channels = ws2812_strip_update_channels, + .length = ws2812_strip_length, }; /* Integer division, but always rounds up: e.g. 10/3 = 4 */ @@ -250,6 +259,7 @@ static const struct led_strip_driver_api ws2812_i2s_api = { .tx_buf_bytes = WS2812_I2S_BUFSIZE(idx), \ .mem_slab = &ws2812_i2s_##idx##_slab, \ .num_colors = WS2812_NUM_COLORS(idx), \ + .length = DT_INST_PROP(idx, chain_length), \ .color_mapping = ws2812_i2s_##idx##_color_mapping, \ .lrck_period = WS2812_I2S_LRCK_PERIOD_US(idx), \ .extra_wait_time_us = DT_INST_PROP(idx, extra_wait_time), \ diff --git a/drivers/led_strip/ws2812_rpi_pico_pio.c b/drivers/led_strip/ws2812_rpi_pico_pio.c index 5da5cc05f592a6..a50a65a7552b7f 100644 --- a/drivers/led_strip/ws2812_rpi_pico_pio.c +++ b/drivers/led_strip/ws2812_rpi_pico_pio.c @@ -24,6 +24,7 @@ struct ws2812_led_strip_config { const struct device *piodev; const uint8_t gpio_pin; uint8_t num_colors; + size_t length; uint32_t frequency; const uint8_t *const color_mapping; uint16_t reset_delay; @@ -115,9 +116,17 @@ static int ws2812_led_strip_update_channels(const struct device *dev, uint8_t *c return -ENOTSUP; } +static size_t ws2812_led_strip_length(const struct device *dev) +{ + const struct ws2812_led_strip_config *config = dev->config; + + return config->length; +} + static const struct led_strip_driver_api ws2812_led_strip_api = { .update_rgb = ws2812_led_strip_update_rgb, .update_channels = ws2812_led_strip_update_channels, + .length = ws2812_led_strip_length, }; /* @@ -190,6 +199,7 @@ static int ws2812_rpi_pico_pio_init(const struct device *dev) .piodev = DEVICE_DT_GET(DT_PARENT(DT_PARENT(node))), \ .gpio_pin = DT_GPIO_PIN_BY_IDX(node, gpios, 0), \ .num_colors = DT_PROP_LEN(node, color_mapping), \ + .length = DT_PROP(node, chain_length), \ .color_mapping = ws2812_led_strip_##node##_color_mapping, \ .reset_delay = DT_PROP(node, reset_delay), \ .frequency = DT_PROP(node, frequency), \ diff --git a/drivers/led_strip/ws2812_spi.c b/drivers/led_strip/ws2812_spi.c index 44cfecebc9ea52..03172a47b8f653 100644 --- a/drivers/led_strip/ws2812_spi.c +++ b/drivers/led_strip/ws2812_spi.c @@ -44,6 +44,7 @@ struct ws2812_spi_cfg { uint8_t zero_frame; uint8_t num_colors; const uint8_t *color_mapping; + size_t length; uint16_t reset_delay; }; @@ -160,6 +161,13 @@ static int ws2812_strip_update_channels(const struct device *dev, return -ENOTSUP; } +static size_t ws2812_strip_length(const struct device *dev) +{ + const struct ws2812_spi_cfg *cfg = dev_cfg(dev); + + return cfg->length; +} + static int ws2812_spi_init(const struct device *dev) { const struct ws2812_spi_cfg *cfg = dev_cfg(dev); @@ -191,6 +199,7 @@ static int ws2812_spi_init(const struct device *dev) static const struct led_strip_driver_api ws2812_spi_api = { .update_rgb = ws2812_strip_update_rgb, .update_channels = ws2812_strip_update_channels, + .length = ws2812_strip_length, }; #define WS2812_SPI_NUM_PIXELS(idx) \ @@ -231,6 +240,7 @@ static const struct led_strip_driver_api ws2812_spi_api = { .zero_frame = WS2812_SPI_ZERO_FRAME(idx), \ .num_colors = WS2812_NUM_COLORS(idx), \ .color_mapping = ws2812_spi_##idx##_color_mapping, \ + .length = DT_INST_PROP(idx, chain_length), \ .reset_delay = WS2812_RESET_DELAY(idx), \ }; \ \ diff --git a/dts/bindings/led_strip/apa,apa102.yaml b/dts/bindings/led_strip/apa,apa102.yaml index 0a6e6a00a0de46..2d3b7b665294ea 100644 --- a/dts/bindings/led_strip/apa,apa102.yaml +++ b/dts/bindings/led_strip/apa,apa102.yaml @@ -2,4 +2,4 @@ description: APA102 SPI LED strip compatible: "apa,apa102" -include: spi-device.yaml +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/greeled,lpd8803.yaml b/dts/bindings/led_strip/greeled,lpd8803.yaml index 6baca4898d68c5..7a7dc8158c279d 100644 --- a/dts/bindings/led_strip/greeled,lpd8803.yaml +++ b/dts/bindings/led_strip/greeled,lpd8803.yaml @@ -5,4 +5,4 @@ description: GreeLed LPD8803 SPI LED strip compatible: "greeled,lpd8803" -include: spi-device.yaml +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/greeled,lpd8806.yaml b/dts/bindings/led_strip/greeled,lpd8806.yaml index 0a0f0e9f6ee74a..971155b210d65a 100644 --- a/dts/bindings/led_strip/greeled,lpd8806.yaml +++ b/dts/bindings/led_strip/greeled,lpd8806.yaml @@ -5,4 +5,4 @@ description: GreeLed LPD8806 SPI LED strip compatible: "greeled,lpd8806" -include: spi-device.yaml +include: [spi-device.yaml, led-strip.yaml] diff --git a/include/zephyr/drivers/led_strip.h b/include/zephyr/drivers/led_strip.h index b9c7a81407baae..328859870d4767 100644 --- a/include/zephyr/drivers/led_strip.h +++ b/include/zephyr/drivers/led_strip.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Linaro Limited + * Copyright (c) 2024 Jamie McCrae * * SPDX-License-Identifier: Apache-2.0 */ @@ -71,6 +72,14 @@ typedef int (*led_api_update_channels)(const struct device *dev, uint8_t *channels, size_t num_channels); +/** + * @typedef led_api_length + * @brief Callback API for getting length of an LED strip. + * + * @see led_strip_length() for argument descriptions. + */ +typedef size_t (*led_api_length)(const struct device *dev); + /** * @brief LED strip driver API * @@ -79,6 +88,7 @@ typedef int (*led_api_update_channels)(const struct device *dev, __subsystem struct led_strip_driver_api { led_api_update_rgb update_rgb; led_api_update_channels update_channels; + led_api_length length; }; /** @@ -131,6 +141,21 @@ static inline int led_strip_update_channels(const struct device *dev, return api->update_channels(dev, channels, num_channels); } +/** + * @brief Mandatory function to get chain length (in pixels) of an LED strip device. + * + * @param dev LED strip device. + * + * @retval Length of LED strip device. + */ +static inline size_t led_strip_length(const struct device *dev) +{ + const struct led_strip_driver_api *api = + (const struct led_strip_driver_api *)dev->api; + + return api->length(dev); +} + #ifdef __cplusplus } #endif From 8a1cc1988a78867150f27df65146d5f3fdde2c96 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0598/1389] drivers: led_strip: Update format Updates the include file to fix some formatting issues Signed-off-by: Jamie McCrae --- include/zephyr/drivers/led_strip.h | 44 ++++++++++++++---------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/include/zephyr/drivers/led_strip.h b/include/zephyr/drivers/led_strip.h index 328859870d4767..e57d8c810081c3 100644 --- a/include/zephyr/drivers/led_strip.h +++ b/include/zephyr/drivers/led_strip.h @@ -92,23 +92,21 @@ __subsystem struct led_strip_driver_api { }; /** - * @brief Update an LED strip made of RGB pixels + * @brief Mandatory function to update an LED strip with the given RGB array. * - * Important: - * This routine may overwrite @a pixels. + * @param dev LED strip device. + * @param pixels Array of pixel data. + * @param num_pixels Length of pixels array. * - * This routine immediately updates the strip display according to the - * given pixels array. + * @retval 0 on success. + * @retval -errno negative errno code on failure. * - * @param dev LED strip device - * @param pixels Array of pixel data - * @param num_pixels Length of pixels array - * @return 0 on success, negative on error - * @warning May overwrite @a pixels + * @warning This routine may overwrite @a pixels. */ static inline int led_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, - size_t num_pixels) { + size_t num_pixels) +{ const struct led_strip_driver_api *api = (const struct led_strip_driver_api *)dev->api; @@ -116,25 +114,23 @@ static inline int led_strip_update_rgb(const struct device *dev, } /** - * @brief Update an LED strip on a per-channel basis. + * @brief Function to update an LED strip with the given channel array + * (each channel byte corresponding to an individually addressable color + * channel or LED. Channels are updated linearly in strip order. * - * Important: - * This routine may overwrite @a channels. + * @param dev LED strip device. + * @param channels Array of per-channel data. + * @param num_channels Length of channels array. * - * This routine immediately updates the strip display according to the - * given channels array. Each channel byte corresponds to an - * individually addressable color channel or LED. Channels - * are updated linearly in strip order. + * @retval 0 on success. + * @retval -errno negative errno code on failure. * - * @param dev LED strip device - * @param channels Array of per-channel data - * @param num_channels Length of channels array - * @return 0 on success, negative on error - * @warning May overwrite @a channels + * @warning This routine may overwrite @a channels. */ static inline int led_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) { + size_t num_channels) +{ const struct led_strip_driver_api *api = (const struct led_strip_driver_api *)dev->api; From aa92ab5d3fa6d1220465e6579c8e61964c20e61e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0599/1389] drivers: led_strip: Check length before updating LED strip Checks that the supplied length is valid for the given driver before passing it to the update function Signed-off-by: Jamie McCrae --- drivers/led_strip/tlc5971.c | 7 ------- drivers/led_strip/ws2812_spi.c | 22 +--------------------- include/zephyr/drivers/led_strip.h | 11 +++++++++++ 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/led_strip/tlc5971.c b/drivers/led_strip/tlc5971.c index da6bcddbbb461d..3a9a787fd70993 100644 --- a/drivers/led_strip/tlc5971.c +++ b/drivers/led_strip/tlc5971.c @@ -248,13 +248,6 @@ static int tlc5971_transmit_data(const struct device *dev, size_t num_pixels) static int tlc5971_update_rgb(const struct device *dev, struct led_rgb *pixels, size_t num_pixels) { - const struct tlc5971_config *cfg = dev->config; - - if (num_pixels > cfg->num_pixels) { - LOG_ERR("invalid number of pixels, %zu vs actual %i", num_pixels, cfg->num_pixels); - return -EINVAL; - } - tlc5971_fill_data_buffer(dev, pixels, num_pixels); return tlc5971_transmit_data(dev, num_pixels); diff --git a/drivers/led_strip/ws2812_spi.c b/drivers/led_strip/ws2812_spi.c index 03172a47b8f653..65dd80a92f67d0 100644 --- a/drivers/led_strip/ws2812_spi.c +++ b/drivers/led_strip/ws2812_spi.c @@ -39,7 +39,6 @@ LOG_MODULE_REGISTER(ws2812_spi); struct ws2812_spi_cfg { struct spi_dt_spec bus; uint8_t *px_buf; - size_t px_buf_size; uint8_t one_frame; uint8_t zero_frame; uint8_t num_colors; @@ -68,20 +67,6 @@ static inline void ws2812_spi_ser(uint8_t buf[8], uint8_t color, } } -/* - * Returns true if and only if cfg->px_buf is big enough to convert - * num_pixels RGB color values into SPI frames. - */ -static inline bool num_pixels_ok(const struct ws2812_spi_cfg *cfg, - size_t num_pixels) -{ - size_t nbytes; - bool overflow; - - overflow = size_mul_overflow(num_pixels, cfg->num_colors * 8, &nbytes); - return !overflow && (nbytes <= cfg->px_buf_size); -} - /* * Latch current color values on strip and reset its state machines. */ @@ -98,7 +83,7 @@ static int ws2812_strip_update_rgb(const struct device *dev, const uint8_t one = cfg->one_frame, zero = cfg->zero_frame; struct spi_buf buf = { .buf = cfg->px_buf, - .len = cfg->px_buf_size, + .len = (cfg->length * 8 * cfg->num_colors), }; const struct spi_buf_set tx = { .buffers = &buf, @@ -108,10 +93,6 @@ static int ws2812_strip_update_rgb(const struct device *dev, size_t i; int rc; - if (!num_pixels_ok(cfg, num_pixels)) { - return -ENOMEM; - } - /* * Convert pixel data into SPI frames. Each frame has pixel data * in color mapping on-wire format (e.g. GRB, GRBW, RGB, etc). @@ -235,7 +216,6 @@ static const struct led_strip_driver_api ws2812_spi_api = { static const struct ws2812_spi_cfg ws2812_spi_##idx##_cfg = { \ .bus = SPI_DT_SPEC_INST_GET(idx, SPI_OPER(idx), 0), \ .px_buf = ws2812_spi_##idx##_px_buf, \ - .px_buf_size = WS2812_SPI_BUFSZ(idx), \ .one_frame = WS2812_SPI_ONE_FRAME(idx), \ .zero_frame = WS2812_SPI_ZERO_FRAME(idx), \ .num_colors = WS2812_NUM_COLORS(idx), \ diff --git a/include/zephyr/drivers/led_strip.h b/include/zephyr/drivers/led_strip.h index e57d8c810081c3..94afae1431ff89 100644 --- a/include/zephyr/drivers/led_strip.h +++ b/include/zephyr/drivers/led_strip.h @@ -23,6 +23,7 @@ * @{ */ +#include #include #include @@ -110,6 +111,16 @@ static inline int led_strip_update_rgb(const struct device *dev, const struct led_strip_driver_api *api = (const struct led_strip_driver_api *)dev->api; + /* Allow for out-of-tree drivers that do not have this function for 2 Zephyr releases + * until making it mandatory, function added after Zephyr 3.6 + */ + if (api->length != NULL) { + /* Ensure supplied pixel size is valid for this device */ + if (api->length(dev) < num_pixels) { + return -ERANGE; + } + } + return api->update_rgb(dev, pixels, num_pixels); } From 55be6b1dd7159672deee80420090d1e40a2b69e2 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0600/1389] drivers: led_strip: Make update channels function optional Makes the update channels function optional, this is only implemented in one driver so can be safely omitted from most drivers Signed-off-by: Jamie McCrae --- drivers/led_strip/apa102.c | 8 -------- drivers/led_strip/tlc5971.c | 10 ---------- drivers/led_strip/ws2812_gpio.c | 9 --------- drivers/led_strip/ws2812_i2s.c | 8 -------- drivers/led_strip/ws2812_rpi_pico_pio.c | 8 -------- drivers/led_strip/ws2812_spi.c | 9 --------- include/zephyr/drivers/led_strip.h | 9 +++++++-- 7 files changed, 7 insertions(+), 54 deletions(-) diff --git a/drivers/led_strip/apa102.c b/drivers/led_strip/apa102.c index e6bb90fbb4d5ab..9f7de642358b7e 100644 --- a/drivers/led_strip/apa102.c +++ b/drivers/led_strip/apa102.c @@ -74,13 +74,6 @@ static int apa102_update_rgb(const struct device *dev, struct led_rgb *pixels, return apa102_update(dev, pixels, sizeof(struct led_rgb) * count); } -static int apa102_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) -{ - /* Not implemented */ - return -EINVAL; -} - static size_t apa102_length(const struct device *dev) { const struct apa102_config *config = dev->config; @@ -101,7 +94,6 @@ static int apa102_init(const struct device *dev) static const struct led_strip_driver_api apa102_api = { .update_rgb = apa102_update_rgb, - .update_channels = apa102_update_channels, .length = apa102_length, }; diff --git a/drivers/led_strip/tlc5971.c b/drivers/led_strip/tlc5971.c index 3a9a787fd70993..ace45414fbf823 100644 --- a/drivers/led_strip/tlc5971.c +++ b/drivers/led_strip/tlc5971.c @@ -253,15 +253,6 @@ static int tlc5971_update_rgb(const struct device *dev, struct led_rgb *pixels, return tlc5971_transmit_data(dev, num_pixels); } -static int tlc5971_update_channels(const struct device *dev, uint8_t *channels, size_t num_channels) -{ - ARG_UNUSED(dev); - ARG_UNUSED(channels); - ARG_UNUSED(num_channels); - - return -ENOTSUP; -} - static size_t tlc5971_length(const struct device *dev) { const struct tlc5971_config *cfg = dev->config; @@ -333,7 +324,6 @@ static int tlc5971_init(const struct device *dev) static const struct led_strip_driver_api tlc5971_api = { .update_rgb = tlc5971_update_rgb, - .update_channels = tlc5971_update_channels, .length = tlc5971_length, }; diff --git a/drivers/led_strip/ws2812_gpio.c b/drivers/led_strip/ws2812_gpio.c index f53cbf1b3e23fc..9c0d47d3afb0d2 100644 --- a/drivers/led_strip/ws2812_gpio.c +++ b/drivers/led_strip/ws2812_gpio.c @@ -180,14 +180,6 @@ static int ws2812_gpio_update_rgb(const struct device *dev, return send_buf(dev, (uint8_t *)pixels, num_pixels * config->num_colors); } -static int ws2812_gpio_update_channels(const struct device *dev, - uint8_t *channels, - size_t num_channels) -{ - LOG_ERR("update_channels not implemented"); - return -ENOTSUP; -} - static size_t ws2812_gpio_length(const struct device *dev) { const struct ws2812_gpio_cfg *config = dev->config; @@ -197,7 +189,6 @@ static size_t ws2812_gpio_length(const struct device *dev) static const struct led_strip_driver_api ws2812_gpio_api = { .update_rgb = ws2812_gpio_update_rgb, - .update_channels = ws2812_gpio_update_channels, .length = ws2812_gpio_length, }; diff --git a/drivers/led_strip/ws2812_i2s.c b/drivers/led_strip/ws2812_i2s.c index b9346a62b4411a..b1b951216282a6 100644 --- a/drivers/led_strip/ws2812_i2s.c +++ b/drivers/led_strip/ws2812_i2s.c @@ -164,13 +164,6 @@ static int ws2812_strip_update_rgb(const struct device *dev, struct led_rgb *pix return ret; } -static int ws2812_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) -{ - LOG_ERR("update_channels not implemented"); - return -ENOTSUP; -} - static size_t ws2812_strip_length(const struct device *dev) { const struct ws2812_i2s_cfg *cfg = dev->config; @@ -225,7 +218,6 @@ static int ws2812_i2s_init(const struct device *dev) static const struct led_strip_driver_api ws2812_i2s_api = { .update_rgb = ws2812_strip_update_rgb, - .update_channels = ws2812_strip_update_channels, .length = ws2812_strip_length, }; diff --git a/drivers/led_strip/ws2812_rpi_pico_pio.c b/drivers/led_strip/ws2812_rpi_pico_pio.c index a50a65a7552b7f..45b19da8f8400f 100644 --- a/drivers/led_strip/ws2812_rpi_pico_pio.c +++ b/drivers/led_strip/ws2812_rpi_pico_pio.c @@ -109,13 +109,6 @@ static int ws2812_led_strip_update_rgb(const struct device *dev, struct led_rgb return 0; } -static int ws2812_led_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) -{ - LOG_DBG("update_channels not implemented"); - return -ENOTSUP; -} - static size_t ws2812_led_strip_length(const struct device *dev) { const struct ws2812_led_strip_config *config = dev->config; @@ -125,7 +118,6 @@ static size_t ws2812_led_strip_length(const struct device *dev) static const struct led_strip_driver_api ws2812_led_strip_api = { .update_rgb = ws2812_led_strip_update_rgb, - .update_channels = ws2812_led_strip_update_channels, .length = ws2812_led_strip_length, }; diff --git a/drivers/led_strip/ws2812_spi.c b/drivers/led_strip/ws2812_spi.c index 65dd80a92f67d0..536da5463c9a0a 100644 --- a/drivers/led_strip/ws2812_spi.c +++ b/drivers/led_strip/ws2812_spi.c @@ -134,14 +134,6 @@ static int ws2812_strip_update_rgb(const struct device *dev, return rc; } -static int ws2812_strip_update_channels(const struct device *dev, - uint8_t *channels, - size_t num_channels) -{ - LOG_ERR("update_channels not implemented"); - return -ENOTSUP; -} - static size_t ws2812_strip_length(const struct device *dev) { const struct ws2812_spi_cfg *cfg = dev_cfg(dev); @@ -179,7 +171,6 @@ static int ws2812_spi_init(const struct device *dev) static const struct led_strip_driver_api ws2812_spi_api = { .update_rgb = ws2812_strip_update_rgb, - .update_channels = ws2812_strip_update_channels, .length = ws2812_strip_length, }; diff --git a/include/zephyr/drivers/led_strip.h b/include/zephyr/drivers/led_strip.h index 94afae1431ff89..7c297cbc6cdc18 100644 --- a/include/zephyr/drivers/led_strip.h +++ b/include/zephyr/drivers/led_strip.h @@ -125,7 +125,7 @@ static inline int led_strip_update_rgb(const struct device *dev, } /** - * @brief Function to update an LED strip with the given channel array + * @brief Optional function to update an LED strip with the given channel array * (each channel byte corresponding to an individually addressable color * channel or LED. Channels are updated linearly in strip order. * @@ -134,7 +134,8 @@ static inline int led_strip_update_rgb(const struct device *dev, * @param num_channels Length of channels array. * * @retval 0 on success. - * @retval -errno negative errno code on failure. + * @retval -ENOSYS if not implemented. + * @retval -errno negative errno code on other failure. * * @warning This routine may overwrite @a channels. */ @@ -145,6 +146,10 @@ static inline int led_strip_update_channels(const struct device *dev, const struct led_strip_driver_api *api = (const struct led_strip_driver_api *)dev->api; + if (api->update_channels == NULL) { + return -ENOSYS; + } + return api->update_channels(dev, channels, num_channels); } From 4e3d11847e69562b0bea4ed77def4673ad0efa8e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:57 +0200 Subject: [PATCH 0601/1389] doc: migration/release: 3.7: Add LED strip changes Adds changes about the LED strip driver Signed-off-by: Jamie McCrae --- doc/releases/migration-guide-3.7.rst | 8 ++++++++ doc/releases/release-notes-3.7.rst | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 73f3e5ccaf809b..19de22a992e8ff 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -252,6 +252,14 @@ LED Strip * The property ``in-gpios`` defined in :dtcompatible:`worldsemi,ws2812-gpio` has been renamed to ``gpios``. (:github:`68514`) +* The ``chain-length`` and ``color-mapping`` properties have been added to all LED strip bindings + and are now mandatory. + +* Added a new mandatory ``length`` function which returns the length (number of pixels) of an LED + strip device. + +* Made ``update_channels`` function optional and removed unimplemented functions. + Sensors ======= diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index c778f96d479862..d73bd134332f32 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -207,6 +207,11 @@ Drivers and Sensors * Input +* LED Strip + + * The ``chain-length`` and ``color-mapping`` properties have been added to all LED strip + bindings. + * MDIO * MFD From 956dadbe2bb1ca9bcf84091afc6ce52e31506a25 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0602/1389] samples: drivers: led_strip: Remove length Kconfig The chain-length DTS property is now mandatory, so remove the optional Kconfig for setting the length Signed-off-by: Jamie McCrae --- samples/drivers/led_strip/Kconfig | 8 -------- samples/drivers/led_strip/README.rst | 3 --- .../drivers/led_strip/boards/96b_carbon_stm32f401xe.conf | 2 -- samples/drivers/led_strip/boards/adafruit_itsybitsy.conf | 1 - samples/drivers/led_strip/boards/adafruit_trinket_m0.conf | 1 - .../led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf | 1 - samples/drivers/led_strip/boards/nucleo_l432kc.conf | 1 - samples/drivers/led_strip/src/main.c | 4 +--- 8 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 samples/drivers/led_strip/boards/adafruit_itsybitsy.conf delete mode 100644 samples/drivers/led_strip/boards/adafruit_trinket_m0.conf delete mode 100644 samples/drivers/led_strip/boards/nucleo_l432kc.conf diff --git a/samples/drivers/led_strip/Kconfig b/samples/drivers/led_strip/Kconfig index 2931d4cc929b8c..fdf12abde2446f 100644 --- a/samples/drivers/led_strip/Kconfig +++ b/samples/drivers/led_strip/Kconfig @@ -9,14 +9,6 @@ config SAMPLE_LED_UPDATE_DELAY help Delay between LED updates in ms. -config SAMPLE_LED_STRIP_LENGTH - int "LED strip length" - default 0 - help - Number of LEDs in the strip. - If the value is zero, use the 'chain-length' property in - devicetree instead to determine LED numbers. - endmenu source "Kconfig.zephyr" diff --git a/samples/drivers/led_strip/README.rst b/samples/drivers/led_strip/README.rst index a6b00327926342..27c211e24e4036 100644 --- a/samples/drivers/led_strip/README.rst +++ b/samples/drivers/led_strip/README.rst @@ -65,9 +65,6 @@ Building and Running The sample updates the LED strip periodically. The update frequency can be modified by changing the :kconfig:option:`CONFIG_SAMPLE_LED_UPDATE_DELAY`. -If there is no chain-length property in the devicetree node, you need to set -the number of LEDs in the :kconfig:option:`CONFIG_SAMPLE_LED_STRIP_LENGTH` option. - Then build and flash the application: .. zephyr-app-commands:: diff --git a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf index 49fc84a0a95fc0..0232f7d97c3475 100644 --- a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf +++ b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf @@ -1,3 +1 @@ CONFIG_SPI_STM32_INTERRUPT=y - -CONFIG_SAMPLE_LED_STRIP_LENGTH=1 diff --git a/samples/drivers/led_strip/boards/adafruit_itsybitsy.conf b/samples/drivers/led_strip/boards/adafruit_itsybitsy.conf deleted file mode 100644 index 9c347a35588847..00000000000000 --- a/samples/drivers/led_strip/boards/adafruit_itsybitsy.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SAMPLE_LED_STRIP_LENGTH=4 diff --git a/samples/drivers/led_strip/boards/adafruit_trinket_m0.conf b/samples/drivers/led_strip/boards/adafruit_trinket_m0.conf deleted file mode 100644 index af9d53eddc0730..00000000000000 --- a/samples/drivers/led_strip/boards/adafruit_trinket_m0.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SAMPLE_LED_STRIP_LENGTH=1 diff --git a/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf b/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf index e4aff43aee8111..a97acd9ffab891 100644 --- a/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf +++ b/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf @@ -1,3 +1,2 @@ # Enable LED 5V Regulator CONFIG_REGULATOR=y -CONFIG_SAMPLE_LED_STRIP_LENGTH=4 diff --git a/samples/drivers/led_strip/boards/nucleo_l432kc.conf b/samples/drivers/led_strip/boards/nucleo_l432kc.conf deleted file mode 100644 index af9d53eddc0730..00000000000000 --- a/samples/drivers/led_strip/boards/nucleo_l432kc.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SAMPLE_LED_STRIP_LENGTH=1 diff --git a/samples/drivers/led_strip/src/main.c b/samples/drivers/led_strip/src/main.c index d6dafcd68ea92e..45e8fad35cd9d2 100644 --- a/samples/drivers/led_strip/src/main.c +++ b/samples/drivers/led_strip/src/main.c @@ -21,9 +21,7 @@ LOG_MODULE_REGISTER(main); #define STRIP_NODE DT_ALIAS(led_strip) -#if CONFIG_SAMPLE_LED_STRIP_LENGTH != 0 -#define STRIP_NUM_PIXELS CONFIG_SAMPLE_LED_STRIP_LENGTH -#elif DT_NODE_HAS_PROP(DT_ALIAS(led_strip), chain_length) +#if DT_NODE_HAS_PROP(DT_ALIAS(led_strip), chain_length) #define STRIP_NUM_PIXELS DT_PROP(DT_ALIAS(led_strip), chain_length) #else #error Unable to determine length of LED strip From f720b60030db239b098c07bf74fa1c93f0b6039f Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0603/1389] Bluetooth: BAP: Shell: Add support for USB audio in Add support for receiving audio data from e.g. a PC over USB and LC3 encode it before sending it on BAP audio streams. This refactores the entire TX path, as it has moved from only support the sine wave generator, to also supporting USB. The encoding and sending of data is now in it's own thread, instead of relying on the system workqueue thread and k_work items. Several other refactors have taken place to reduce lines of codec (such as the introduction of the bap_foreach_stream function. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/shell/CMakeLists.txt | 2 +- subsys/bluetooth/audio/shell/audio.h | 47 +- subsys/bluetooth/audio/shell/bap.c | 751 +++++++++----------- subsys/bluetooth/audio/shell/bap_usb.c | 245 ++++++- 4 files changed, 597 insertions(+), 448 deletions(-) diff --git a/subsys/bluetooth/audio/shell/CMakeLists.txt b/subsys/bluetooth/audio/shell/CMakeLists.txt index cb86f9042a6723..d44f4e18417774 100644 --- a/subsys/bluetooth/audio/shell/CMakeLists.txt +++ b/subsys/bluetooth/audio/shell/CMakeLists.txt @@ -81,7 +81,7 @@ zephyr_library_sources_ifdef( CONFIG_BT_BAP_STREAM bap.c ) -if (CONFIG_BT_AUDIO_RX AND CONFIG_LIBLC3 AND CONFIG_USB_DEVICE_AUDIO) +if (CONFIG_LIBLC3 AND CONFIG_USB_DEVICE_AUDIO) zephyr_library_sources(bap_usb.c) endif() zephyr_library_sources_ifdef( diff --git a/subsys/bluetooth/audio/shell/audio.h b/subsys/bluetooth/audio/shell/audio.h index 6aa4ee52dd5061..8d537557dae96a 100644 --- a/subsys/bluetooth/audio/shell/audio.h +++ b/subsys/bluetooth/audio/shell/audio.h @@ -48,7 +48,7 @@ ssize_t cap_initiator_pa_data_add(struct bt_data *data_array, const size_t data_ #include #include -unsigned long bap_get_recv_stats_interval(void); +unsigned long bap_get_stats_interval(void); #if defined(CONFIG_LIBLC3) #include "lc3.h" @@ -61,7 +61,7 @@ unsigned long bap_get_recv_stats_interval(void); #define LC3_MAX_NUM_SAMPLES_STEREO (LC3_MAX_NUM_SAMPLES_MONO * 2U) #endif /* CONFIG_LIBLC3 */ -#define LOCATION BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT +#define LOCATION BT_AUDIO_LOCATION_FRONT_LEFT #define CONTEXT \ (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ BT_AUDIO_CONTEXT_TYPE_MEDIA | \ @@ -75,15 +75,6 @@ struct named_lc3_preset { struct bt_bap_lc3_preset preset; }; -const struct named_lc3_preset *bap_get_named_preset(bool is_unicast, enum bt_audio_dir dir, - const char *preset_arg); - -size_t bap_get_rx_streaming_cnt(void); -int bap_usb_init(void); -int bap_usb_add_frame_to_usb(enum bt_audio_location lc3_chan_allocation, const int16_t *frame, - size_t frame_size, uint32_t ts); -void bap_usb_clear_frames_to_usb(void); - struct shell_stream { struct bt_cap_stream stream; struct bt_audio_codec_cfg codec_cfg; @@ -106,11 +97,20 @@ struct shell_stream { /* The uptime tick measured when stream was connected */ int64_t connected_at_ticks; uint16_t seq_num; - struct k_work_delayable audio_send_work; - bool active; #if defined(CONFIG_LIBLC3) atomic_t lc3_enqueue_cnt; + bool active; + size_t encoded_cnt; size_t lc3_sdu_cnt; + lc3_encoder_mem_48k_t lc3_encoder_mem; + lc3_encoder_t lc3_encoder; +#if defined(CONFIG_USB_DEVICE_AUDIO) + /* Indicates where to read left USB data in the ring buffer */ + size_t left_read_idx; + /* Indicates where to read right USB data in the ring buffer */ + size_t right_read_idx; + size_t right_ring_buf_fail_cnt; +#endif /* CONFIG_USB_DEVICE_AUDIO */ #endif /* CONFIG_LIBLC3 */ } tx; #endif /* CONFIG_BT_AUDIO_TX */ @@ -119,6 +119,7 @@ struct shell_stream { struct { struct bt_iso_recv_info last_info; size_t empty_sdu_pkts; + size_t valid_sdu_pkts; size_t lost_pkts; size_t err_pkts; size_t dup_psn; @@ -134,6 +135,26 @@ struct shell_stream { }; }; +const struct named_lc3_preset *bap_get_named_preset(bool is_unicast, enum bt_audio_dir dir, + const char *preset_arg); + +size_t bap_get_rx_streaming_cnt(void); +size_t bap_get_tx_streaming_cnt(void); +void bap_foreach_stream(void (*func)(struct shell_stream *sh_stream, void *data), void *data); + +int bap_usb_init(void); + +int bap_usb_add_frame_to_usb(enum bt_audio_location lc3_chan_allocation, const int16_t *frame, + size_t frame_size, uint32_t ts); +void bap_usb_clear_frames_to_usb(void); +uint16_t get_next_seq_num(struct bt_bap_stream *bap_stream); +struct shell_stream *shell_stream_from_bap_stream(struct bt_bap_stream *bap_stream); +struct bt_bap_stream *bap_stream_from_shell_stream(struct shell_stream *sh_stream); +bool bap_usb_can_get_full_sdu(struct shell_stream *sh_stream); +void bap_usb_get_frame(struct shell_stream *sh_stream, enum bt_audio_location chan_alloc, + int16_t buffer[]); +size_t bap_usb_get_frame_size(const struct shell_stream *sh_stream); + struct broadcast_source { bool is_cap; union { diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index 1ed8f0480691d2..0cc7d9b3d79acc 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -34,23 +34,7 @@ #define IS_BAP_INITIATOR \ (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE) || IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) -#if defined(CONFIG_LIBLC3) - -static void clear_lc3_sine_data(struct bt_bap_stream *bap_stream); -static void lc3_decoder_stream_clear(struct shell_stream *sh_stream); - -static void lc3_clear_stream(struct shell_stream *sh_stream) -{ -#if defined(CONFIG_BT_AUDIO_TX) - clear_lc3_sine_data(&sh_stream->stream.bap_stream); -#endif /* CONFIG_BT_AUDIO_TX */ - -#if defined(CONFIG_BT_AUDIO_RX) - lc3_decoder_stream_clear(sh_stream); -#endif /* CONFIG_BT_AUDIO_RX */ -} - -#endif /* CONFIG_LIBLC3 */ +#define GENERATE_SINE_SUPPORTED (IS_ENABLED(CONFIG_LIBLC3) && !IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) #if defined(CONFIG_BT_BAP_UNICAST) @@ -165,8 +149,9 @@ static const struct named_lc3_preset lc3_broadcast_presets[] = { }; static bool initialized; +static unsigned long bap_stats_interval = 1000U; -static struct shell_stream *shell_stream_from_bap_stream(struct bt_bap_stream *bap_stream) +struct shell_stream *shell_stream_from_bap_stream(struct bt_bap_stream *bap_stream) { struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); @@ -175,13 +160,75 @@ static struct shell_stream *shell_stream_from_bap_stream(struct bt_bap_stream *b return sh_stream; } -static struct bt_bap_stream *bap_stream_from_shell_stream(struct shell_stream *sh_stream) +struct bt_bap_stream *bap_stream_from_shell_stream(struct shell_stream *sh_stream) { return &sh_stream->stream.bap_stream; } +unsigned long bap_get_stats_interval(void) +{ + return bap_stats_interval; +} + +void bap_foreach_stream(void (*func)(struct shell_stream *sh_stream, void *data), void *data) +{ +#if defined(CONFIG_BT_BAP_UNICAST) + for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) { + func(&unicast_streams[i], data); + } +#endif /* CONFIG_BT_BAP_UNICAST */ + +#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { + func(&broadcast_source_streams[i], data); + } +#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */ + +#if defined(CONFIG_BT_BAP_BROADCAST_SINK) + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) { + func(&broadcast_sink_streams[i], data); + } +#endif /* CONFIG_BT_BAP_BROADCAST_SINK */ +} + +#if defined(CONFIG_LIBLC3) +static int get_lc3_chan_alloc_from_index(const struct shell_stream *sh_stream, uint8_t index, + enum bt_audio_location *chan_alloc) +{ + const bool has_left = (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; + const bool has_right = + (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; + const bool is_mono = sh_stream->lc3_chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO; + const bool is_left = index == 0 && has_left; + const bool is_right = has_right && (index == 0U || (index == 1U && has_left)); + + /* LC3 is always Left before Right, so we can use the index and the stream channel + * allocation to determine if index 0 is left or right. + */ + if (is_left) { + *chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT; + } else if (is_right) { + *chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT; + } else if (is_mono) { + *chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO; + } else { + /* Not suitable for USB */ + return -EINVAL; + } + + return 0; +} +#endif /* CONFIG_LIBLC3 */ + #if defined(CONFIG_BT_AUDIO_TX) -static uint16_t get_next_seq_num(struct bt_bap_stream *bap_stream) +static size_t tx_streaming_cnt; + +size_t bap_get_tx_streaming_cnt(void) +{ + return tx_streaming_cnt; +} + +uint16_t get_next_seq_num(struct bt_bap_stream *bap_stream) { struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream); const uint32_t interval_us = bap_stream->qos->interval; @@ -211,7 +258,7 @@ static uint16_t get_next_seq_num(struct bt_bap_stream *bap_stream) * controller ISO buffer to handle jitter. */ #define PRIME_COUNT 2U -#define SINE_TX_POOL_SIZE BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU) +#define SINE_TX_POOL_SIZE (BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU)) NET_BUF_POOL_FIXED_DEFINE(sine_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, SINE_TX_POOL_SIZE, CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); @@ -221,18 +268,58 @@ NET_BUF_POOL_FIXED_DEFINE(sine_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, SINE_TX_POOL #define AUDIO_TONE_FREQUENCY_HZ 400 static int16_t lc3_tx_buf[LC3_MAX_NUM_SAMPLES_MONO]; -static lc3_encoder_t lc3_encoder; -static lc3_encoder_mem_48k_t lc3_encoder_mem; -static int lc3_encoder_freq_hz; -static int lc3_encoder_frame_duration_us; -static void clear_lc3_sine_data(struct bt_bap_stream *bap_stream) +static int init_lc3_encoder(struct shell_stream *sh_stream) { - struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream); + if (sh_stream == NULL) { + shell_error(ctx_shell, "NULL stream to init LC3"); + return -EINVAL; + } - if (sh_stream->is_tx) { - (void)k_work_cancel_delayable(&sh_stream->tx.audio_send_work); + if (!sh_stream->is_tx) { + shell_error(ctx_shell, "Invalid stream to init LC3 encoder"); + return -EINVAL; } + + if (sh_stream->tx.lc3_encoder != NULL) { + shell_error(ctx_shell, "Already initialized"); + return -EALREADY; + } + + if (sh_stream->lc3_freq_hz == 0 || sh_stream->lc3_frame_duration_us == 0) { + shell_error(ctx_shell, "Invalid freq (%u) or frame duration (%u)", + sh_stream->lc3_freq_hz, sh_stream->lc3_frame_duration_us); + + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) { + const size_t frame_size = bap_usb_get_frame_size(sh_stream); + + if (frame_size > sizeof(lc3_tx_buf)) { + shell_error(ctx_shell, "Cannot put %u octets in lc3_tx_buf of size %zu", + frame_size, sizeof(lc3_tx_buf)); + + return -EINVAL; + } + } + + shell_print(ctx_shell, + "Initializing LC3 encoder for BAP stream %p with %u us duration and %u Hz " + "frequency", + bap_stream_from_shell_stream(sh_stream), sh_stream->lc3_frame_duration_us, + sh_stream->lc3_freq_hz); + + sh_stream->tx.lc3_encoder = + lc3_setup_encoder(sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz, + IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) ? USB_SAMPLE_RATE : 0, + &sh_stream->tx.lc3_encoder_mem); + if (sh_stream->tx.lc3_encoder == NULL) { + shell_error(ctx_shell, "Failed to setup LC3 encoder - wrong parameters?\n"); + return -EINVAL; + } + + return 0; } /** @@ -256,57 +343,89 @@ static void fill_lc3_tx_buf_sin(int16_t *buf, int length_us, int frequency_hz, i } } -static int init_lc3_encoder(const struct shell_stream *sh_stream) +static bool encode_frame(struct shell_stream *sh_stream, uint8_t index, size_t frame_cnt, + struct net_buf *out_buf) { - size_t num_samples; + const size_t total_frames = sh_stream->lc3_chan_cnt * sh_stream->lc3_frame_blocks_per_sdu; + const uint16_t octets_per_frame = sh_stream->lc3_octets_per_frame; + int lc3_ret; - if (sh_stream == NULL) { - shell_error(ctx_shell, "invalid stream to init LC3"); - return -EINVAL; - } + if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) { + enum bt_audio_location chan_alloc; + int err; - if (sh_stream->lc3_freq_hz == 0 || sh_stream->lc3_frame_duration_us == 0) { - shell_error(ctx_shell, "Invalid freq (%u) or frame duration (%u)", - sh_stream->lc3_freq_hz, sh_stream->lc3_frame_duration_us); + err = get_lc3_chan_alloc_from_index(sh_stream, index, &chan_alloc); + if (err != 0) { + /* Not suitable for USB */ + false; + } - return -EINVAL; + /* TODO: Move the following to a function in bap_usb.c*/ + bap_usb_get_frame(sh_stream, chan_alloc, lc3_tx_buf); + } else { + /* Generate sine wave */ + fill_lc3_tx_buf_sin(lc3_tx_buf, sh_stream->lc3_frame_duration_us, + AUDIO_TONE_FREQUENCY_HZ, sh_stream->lc3_freq_hz); } - /* Create the encoder instance. This shall complete before stream_started() is called. */ - lc3_encoder = lc3_setup_encoder(sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz, - 0, /* No resampling */ - &lc3_encoder_mem); + if ((sh_stream->tx.encoded_cnt % bap_stats_interval) == 0) { + shell_print(ctx_shell, "[%zu]: Encoding frame of size %u (%u/%u)", + sh_stream->tx.encoded_cnt, octets_per_frame, frame_cnt + 1, + total_frames); + } - if (lc3_encoder == NULL) { - shell_error(ctx_shell, "Failed to setup LC3 encoder - wrong parameters?\n"); - return -EINVAL; + lc3_ret = lc3_encode(sh_stream->tx.lc3_encoder, LC3_PCM_FORMAT_S16, lc3_tx_buf, 1, + octets_per_frame, net_buf_tail(out_buf)); + if (lc3_ret == -1) { + shell_error(ctx_shell, "LC3 encoder failed - wrong parameters?: %d", lc3_ret); + + return false; } - lc3_encoder_freq_hz = sh_stream->lc3_freq_hz; - lc3_encoder_frame_duration_us = sh_stream->lc3_frame_duration_us; + out_buf->len += octets_per_frame; - /* Fill audio buffer with Sine wave only once and repeat encoding the same tone frame */ - fill_lc3_tx_buf_sin(lc3_tx_buf, lc3_encoder_frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, - lc3_encoder_freq_hz); + return true; +} - num_samples = ((lc3_encoder_frame_duration_us * lc3_encoder_freq_hz) / USEC_PER_SEC); - for (size_t i = 0; i < num_samples; i++) { - printk("%zu: %6i\n", i, lc3_tx_buf[i]); +static size_t encode_frame_block(struct shell_stream *sh_stream, size_t frame_cnt, + struct net_buf *out_buf) +{ + const uint8_t chan_cnt = sh_stream->lc3_chan_cnt; + size_t encoded_frames = 0U; + + for (uint8_t i = 0U; i < chan_cnt; i++) { + /* We provide the total number of decoded frames to `decode_frame` for logging + * purposes + */ + if (encode_frame(sh_stream, i, frame_cnt, out_buf)) { + encoded_frames++; + } } - return 0; + return encoded_frames; } -static void lc3_audio_send_data(struct k_work *work) +static void do_lc3_encode(struct shell_stream *sh_stream, struct net_buf *out_buf) +{ + if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) && !bap_usb_can_get_full_sdu(sh_stream)) { + /* No op - Will just send empty SDU */ + } else { + size_t frame_cnt = 0U; + + for (uint8_t i = 0U; i < sh_stream->lc3_frame_blocks_per_sdu; i++) { + frame_cnt += encode_frame_block(sh_stream, frame_cnt, out_buf); + + sh_stream->tx.encoded_cnt++; + } + } +} + +static void lc3_audio_send_data(struct shell_stream *sh_stream) { - struct shell_stream *sh_stream = CONTAINER_OF(k_work_delayable_from_work(work), - struct shell_stream, tx.audio_send_work); struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream); const uint16_t tx_sdu_len = sh_stream->lc3_frame_blocks_per_sdu * sh_stream->lc3_chan_cnt * sh_stream->lc3_octets_per_frame; struct net_buf *buf; - uint8_t *net_buffer; - off_t offset = 0; int err; if (!sh_stream->is_tx || !sh_stream->tx.active) { @@ -314,7 +433,7 @@ static void lc3_audio_send_data(struct k_work *work) return; } - if (lc3_encoder == NULL) { + if (sh_stream->tx.lc3_encoder == NULL) { shell_error(ctx_shell, "LC3 encoder not setup, cannot encode data"); return; } @@ -335,53 +454,24 @@ static void lc3_audio_send_data(struct k_work *work) } if (atomic_get(&sh_stream->tx.lc3_enqueue_cnt) == 0U) { - shell_error(ctx_shell, "Stream %p enqueue count was 0", bap_stream); - - /* Reschedule for next interval */ - k_work_reschedule(k_work_delayable_from_work(work), - K_USEC(bap_stream->qos->interval)); + /* no op */ return; } buf = net_buf_alloc(&sine_tx_pool, K_FOREVER); net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - net_buffer = net_buf_tail(buf); - buf->len += tx_sdu_len; - - for (uint8_t i = 0U; i < sh_stream->lc3_frame_blocks_per_sdu; i++) { - for (uint8_t j = 0U; j < sh_stream->lc3_chan_cnt; j++) { - int lc3_ret; - - lc3_ret = lc3_encode(lc3_encoder, LC3_PCM_FORMAT_S16, lc3_tx_buf, 1, - sh_stream->lc3_octets_per_frame, net_buffer + offset); - offset += sh_stream->lc3_octets_per_frame; - - if (lc3_ret == -1) { - shell_error(ctx_shell, "LC3 encoder failed - wrong parameters?: %d", - lc3_ret); - net_buf_unref(buf); - - /* Reschedule for next interval */ - k_work_reschedule(k_work_delayable_from_work(work), - K_USEC(bap_stream->qos->interval)); - return; - } - } - } + do_lc3_encode(sh_stream, buf); err = bt_bap_stream_send(bap_stream, buf, sh_stream->tx.seq_num); if (err < 0) { shell_error(ctx_shell, "Failed to send LC3 audio data (%d)", err); net_buf_unref(buf); - /* Reschedule for next interval */ - k_work_reschedule(k_work_delayable_from_work(work), - K_USEC(bap_stream->qos->interval)); return; } - if ((sh_stream->tx.lc3_sdu_cnt % 100) == 0) { + if ((sh_stream->tx.lc3_sdu_cnt % bap_stats_interval) == 0U) { shell_info(ctx_shell, "[%zu]: stream %p : TX LC3: %zu (seq_num %u)", sh_stream->tx.lc3_sdu_cnt, bap_stream, tx_sdu_len, sh_stream->tx.seq_num); @@ -390,34 +480,38 @@ static void lc3_audio_send_data(struct k_work *work) sh_stream->tx.lc3_sdu_cnt++; sh_stream->tx.seq_num++; atomic_dec(&sh_stream->tx.lc3_enqueue_cnt); - - if (atomic_get(&sh_stream->tx.lc3_enqueue_cnt) > 0) { - /* If we have more buffers available, we reschedule the workqueue item immediately - * to trigger another encode + TX, but without blocking this call for too long - */ - k_work_reschedule(k_work_delayable_from_work(work), K_NO_WAIT); - } } static void lc3_sent_cb(struct bt_bap_stream *bap_stream) { struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream); - int err; if (!sh_stream->is_tx) { return; } atomic_inc(&sh_stream->tx.lc3_enqueue_cnt); +} - if (!sh_stream->tx.active) { - /* TX has been aborted */ - return; +static void encode_and_send_cb(struct shell_stream *sh_stream, void *user_data) +{ + if (sh_stream->is_tx) { + lc3_audio_send_data(sh_stream); } +} - err = k_work_schedule(&sh_stream->tx.audio_send_work, K_NO_WAIT); - if (err < 0) { - shell_error(ctx_shell, "Failed to schedule TX for stream %p: %d", bap_stream, err); +static void lc3_encoder_thread_func(void *arg1, void *arg2, void *arg3) +{ + /* This will attempt to send on all TX streams. + * If there are no buffers available or the stream already have PRIME_COUNT outstanding SDUs + * the stream will not send anything. + * + * If USB is enabled it will attempt to read from buffered USB audio data. + * If there is no data available it will send empty SDUs + */ + while (true) { + bap_foreach_stream(encode_and_send_cb, NULL); + k_sleep(K_MSEC(1)); } } #endif /* CONFIG_LIBLC3 && CONFIG_BT_AUDIO_TX */ @@ -2359,7 +2453,6 @@ static struct bt_le_scan_cb bap_scan_cb = { #endif /* CONFIG_BT_BAP_BROADCAST_SINK */ #if defined(CONFIG_BT_AUDIO_RX) -static unsigned long recv_stats_interval = 1000U; static size_t rx_streaming_cnt; size_t bap_get_rx_streaming_cnt(void) @@ -2392,12 +2485,12 @@ static struct shell_stream *usb_right_stream; static int init_lc3_decoder(struct shell_stream *sh_stream) { if (sh_stream == NULL) { - shell_error(ctx_shell, "NULL stream to init LC3"); + shell_error(ctx_shell, "NULL stream to init LC3 decoder"); return -EINVAL; } if (!sh_stream->is_rx) { - shell_error(ctx_shell, "Invalid stream to init LC3"); + shell_error(ctx_shell, "Invalid stream to init LC3 decoder"); return -EINVAL; } @@ -2429,13 +2522,6 @@ static int init_lc3_decoder(struct shell_stream *sh_stream) return 0; } -static void lc3_decoder_stream_clear(struct shell_stream *sh_stream) -{ - if (sh_stream->is_rx) { - sh_stream->rx.lc3_decoder = NULL; - } -} - static bool decode_frame(struct lc3_data *data, size_t frame_cnt) { const struct shell_stream *sh_stream = data->sh_stream; @@ -2448,15 +2534,17 @@ static bool decode_frame(struct lc3_data *data, size_t frame_cnt) if (data->do_plc) { iso_data = NULL; /* perform PLC */ - if ((sh_stream->rx.decoded_cnt % recv_stats_interval) == 0) { + if ((sh_stream->rx.decoded_cnt % bap_stats_interval) == 0) { shell_print(ctx_shell, "[%zu]: Performing PLC", sh_stream->rx.decoded_cnt); } + + data->do_plc = false; /* clear flag */ } else { iso_data = net_buf_pull_mem(data->buf, octets_per_frame); - if ((sh_stream->rx.decoded_cnt % recv_stats_interval) == 0) { + if ((sh_stream->rx.decoded_cnt % bap_stats_interval) == 0) { shell_print(ctx_shell, "[%zu]: Decoding frame of size %u (%u/%u)", - sh_stream->rx.decoded_cnt, octets_per_frame, frame_cnt, + sh_stream->rx.decoded_cnt, octets_per_frame, frame_cnt + 1, total_frames); } } @@ -2472,34 +2560,7 @@ static bool decode_frame(struct lc3_data *data, size_t frame_cnt) return true; } -static int get_chan_alloc_from_index(const struct shell_stream *sh_stream, uint8_t index, - enum bt_audio_location *chan_alloc) -{ - const bool has_left = (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; - const bool has_right = - (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; - const bool is_mono = sh_stream->lc3_chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO; - const bool is_left = index == 0 && has_left; - const bool is_right = has_right && (index == 0U || (index == 1U && has_left)); - - /* LC3 is always Left before Right, so we can use the index and the stream channel - * allocation to determine if index 0 is left or right. - */ - if (is_left) { - *chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT; - } else if (is_right) { - *chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT; - } else if (is_mono) { - *chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO; - } else { - /* Not suitable for USB */ - return -EINVAL; - } - - return 0; -} - -static int decode_frame_block(struct lc3_data *data, size_t frame_cnt) +static size_t decode_frame_block(struct lc3_data *data, size_t frame_cnt) { const struct shell_stream *sh_stream = data->sh_stream; const uint8_t chan_cnt = sh_stream->lc3_chan_cnt; @@ -2516,7 +2577,7 @@ static int decode_frame_block(struct lc3_data *data, size_t frame_cnt) enum bt_audio_location chan_alloc; int err; - err = get_chan_alloc_from_index(sh_stream, i, &chan_alloc); + err = get_lc3_chan_alloc_from_index(sh_stream, i, &chan_alloc); if (err != 0) { /* Not suitable for USB */ continue; @@ -2596,11 +2657,6 @@ static void lc3_decoder_thread_func(void *arg1, void *arg2, void *arg3) #endif /* CONFIG_LIBLC3*/ -unsigned long bap_get_recv_stats_interval(void) -{ - return recv_stats_interval; -} - static void audio_recv(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, struct net_buf *buf) @@ -2621,8 +2677,12 @@ static void audio_recv(struct bt_bap_stream *stream, sh_stream->rx.dup_psn++; } - if ((info->flags & BT_ISO_FLAGS_VALID) != 0 && buf->len == 0U) { - sh_stream->rx.empty_sdu_pkts++; + if ((info->flags & BT_ISO_FLAGS_VALID) != 0) { + if (buf->len == 0U) { + sh_stream->rx.empty_sdu_pkts++; + } else { + sh_stream->rx.valid_sdu_pkts++; + } } if (info->flags & BT_ISO_FLAGS_ERROR) { @@ -2633,14 +2693,14 @@ static void audio_recv(struct bt_bap_stream *stream, sh_stream->rx.lost_pkts++; } - if ((sh_stream->rx.rx_cnt % recv_stats_interval) == 0) { + if ((sh_stream->rx.rx_cnt % bap_stats_interval) == 0) { shell_print(ctx_shell, "[%zu]: Incoming audio on stream %p len %u ts %u seq_num %u flags %u " - "(dup ts %zu; dup psn %zu, err_pkts %zu, lost_pkts %zu, " + "(valid %zu, dup ts %zu, dup psn %zu, err_pkts %zu, lost_pkts %zu, " "empty SDUs %zu)", sh_stream->rx.rx_cnt, stream, buf->len, info->ts, info->seq_num, - info->flags, sh_stream->rx.dup_ts, sh_stream->rx.dup_psn, - sh_stream->rx.err_pkts, sh_stream->rx.lost_pkts, + info->flags, sh_stream->rx.valid_sdu_pkts, sh_stream->rx.dup_ts, + sh_stream->rx.dup_psn, sh_stream->rx.err_pkts, sh_stream->rx.lost_pkts, sh_stream->rx.empty_sdu_pkts); } @@ -2818,13 +2878,30 @@ static void stream_started_cb(struct bt_bap_stream *bap_stream) sh_stream->lc3_octets_per_frame = 0U; } +#if defined(CONFIG_BT_AUDIO_TX) + if (sh_stream->is_tx && sh_stream->tx.lc3_encoder == NULL) { + const int err = init_lc3_encoder(sh_stream); + + if (err != 0) { + shell_error(ctx_shell, "Failed to init LC3 encoder: %d", err); + + return; + } + + if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) { + /* Always mark as active when using USB */ + sh_stream->tx.active = true; + } + } +#endif /* CONFIG_BT_AUDIO_TX */ + #if defined(CONFIG_BT_AUDIO_RX) if (sh_stream->is_rx) { if (sh_stream->rx.lc3_decoder == NULL) { const int err = init_lc3_decoder(sh_stream); if (err != 0) { - shell_error(ctx_shell, "Failed to init the LC3 decoder: %d", + shell_error(ctx_shell, "Failed to init LC3 decoder: %d", err); return; @@ -2874,6 +2951,7 @@ static void stream_started_cb(struct bt_bap_stream *bap_stream) #if defined(CONFIG_BT_AUDIO_RX) if (sh_stream->is_rx) { sh_stream->rx.empty_sdu_pkts = 0U; + sh_stream->rx.valid_sdu_pkts = 0U; sh_stream->rx.lost_pkts = 0U; sh_stream->rx.err_pkts = 0U; sh_stream->rx.dup_psn = 0U; @@ -2886,102 +2964,44 @@ static void stream_started_cb(struct bt_bap_stream *bap_stream) } #if defined(CONFIG_LIBLC3) -static void update_usb_streams(struct shell_stream *sh_stream) +static void update_usb_streams_cb(struct shell_stream *sh_stream, void *user_data) { - /* If the @p sh_stream is the left or right USB stream, we look through other streams to see - * if any of them can be assigned as the USB stream(s) - */ - if (usb_left_stream == sh_stream) { - shell_info(ctx_shell, "Clearing USB left stream (%p)", usb_left_stream); - usb_left_stream = NULL; - -#if defined(CONFIG_BT_BAP_UNICAST) - for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) { - struct shell_stream *tmp_sh_stream = &unicast_streams[i]; - - if (usb_left_stream != NULL) { - break; - } - - if (tmp_sh_stream->is_rx && (tmp_sh_stream->lc3_chan_allocation & - BT_AUDIO_LOCATION_FRONT_LEFT) != 0) { - usb_left_stream = tmp_sh_stream; - shell_info(ctx_shell, "Setting new USB left stream to %p", - tmp_sh_stream); - break; - } + if (sh_stream->is_rx) { + if (usb_left_stream == NULL && + (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0) { + shell_info(ctx_shell, "Setting new USB left stream to %p", sh_stream); + usb_left_stream = sh_stream; } -#endif /* CONFIG_BT_BAP_UNICAST */ - -#if defined(CONFIG_BT_BAP_BROADCAST_SINK) - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) { - struct shell_stream *tmp_sh_stream = &unicast_streams[i]; - - if (usb_left_stream != NULL) { - break; - } - if (tmp_sh_stream->is_rx && (tmp_sh_stream->lc3_chan_allocation & - BT_AUDIO_LOCATION_FRONT_LEFT) != 0) { - usb_left_stream = tmp_sh_stream; - shell_info(ctx_shell, "Setting new USB right stream to %p", - tmp_sh_stream); - break; - } + if (usb_right_stream == NULL && + (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) { + shell_info(ctx_shell, "Setting new USB right stream to %p", sh_stream); + usb_right_stream = sh_stream; } -#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */ } +} - if (usb_right_stream == sh_stream) { - shell_info(ctx_shell, "Clearing USB right stream (%p)", usb_right_stream); - usb_right_stream = NULL; - -#if defined(CONFIG_BT_BAP_UNICAST) - for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) { - struct shell_stream *tmp_sh_stream = &unicast_streams[i]; - - if (usb_right_stream != NULL) { - break; - } - - if (tmp_sh_stream->is_rx && (tmp_sh_stream->lc3_chan_allocation & - BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) { - usb_right_stream = tmp_sh_stream; - break; - } +static void update_usb_streams(struct shell_stream *sh_stream) +{ + if (sh_stream->is_rx) { + if (sh_stream == usb_left_stream) { + shell_info(ctx_shell, "Clearing USB left stream (%p)", usb_left_stream); + usb_left_stream = NULL; } -#endif /* CONFIG_BT_BAP_UNICAST */ -#if defined(CONFIG_BT_BAP_BROADCAST_SINK) - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) { - struct shell_stream *tmp_sh_stream = &unicast_streams[i]; - - if (usb_right_stream != NULL) { - break; - } - - if (tmp_sh_stream->is_rx && (tmp_sh_stream->lc3_chan_allocation & - BT_AUDIO_LOCATION_FRONT_RIGHT) != 0) { - usb_right_stream = tmp_sh_stream; - } + if (sh_stream == usb_right_stream) { + shell_info(ctx_shell, "Clearing USB right stream (%p)", usb_right_stream); + usb_right_stream = NULL; } -#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */ + + bap_foreach_stream(update_usb_streams_cb, NULL); } } #endif /* CONFIG_LIBLC3 */ -static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +static void clear_stream_data(struct shell_stream *sh_stream) { - struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream); - - printk("Stream %p stopped with reason 0x%02X\n", stream, reason); - -#if defined(CONFIG_LIBLC3) - lc3_clear_stream(shell_stream_from_bap_stream(stream)); -#endif /* CONFIG_LIBLC3 */ - #if defined(CONFIG_BT_BAP_BROADCAST_SINK) - if (IS_ARRAY_ELEMENT(broadcast_sink_streams, sh_stream)) { if (default_broadcast_sink.stream_cnt != 0) { default_broadcast_sink.stream_cnt--; @@ -3000,11 +3020,13 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) #if defined(CONFIG_BT_AUDIO_RX) if (sh_stream->is_rx) { rx_streaming_cnt--; + memset(&sh_stream->rx, 0, sizeof(sh_stream->rx)); } #endif + #if defined(CONFIG_BT_AUDIO_TX) if (sh_stream->is_tx) { - sh_stream->tx.active = false; + memset(&sh_stream->tx, 0, sizeof(sh_stream->tx)); } #endif @@ -3017,6 +3039,15 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) #endif /* CONFIG_LIBLC3 */ } +static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + struct shell_stream *sh_stream = shell_stream_from_bap_stream(stream); + + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + + clear_stream_data(sh_stream); +} + #if defined(CONFIG_BT_BAP_UNICAST) static void stream_configured_cb(struct bt_bap_stream *stream, const struct bt_audio_codec_qos_pref *pref) @@ -3067,18 +3098,7 @@ static void stream_released_cb(struct bt_bap_stream *stream) } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */ -#if defined(CONFIG_LIBLC3) - lc3_clear_stream(shell_stream_from_bap_stream(stream)); -#endif /* CONFIG_LIBLC3 */ - - sh_stream->is_tx = false; - sh_stream->is_rx = false; - -#if defined(CONFIG_LIBLC3) - if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) { - update_usb_streams(sh_stream); - } -#endif /* CONFIG_LIBLC3 */ + clear_stream_data(sh_stream); } #endif /* CONFIG_BT_BAP_UNICAST */ @@ -3655,22 +3675,36 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[]) } #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */ -#if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_RX) +#if defined(CONFIG_LIBLC3) +#if defined(CONFIG_BT_AUDIO_RX) static K_KERNEL_STACK_DEFINE(lc3_decoder_thread_stack, 4096); - int lc3_decoder_thread_prio = K_PRIO_PREEMPT(5); - + const int lc3_decoder_thread_prio = K_PRIO_PREEMPT(5); static struct k_thread lc3_decoder_thread; k_thread_create(&lc3_decoder_thread, lc3_decoder_thread_stack, K_KERNEL_STACK_SIZEOF(lc3_decoder_thread_stack), lc3_decoder_thread_func, NULL, NULL, NULL, lc3_decoder_thread_prio, 0, K_NO_WAIT); k_thread_name_set(&lc3_decoder_thread, "LC3 Decoder"); +#endif /* CONFIG_BT_AUDIO_RX */ - if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) { +#if defined(CONFIG_BT_AUDIO_TX) + static K_KERNEL_STACK_DEFINE(lc3_encoder_thread_stack, 4096); + const int lc3_encoder_thread_prio = K_PRIO_PREEMPT(5); + static struct k_thread lc3_encoder_thread; + + k_thread_create(&lc3_encoder_thread, lc3_encoder_thread_stack, + K_KERNEL_STACK_SIZEOF(lc3_encoder_thread_stack), lc3_encoder_thread_func, + NULL, NULL, NULL, lc3_encoder_thread_prio, 0, K_NO_WAIT); + k_thread_name_set(&lc3_encoder_thread, "LC3 Encoder"); + +#endif /* CONFIG_BT_AUDIO_TX */ + + if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) && + (IS_ENABLED(CONFIG_BT_AUDIO_RX) || IS_ENABLED(CONFIG_BT_AUDIO_TX))) { err = bap_usb_init(); __ASSERT(err == 0, "Failed to enable USB: %d", err); } -#endif /* CONFIG_LIBLC3 && CONFIG_BT_AUDIO_RX */ +#endif /* CONFIG_LIBLC3 */ initialized = true; @@ -3678,6 +3712,7 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[]) } #if defined(CONFIG_BT_AUDIO_TX) + #define DATA_MTU CONFIG_BT_ISO_TX_MTU NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, DATA_MTU, CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); @@ -3731,58 +3766,26 @@ static int cmd_send(const struct shell *sh, size_t argc, char *argv[]) return 0; } -#if defined(CONFIG_LIBLC3) -static bool stream_start_sine_verify(const struct shell_stream *sh_stream) +#if GENERATE_SINE_SUPPORTED +static void start_sine_stream_cb(struct shell_stream *sh_stream, void *user_data) { - const struct bt_bap_stream *bap_stream; - struct bt_bap_ep_info info; - int err; - - if (sh_stream == NULL) { - return false; - } - - bap_stream = &sh_stream->stream.bap_stream; - - if (bap_stream->qos == NULL) { - return false; - } - - err = bt_bap_ep_get_info(bap_stream->ep, &info); - if (err != 0) { - return false; - } - - if (info.state != BT_BAP_EP_STATE_STREAMING) { - return false; - } - - if (sh_stream->lc3_freq_hz != lc3_encoder_freq_hz || - sh_stream->lc3_frame_duration_us != lc3_encoder_frame_duration_us) { - return false; - } + if (sh_stream->is_tx) { + struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream); + const struct shell *sh = user_data; + int err; - return true; -} -static int stream_start_sine(struct shell_stream *sh_stream) -{ - int err; + err = init_lc3_encoder(sh_stream); + if (err != 0) { + shell_error(sh, "Failed to init LC3 %d for stream %p", err, bap_stream); - if (!sh_stream->is_tx) { - return -EINVAL; - } + return -ENOEXEC; + } - k_work_init_delayable(&sh_stream->tx.audio_send_work, lc3_audio_send_data); + sh_stream->tx.active = true; + sh_stream->tx.seq_num = get_next_seq_num(bap_stream_from_shell_stream(sh_stream)); - err = k_work_schedule(&sh_stream->tx.audio_send_work, K_NO_WAIT); - if (err < 0) { - return -ENOEXEC; + shell_print(sh, "Started transmitting sine on stream %p", bap_stream); } - - sh_stream->tx.active = true; - sh_stream->tx.seq_num = get_next_seq_num(bap_stream_from_shell_stream(sh_stream)); - - return 0; } static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) @@ -3801,91 +3804,27 @@ static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) } if (start_all) { - bool lc3_initialized = false; - - for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) { - struct shell_stream *sh_stream = &unicast_streams[i]; - struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream); - - if (!lc3_initialized) { - err = init_lc3_encoder(sh_stream); - if (err != 0) { - shell_error(sh, "Failed to init LC3 %d", err); - - return -ENOEXEC; - } - - lc3_initialized = true; - } - - if (!stream_start_sine_verify(sh_stream)) { - continue; - } - - err = stream_start_sine(sh_stream); - if (err != 0) { - shell_error(sh, "Failed to start TX for stream %p: %d", bap_stream, - err); - return err; - } - - shell_print(sh, "Started transmitting on unicast stream %p", bap_stream); - } - - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { - struct shell_stream *sh_stream = &broadcast_source_streams[i]; - struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream); - - if (!lc3_initialized) { - err = init_lc3_encoder(sh_stream); - if (err != 0) { - shell_error(sh, "Failed to init LC3 %d", err); - - return -ENOEXEC; - } - - lc3_initialized = true; - } - - if (!stream_start_sine_verify(sh_stream)) { - continue; - } - - err = stream_start_sine(sh_stream); - if (err != 0) { - shell_error(sh, "Failed to start TX for stream %p: %d", bap_stream, - err); - return err; - } - - shell_print(sh, "Started transmitting on broadcast stream %p", bap_stream); - } + bap_foreach_stream(start_sine_stream_cb, sh); } else { struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream); - err = init_lc3_encoder(sh_stream); - if (err != 0) { - shell_error(sh, "Failed to init LC3 %d", err); + start_sine_stream_cb(sh_stream, sh); + } - return -ENOEXEC; - } + return 0; +} - if (!stream_start_sine_verify(sh_stream)) { - shell_error(sh, "Invalid stream %p", default_stream); - return -ENOEXEC; - } +static void stop_sine_stream_cb(struct shell_stream *sh_stream, void *user_data) +{ + if (sh_stream->is_tx) { + struct bt_bap_stream *bap_stream = + bap_stream_from_shell_stream(&unicast_streams[i]); + const struct shell *sh = user_data; - err = stream_start_sine(sh_stream); - if (err != 0) { - shell_error(sh, "Failed to start TX for stream %p: %d", default_stream, - err); - return err; - } + shell_print(sh, "Stopped transmitting on stream %p", bap_stream); - shell_print(sh, "Started transmitting on default_stream %p", default_stream); + sh_stream->tx.active = false; } - - return 0; } static int cmd_stop_sine(const struct shell *sh, size_t argc, char *argv[]) @@ -3903,43 +3842,22 @@ static int cmd_stop_sine(const struct shell *sh, size_t argc, char *argv[]) } if (stop_all) { - for (size_t i = 0U; i < ARRAY_SIZE(unicast_streams); i++) { - struct bt_bap_stream *bap_stream = - bap_stream_from_shell_stream(&unicast_streams[i]); - - if (unicast_streams[i].is_tx && unicast_streams[i].tx.active) { - clear_lc3_sine_data(bap_stream); - shell_print(sh, "Stopped transmitting on stream %p", bap_stream); - } - } - - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_source_streams); i++) { - struct bt_bap_stream *bap_stream = - bap_stream_from_shell_stream(&broadcast_source_streams[i]); - if (unicast_streams[i].is_tx && unicast_streams[i].tx.active) { - clear_lc3_sine_data(bap_stream); - shell_print(sh, "Stopped transmitting on stream %p", bap_stream); - } - } + bap_foreach_stream(stop_sine_stream_cb, sh); } else { struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream); - if (sh_stream->is_tx && sh_stream->tx.active) { - clear_lc3_sine_data(default_stream); - shell_print(sh, "Stopped transmitting on stream %p", default_stream); - } + stop_sine_stream_cb(sh_stream, sh) } return 0; } -#endif /* CONFIG_LIBLC3 */ +#endif /* GENERATE_SINE_SUPPORTED */ #endif /* CONFIG_BT_AUDIO_TX */ -#if defined(CONFIG_BT_AUDIO_RX) -static int cmd_recv_stats(const struct shell *sh, size_t argc, char *argv[]) +static int cmd_bap_stats(const struct shell *sh, size_t argc, char *argv[]) { if (argc == 1) { - shell_info(sh, "Current receive stats interval: %lu", recv_stats_interval); + shell_info(sh, "Current stats interval: %lu", bap_stats_interval); } else { int err = 0; unsigned long interval; @@ -3957,12 +3875,11 @@ static int cmd_recv_stats(const struct shell *sh, size_t argc, char *argv[]) return -ENOEXEC; } - recv_stats_interval = interval; + bap_stats_interval = interval; } return 0; } -#endif /* CONFIG_BT_AUDIO_RX */ #if defined(CONFIG_BT_BAP_UNICAST_SERVER) static void print_ase_info(struct bt_bap_ep *ep, void *user_data) @@ -4055,18 +3972,16 @@ SHELL_STATIC_SUBCMD_SET_CREATE( #endif /* IS_BAP_INITIATOR */ #if defined(CONFIG_BT_AUDIO_TX) SHELL_CMD_ARG(send, NULL, "Send to Audio Stream [data]", cmd_send, 1, 1), -#if defined(CONFIG_LIBLC3) +#if GENERATE_SINE_SUPPORTED SHELL_CMD_ARG(start_sine, NULL, "Start sending a LC3 encoded sine wave [all]", cmd_start_sine, 1, 1), SHELL_CMD_ARG(stop_sine, NULL, "Stop sending a LC3 encoded sine wave [all]", cmd_stop_sine, 1, 1), -#endif /* CONFIG_LIBLC3 */ +#endif /* GENERATE_SINE_SUPPORTED */ #endif /* CONFIG_BT_AUDIO_TX */ -#if defined(CONFIG_BT_AUDIO_RX) - SHELL_CMD_ARG(recv_stats, NULL, - "Sets or gets the receive statistics reporting interval in # of packets", - cmd_recv_stats, 1, 1), -#endif /* CONFIG_BT_AUDIO_RX */ + SHELL_CMD_ARG(bap_stats, NULL, + "Sets or gets the statistics reporting interval in # of packets", + cmd_bap_stats, 1, 1), SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_location, NULL, " ", cmd_set_loc, 3, 0), SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_context, NULL, diff --git a/subsys/bluetooth/audio/shell/bap_usb.c b/subsys/bluetooth/audio/shell/bap_usb.c index 97c7309bca8fc4..30afd5ae093c3a 100644 --- a/subsys/bluetooth/audio/shell/bap_usb.c +++ b/subsys/bluetooth/audio/shell/bap_usb.c @@ -10,6 +10,7 @@ */ #include +#include #include #include @@ -27,13 +28,17 @@ LOG_MODULE_REGISTER(bap_usb, CONFIG_BT_BAP_STREAM_LOG_LEVEL); -#define USB_ENQUEUE_COUNT 30U /* 30ms */ -#define USB_FRAME_DURATION_US 1000U -#define USB_MONO_SAMPLE_SIZE \ - ((USB_FRAME_DURATION_US * USB_SAMPLE_RATE * sizeof(int16_t)) / USEC_PER_SEC) -#define USB_STEREO_SAMPLE_SIZE (USB_MONO_SAMPLE_SIZE * 2U) -#define USB_RING_BUF_SIZE (CONFIG_BT_ISO_RX_BUF_COUNT * LC3_MAX_NUM_SAMPLES_STEREO) - +#define USB_ENQUEUE_COUNT 30U /* 30ms */ +#define USB_FRAME_DURATION_US 1000U +#define USB_SAMPLE_CNT ((USB_FRAME_DURATION_US * USB_SAMPLE_RATE) / USEC_PER_SEC) +#define USB_BYTES_PER_SAMPLE sizeof(int16_t) +#define USB_MONO_FRAME_SIZE (USB_SAMPLE_CNT * USB_BYTES_PER_SAMPLE) +#define USB_CHANNELS 2U +#define USB_STEREO_FRAME_SIZE (USB_MONO_FRAME_SIZE * USB_CHANNELS) +#define USB_OUT_RING_BUF_SIZE (CONFIG_BT_ISO_RX_BUF_COUNT * LC3_MAX_NUM_SAMPLES_STEREO) +#define USB_IN_RING_BUF_SIZE (USB_MONO_FRAME_SIZE * USB_ENQUEUE_COUNT) + +#if defined CONFIG_BT_AUDIO_RX struct decoded_sdu { int16_t right_frames[MAX_CODEC_FRAMES_PER_SDU][LC3_MAX_NUM_SAMPLES_MONO]; int16_t left_frames[MAX_CODEC_FRAMES_PER_SDU][LC3_MAX_NUM_SAMPLES_MONO]; @@ -43,13 +48,13 @@ struct decoded_sdu { uint32_t ts; } decoded_sdu; -RING_BUF_DECLARE(usb_out_ring_buf, USB_RING_BUF_SIZE); -NET_BUF_POOL_DEFINE(usb_tx_buf_pool, USB_ENQUEUE_COUNT, USB_STEREO_SAMPLE_SIZE, 0, net_buf_destroy); +RING_BUF_DECLARE(usb_out_ring_buf, USB_OUT_RING_BUF_SIZE); +NET_BUF_POOL_DEFINE(usb_out_buf_pool, USB_ENQUEUE_COUNT, USB_STEREO_FRAME_SIZE, 0, net_buf_destroy); /* USB consumer callback, called every 1ms, consumes data from ring-buffer */ static void usb_data_request_cb(const struct device *dev) { - uint8_t usb_audio_data[USB_STEREO_SAMPLE_SIZE] = {0}; + uint8_t usb_audio_data[USB_STEREO_FRAME_SIZE] = {0}; struct net_buf *pcm_buf; uint32_t size; int err; @@ -59,7 +64,7 @@ static void usb_data_request_cb(const struct device *dev) return; } - pcm_buf = net_buf_alloc(&usb_tx_buf_pool, K_NO_WAIT); + pcm_buf = net_buf_alloc(&usb_out_buf_pool, K_NO_WAIT); if (pcm_buf == NULL) { LOG_WRN("Could not allocate pcm_buf"); return; @@ -73,13 +78,13 @@ static void usb_data_request_cb(const struct device *dev) if (size != 0) { static size_t cnt; - if ((++cnt % bap_get_recv_stats_interval()) == 0U) { + if ((++cnt % bap_get_stats_interval()) == 0U) { LOG_INF("[%zu]: Sending USB audio", cnt); } } else { static size_t cnt; - if ((++cnt % bap_get_recv_stats_interval()) == 0U) { + if ((++cnt % bap_get_stats_interval()) == 0U) { LOG_INF("[%zu]: Sending empty USB audio", cnt); } } @@ -128,7 +133,7 @@ static void bap_usb_send_frames_to_usb(void) /* Not enough space to store data */ if (ring_buf_space_get(&usb_out_ring_buf) < sizeof(stereo_frame)) { - if ((fail_cnt % bap_get_recv_stats_interval()) == 0U) { + if ((fail_cnt % bap_get_stats_interval()) == 0U) { LOG_WRN("[%zu] Could not send more than %zu frames to USB", fail_cnt, i); } @@ -174,7 +179,7 @@ static void bap_usb_send_frames_to_usb(void) } } - if ((++cnt % bap_get_recv_stats_interval()) == 0U) { + if ((++cnt % bap_get_stats_interval()) == 0U) { LOG_INF("[%zu]: Sending %u USB audio frame", cnt, frame_cnt); } @@ -199,7 +204,7 @@ int bap_usb_add_frame_to_usb(enum bt_audio_location chan_allocation, const int16 static size_t cnt; - if ((++cnt % bap_get_recv_stats_interval()) == 0U) { + if ((++cnt % bap_get_stats_interval()) == 0U) { LOG_INF("[%zu]: Adding USB audio frame", cnt); } @@ -300,13 +305,221 @@ void bap_usb_clear_frames_to_usb(void) decoded_sdu.left_frames_cnt = 0U; decoded_sdu.ts = 0U; } +#endif /* CONFIG_BT_AUDIO_RX */ + +#if defined(CONFIG_BT_AUDIO_TX) +BUILD_ASSERT((USB_IN_RING_BUF_SIZE % USB_MONO_FRAME_SIZE) == 0); +static int16_t usb_in_left_ring_buffer[USB_IN_RING_BUF_SIZE]; +static int16_t usb_in_right_ring_buffer[USB_IN_RING_BUF_SIZE]; +static size_t write_index; /* Points to the oldest/uninitialized data */ + +size_t bap_usb_get_read_cnt(const struct shell_stream *sh_stream) +{ + return (USB_SAMPLE_CNT * sh_stream->lc3_frame_duration_us) / USEC_PER_MSEC; +} + +size_t bap_usb_get_frame_size(const struct shell_stream *sh_stream) +{ + return USB_BYTES_PER_SAMPLE * bap_usb_get_read_cnt(sh_stream); +} + +static void stream_cb(struct shell_stream *sh_stream, void *user_data) +{ + if (sh_stream->is_tx) { + const bool has_left = + (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; + const bool has_right = + (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; + const bool has_stereo = has_right && has_left; + const bool is_mono = sh_stream->lc3_chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO; + const size_t old_write_index = POINTER_TO_UINT(user_data); + const bool overflowed = write_index < old_write_index; + size_t read_idx; + + if (has_stereo) { + /* These should always be the same */ + read_idx = MIN(sh_stream->tx.left_read_idx, sh_stream->tx.right_read_idx); + } else if (has_left || is_mono) { + read_idx = sh_stream->tx.left_read_idx; + } else if (has_right) { + read_idx = sh_stream->tx.right_read_idx; + } else { + /* Not a valid USB stream */ + return; + } + + /* If we are overwriting data that the stream is currently pointing to, then we + * need to update the index so that the stream will point to the oldest valid data + */ + if (read_idx > old_write_index) { + if (read_idx < write_index || (overflowed && read_idx < write_index)) { + sh_stream->tx.left_read_idx = write_index; + sh_stream->tx.right_read_idx = write_index; + } + } + } +} + +static void usb_data_received_cb(const struct device *dev, struct net_buf *buf, size_t size) +{ + const size_t old_write_index = write_index; + static size_t cnt; + int16_t *pcm; + + if (buf == NULL) { + return; + } + + if (size != USB_STEREO_FRAME_SIZE) { + net_buf_unref(buf); + + return; + } + + pcm = (int16_t *)buf->data; + + /* Split the data into left and right as LC3 uses LLLLRRRR instead of LRLRLRLR as USB + * + * Since the left and right buffer sizes are a factor of USB_SAMPLE_CNT, then we can always + * add USB_SAMPLE_CNT in a single go without needing to check the remaining size as that + * can be done once afterwards + */ + for (size_t i = 0U, j = 0U; i < USB_SAMPLE_CNT; i++, j += USB_CHANNELS) { + usb_in_left_ring_buffer[write_index + i] = pcm[j]; + usb_in_right_ring_buffer[write_index + i] = pcm[j + 1]; + } + + write_index += USB_SAMPLE_CNT; + + if (write_index == USB_IN_RING_BUF_SIZE) { + /* Overflow so that we start overwriting oldest */ + write_index = 0U; + } + + /* Update the read pointers of each stream to ensure that the new write index is not larger + * than their read indexes + */ + bap_foreach_stream(stream_cb, UINT_TO_POINTER(old_write_index)); + + if ((++cnt % bap_get_stats_interval()) == 0U) { + LOG_DBG("USB Data received (count = %d)", cnt); + } + + net_buf_unref(buf); +} + +bool bap_usb_can_get_full_sdu(struct shell_stream *sh_stream) +{ + const bool has_left = (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; + const bool has_right = + (sh_stream->lc3_chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; + const bool has_stereo = has_right && has_left; + const bool is_mono = sh_stream->lc3_chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO; + const uint32_t read_cnt = bap_usb_get_read_cnt(sh_stream); + const uint32_t retrieve_cnt = read_cnt * sh_stream->lc3_frame_blocks_per_sdu; + static bool failed_last_time; + size_t read_idx; + size_t buffer_cnt; + + if (has_stereo) { + /* These should always be the same */ + read_idx = MIN(sh_stream->tx.left_read_idx, sh_stream->tx.right_read_idx); + } else if (has_left || is_mono) { + read_idx = sh_stream->tx.left_read_idx; + } else if (has_right) { + read_idx = sh_stream->tx.right_read_idx; + } else { + return false; + } + + if (read_idx <= write_index) { + buffer_cnt = write_index - read_idx; + } else { + /* Handle the case where the read spans across the end of the buffer */ + buffer_cnt = write_index + (USB_IN_RING_BUF_SIZE - read_idx); + } + + if (buffer_cnt < retrieve_cnt) { + /* Not enough for a frame yet */ + if (!failed_last_time) { + LOG_WRN("Ring buffer (%u/%u) does not contain enough for an entire SDU %u", + buffer_cnt, USB_IN_RING_BUF_SIZE, retrieve_cnt); + } + + failed_last_time = true; + + return false; + } + + failed_last_time = false; + + return true; +} + +/** + * Reads @p size octets from src, handling wrapping and returns the new idx + * (which is lower than @p idx in the case of wrapping) + * + * bap_usb_can_get_full_sdu should always be called before this to ensure that we are getting + * valid data + */ +static size_t usb_ring_buf_get(int16_t dest[], int16_t src[], size_t idx, size_t cnt) +{ + size_t new_idx; + + if (idx >= USB_IN_RING_BUF_SIZE) { + LOG_ERR("Invalid idx %zu", idx); + + return 0; + } + + if ((idx + cnt) < USB_IN_RING_BUF_SIZE) { + /* Simply copy of the data and increment the index*/ + memcpy(dest, &src[idx], cnt * USB_BYTES_PER_SAMPLE); + new_idx = idx + cnt; + } else { + /* Handle wrapping */ + const size_t first_read_cnt = USB_IN_RING_BUF_SIZE - idx; + const size_t second_read_cnt = cnt - first_read_cnt; + + memcpy(dest, &src[idx], first_read_cnt * USB_BYTES_PER_SAMPLE); + memcpy(&dest[first_read_cnt], &src[0], second_read_cnt * USB_BYTES_PER_SAMPLE); + + new_idx = second_read_cnt; + } + + return new_idx; +} + +void bap_usb_get_frame(struct shell_stream *sh_stream, enum bt_audio_location chan_alloc, + int16_t buffer[]) +{ + const bool is_left = (chan_alloc & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; + const bool is_right = (chan_alloc & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; + const bool is_mono = chan_alloc == BT_AUDIO_LOCATION_MONO_AUDIO; + const uint32_t read_cnt = bap_usb_get_read_cnt(sh_stream); + + if (is_left || is_mono) { + sh_stream->tx.left_read_idx = usb_ring_buf_get( + buffer, usb_in_left_ring_buffer, sh_stream->tx.left_read_idx, read_cnt); + } else if (is_right) { + sh_stream->tx.right_read_idx = usb_ring_buf_get( + buffer, usb_in_right_ring_buffer, sh_stream->tx.right_read_idx, read_cnt); + } +} +#endif /* CONFIG_BT_AUDIO_TX */ int bap_usb_init(void) { const struct device *hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0)); static const struct usb_audio_ops usb_ops = { +#if defined(CONFIG_BT_AUDIO_RX) .data_request_cb = usb_data_request_cb, .data_written_cb = usb_data_written_cb, +#endif /* CONFIG_BT_AUDIO_RX */ +#if defined(CONFIG_BT_AUDIO_TX) + .data_received_cb = usb_data_received_cb, +#endif /* CONFIG_BT_AUDIO_TX */ }; int err; From afa56ff1029af0a2dc545ebc5eb318ca28916ae9 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0604/1389] dts/arm/st: wl: change cpu0 compatible to arm,cortex-m4 The STM32WL SoC has a Cortex M4 CPU without FPU. Change the cpu0 compatible string accordingly. Signed-off-by: Aurelien Jarno --- dts/arm/st/wl/stm32wl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index a6611b8ef1b226..9ef2a41969a678 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -29,7 +29,7 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "arm,cortex-m4f"; + compatible = "arm,cortex-m4"; reg = <0>; cpu-power-states = <&stop0 &stop1 &stop2>; }; From c2ac882b3dfabdc8eddc24d24d9d8a7b19f28db4 Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0605/1389] toolchain: llvm: Allow TLS when using llvm targeting arm TLS for Arm targets seems to be well supported in clang/lld, so mark it as supported by the toolchain. Signed-off-by: Jonathon Penix --- cmake/toolchain/llvm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/toolchain/llvm/Kconfig b/cmake/toolchain/llvm/Kconfig index 1886f50cfe51db..50293b2d61e1cd 100644 --- a/cmake/toolchain/llvm/Kconfig +++ b/cmake/toolchain/llvm/Kconfig @@ -19,7 +19,7 @@ config LLVM_USE_LLD endchoice config TOOLCHAIN_LLVM_SUPPORTS_THREAD_LOCAL_STORAGE - depends on RISCV + depends on RISCV || ARM def_bool y select TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE From 21accb023b4fe3e6a5bd05a5ff9f8403daccb2df Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0606/1389] doc: clarify what a subsystem is Clarify what a subsystem is, this has been missing the docs. Signed-off-by: Anas Nashif --- doc/glossary.rst | 4 ++++ doc/introduction/index.rst | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/doc/glossary.rst b/doc/glossary.rst index 240727d9e24388..e9e892320c44f9 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -140,6 +140,10 @@ Glossary of Terms A number of different :term:`SoCs ` that share similar characteristics and features, and that the vendor typically names and markets together. + subsystem + A subsystem refers to a logically distinct part of the operating system + that handles specific functionality or provides certain services. + system power state System power states describe the power consumption of the system as a whole. System power states are represented by :c:enum:`pm_state`. diff --git a/doc/introduction/index.rst b/doc/introduction/index.rst index f8b841ae300222..af67331aa29911 100644 --- a/doc/introduction/index.rst +++ b/doc/introduction/index.rst @@ -23,6 +23,14 @@ The Zephyr kernel supports multiple architectures, including: The full list of supported boards based on these architectures can be found :ref:`here `. +In the context of the Zephyr OS, a :term:`subsystem` refers to a logically distinct +part of the operating system that handles specific functionality or provides +certain services. Subsystems can include components such as networking, +file systems, device driver classes, power management, and communication protocols, +among others. Each subsystem is designed to be modular and can be configured, +customized, and extended to meet the requirements of different embedded +applications. + Licensing ********* From 9154d89f6cb322a8553afa8d591f59fcbc6ffe9e Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0607/1389] Bluetooth: CAP: Fix check for volume_mute_changed callback The callback was guarded by a wrong check. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/cap_commander.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/audio/cap_commander.c b/subsys/bluetooth/audio/cap_commander.c index f7c05a4e55f5ea..7a9c1663594d1c 100644 --- a/subsys/bluetooth/audio/cap_commander.c +++ b/subsys/bluetooth/audio/cap_commander.c @@ -410,7 +410,7 @@ static void cap_commander_proc_complete(void) } break; case BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE: - if (cap_cb->volume_changed != NULL) { + if (cap_cb->volume_mute_changed != NULL) { cap_cb->volume_mute_changed(failed_conn, err); } break; From 762100c80aba01a1a58f2dfc56f1aeba367e2285 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0608/1389] manifest: update hal_nordic revision to have nrfx 3.5.0 Updated hal_nordic revision brings nrfx 3.5.0 release, that contain MDK 8.64.0, AUXPLL HAL and TWIM/RRAMC driver fixes. Signed-off-by: Nikodem Kastelik --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 825f15f4c4d261..0beadf4237d144 100644 --- a/west.yml +++ b/west.yml @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: bdef8b66d5f59d95c09889918a04ddaecce322c8 + revision: a3aacc7e43dec644a9ddfee4aa578a4f8ff54610 path: modules/hal/nordic groups: - hal From 3740f1238227772a8b8360e2b6d66d8fd117d8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0609/1389] drivers: udc_dwc2: Submit reset after chirp sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DWC USB 2.0 HS OTG Controller sets USB Reset interrupt after Reset signalling starts, but before the High-Speed Detection Handshake. This allows software to perform most of the reset handling even before the connection speed is known. The device controller indicates High-Speed Detection Handshake result is available in DSTS register by setting Enumeration Done interrupt. USB stack expects that the connection speed is known immediately after UDC_EVT_RESET is submitted. Due to this expectation, it is important to submit UDC_EVT_RESET only after Enumeration Done interrupt to prevent the USB stack from reading (and storing) actual device speed before it is known. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 8f5547d36c79a4..ea9dc2da7a4246 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -865,13 +865,13 @@ static void udc_dwc2_isr_handler(const struct device *dev) sys_write32(USB_DWC2_GINTSTS_USBRST, gintsts_reg); dwc2_on_bus_reset(dev); LOG_DBG("USB Reset interrupt"); - udc_submit_event(dev, UDC_EVT_RESET, 0); } if (int_status & USB_DWC2_GINTSTS_ENUMDONE) { /* Clear and handle Enumeration Done interrupt. */ sys_write32(USB_DWC2_GINTSTS_ENUMDONE, gintsts_reg); dwc2_handle_enumdone(dev); + udc_submit_event(dev, UDC_EVT_RESET, 0); } if (int_status & USB_DWC2_GINTSTS_USBSUSP) { From c91986ffe8186acc176c076081d6dff2d7bfeae5 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0610/1389] soc: nordic: add `vpr_launcher` in sysbuild `SB_CONFIG_VPR_LAUNCHER` can now be used in building a VPR target, to enable automatic building of image that will launch the VPR. Signed-off-by: Marcin Szymczyk --- soc/nordic/Kconfig.sysbuild | 4 ++++ soc/nordic/common/vpr/Kconfig.sysbuild | 11 +++++++++ soc/nordic/sysbuild.cmake | 31 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 soc/nordic/Kconfig.sysbuild create mode 100644 soc/nordic/common/vpr/Kconfig.sysbuild create mode 100644 soc/nordic/sysbuild.cmake diff --git a/soc/nordic/Kconfig.sysbuild b/soc/nordic/Kconfig.sysbuild new file mode 100644 index 00000000000000..f146dac821e100 --- /dev/null +++ b/soc/nordic/Kconfig.sysbuild @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +rsource "common/vpr/Kconfig.sysbuild" diff --git a/soc/nordic/common/vpr/Kconfig.sysbuild b/soc/nordic/common/vpr/Kconfig.sysbuild new file mode 100644 index 00000000000000..84fbad22f26ef3 --- /dev/null +++ b/soc/nordic/common/vpr/Kconfig.sysbuild @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config VPR_LAUNCHER + bool "VPR launcher" + default y + depends on (SOC_NRF54H20_CPUPPR || SOC_NRF54L15_ENGA_CPUFLPR) + help + Include VPR launcher in build. + VPR launcher is a minimal sample built for an ARM core that starts given VPR core. + It is based on samples/basic/minimal with an appropriate snippet. diff --git a/soc/nordic/sysbuild.cmake b/soc/nordic/sysbuild.cmake new file mode 100644 index 00000000000000..03db1a5ad18e41 --- /dev/null +++ b/soc/nordic/sysbuild.cmake @@ -0,0 +1,31 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_VPR_LAUNCHER) + set(launcher_core "cpuapp") + string(REPLACE "/" ";" launcher_quals ${BOARD_QUALIFIERS}) + list(LENGTH launcher_quals launcher_quals_len) + list(GET launcher_quals 1 launcher_soc) + list(GET launcher_quals 2 launcher_vpr) + + string(REPLACE "cpu" "" launcher_vpr ${launcher_vpr}) + + if(launcher_quals_len EQUAL 4) + list(GET launcher_quals 3 launcher_variant) + set(launcher_vpr ${launcher_vpr}-${launcher_variant}) + endif() + + string(CONCAT launcher_board ${BOARD} "/" ${launcher_soc} "/" ${launcher_core}) + + set(image "vpr_launcher") + + ExternalZephyrProject_Add( + APPLICATION ${image} + SOURCE_DIR ${ZEPHYR_BASE}/samples/basic/minimal + BOARD ${launcher_board} + ) + + string(CONCAT launcher_snippet "nordic-" ${launcher_vpr}) + + sysbuild_cache_set(VAR ${image}_SNIPPET APPEND REMOVE_DUPLICATES ${launcher_snippet}) +endif() From b5251b4e97659b51877000bf4bdb2002736fec4f Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0611/1389] tests: drivers: Update uart_elementary suite with different configuration Conigure UART to use 2 stop bits and even parity in 'dual transmission' case to cover more driver code cases. Signed-off-by: Bartosz Miller --- tests/drivers/uart/uart_elementary/src/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/drivers/uart/uart_elementary/src/main.c b/tests/drivers/uart/uart_elementary/src/main.c index df8c7b54b10209..da8fa4f6690ae3 100644 --- a/tests/drivers/uart/uart_elementary/src/main.c +++ b/tests/drivers/uart/uart_elementary/src/main.c @@ -233,15 +233,15 @@ ZTEST(uart_elementary, test_uart_dual_port_transmission) { int err; struct uart_config test_uart_config = { .baudrate = 115200, - .parity = UART_CFG_PARITY_NONE, - .stop_bits = UART_CFG_STOP_BITS_1, + .parity = UART_CFG_PARITY_EVEN, + .stop_bits = UART_CFG_STOP_BITS_2, .data_bits = UART_CFG_DATA_BITS_8, .flow_ctrl = UART_CFG_FLOW_CTRL_NONE }; #if defined(CONFIG_SETUP_MISMATCH_TEST) struct uart_config test_uart_config_aux = { .baudrate = 9600, - .parity = UART_CFG_PARITY_NONE, - .stop_bits = UART_CFG_STOP_BITS_1, + .parity = UART_CFG_PARITY_EVEN, + .stop_bits = UART_CFG_STOP_BITS_2, .data_bits = UART_CFG_DATA_BITS_8, .flow_ctrl = UART_CFG_FLOW_CTRL_NONE }; #endif From 5084ab9001cf1db751d788fd5838b36076cf69ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0612/1389] samples: sensor: qdec: Run sample on nrf54h20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlay file that enables sample on nrf54h20 Application core. Signed-off-by: Sebastian Głąb --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 43 +++++++++++++++++++ samples/sensor/qdec/sample.yaml | 2 + 2 files changed, 45 insertions(+) create mode 100644 samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..748e06aef83583 --- /dev/null +++ b/samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,43 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + qdec0 = &qdec130; + qenca = &phase_a; + qencb = &phase_b; + }; + + encoder-emulate { + compatible = "gpio-leds"; + phase_a: phase_a { + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + phase_b: phase_b { + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + qdec_pinctrl: qdec_pinctrl { + group1 { + psels = , + ; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&qdec130 { + status = "okay"; + pinctrl-0 = <&qdec_pinctrl>; + pinctrl-names = "default"; + steps = <120>; + led-pre = <500>; +}; diff --git a/samples/sensor/qdec/sample.yaml b/samples/sensor/qdec/sample.yaml index 8982dfccd33db2..52e19e8bb1861f 100644 --- a/samples/sensor/qdec/sample.yaml +++ b/samples/sensor/qdec/sample.yaml @@ -22,10 +22,12 @@ tests: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp harness_config: fixture: gpio_loopback type: multi_line From 0565bfb8646c4d1839da91c3547c717630f2b8b2 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0613/1389] posix: env: Fix 2 build warnings Fix 2 build warnings in posix/options/env: The maximum length given to strncpy() matches the input string length, which makes the call equivalent to strcpy(). As the destination buffer size has been ensured sufficient (in the first case by chechking just before, in the second case by allocating it big enough), let's just use strcpy() instead. lib/posix/options/env.c: In function 'getenv_r': lib/posix/options/env.c:109:17: error: 'strncpy' specified bound depends on the length of the source argument [-Werror=stringop-truncation] 109 | strncpy(buf, val, vsize); | ^~~~~~~~~~~~~~~~~~~~~~~~ lib/posix/options/env.c:104:25: note: length computed here 104 | vsize = strlen(val) + 1; | ^~~~~~~~~~~ lib/posix/options/env.c: In function 'setenv': lib/posix/options/env.c:191:17: error: 'strncpy' output truncated before terminating nul copying as many bytes from a string as its length [-Werror=stringop-truncation] 191 | strncpy(environ[ret], name, nsize); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lib/posix/options/env.c:128:51: note: length computed here 128 | const size_t nsize = (name == NULL) ? 0 : strlen(name); | ^~~~~~~~~~~~ Signed-off-by: Alberto Escolar Piedras --- lib/posix/options/env.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/posix/options/env.c b/lib/posix/options/env.c index 2607ae2a4be85c..56d3b4ae5430e8 100644 --- a/lib/posix/options/env.c +++ b/lib/posix/options/env.c @@ -106,7 +106,7 @@ int getenv_r(const char *name, char *buf, size_t len) ret = -ERANGE; K_SPINLOCK_BREAK; } - strncpy(buf, val, vsize); + strcpy(buf, val); LOG_DBG("Found entry %s", environ[ret]); } @@ -188,7 +188,7 @@ int setenv(const char *name, const char *val, int overwrite) environ[ret] = env; } - strncpy(environ[ret], name, nsize); + strcpy(environ[ret], name); environ[ret][nsize] = '='; strncpy(environ[ret] + nsize + 1, val, vsize + 1); LOG_DBG("Added entry %s", environ[ret]); From 4f4b3e978fd4c3b2ce3052b9f2bf6619c310ff18 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0614/1389] pinctrl: npcx: add nodes for Serial Port SIO clock selection This commits adds required pinctrl node to provide the corresponding SIO clock selection for the Serial Port under the different VOSCCLK. Signed-off-by: Jun Lin --- dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi | 16 ++++++++++++++++ dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi | 8 ++++++++ dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi | 8 ++++++++ 3 files changed, 32 insertions(+) diff --git a/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi index af45fa59ddb082..ec9979c707725a 100644 --- a/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi @@ -30,6 +30,22 @@ dev-ctl = <0x0 6 1 0x01>; }; + /omit-if-no-ref/ sio_clk_sel_96m: devctl3-sio-clk_sel-96m { + dev-ctl = <0x4 6 2 0x00>; + }; + + /omit-if-no-ref/ sio_clk_sel_100: devctl3-sio-clk_sel-100m { + dev-ctl = <0x4 6 2 0x01>; + }; + + /omit-if-no-ref/ sio_clk_sel_120m: devctl3-sio-clk_sel-120m { + dev-ctl = <0x4 6 2 0x02>; + }; + + /omit-if-no-ref/ sio_clk_sel_90m: devctl3-sio-clk_sel-90m { + dev-ctl = <0x4 6 2 0x03>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ /* Flash Interface Unit (FIU) */ /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { diff --git a/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi index 2b219c48edecbd..35a40411835d4d 100644 --- a/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi @@ -22,6 +22,14 @@ dev-ctl = <0x0 6 1 0x01>; }; + /omit-if-no-ref/ sio_full_ck48: devctl4-sio-full-ck48 { + dev-ctl = <0x6 3 1 0x00>; + }; + + /omit-if-no-ref/ sio_full_ck50: devctl4-sio-full-ck50 { + dev-ctl = <0x6 3 1 0x01>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ /* Flash Interface Unit (FIU) */ /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { diff --git a/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi index 2ba0b78fdda299..583b5352fad7de 100644 --- a/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi @@ -23,6 +23,14 @@ dev-ctl = <0x0 6 1 0x01>; }; + /omit-if-no-ref/ sio_full_ck48: devctl4-sio-full-ck48 { + dev-ctl = <0x6 3 1 0x00>; + }; + + /omit-if-no-ref/ sio_full_ck50: devctl4-sio-full-ck50 { + dev-ctl = <0x6 3 1 0x01>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ /* Flash Interface Unit (FIU) */ /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { From c1ca43831dbc42f8eeb41eba4ae985ee55d56035 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0615/1389] driver: espi: npcx: enable the Serial Port Initialize and enable the Serial Port/Host UART when CONFIG_ESPI_PERIPHERAL_UART=y. Signed-off-by: Jun Lin --- drivers/espi/host_subs_npcx.c | 38 ++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/espi/host_subs_npcx.c b/drivers/espi/host_subs_npcx.c index 41810666604a67..51802586c8c9e1 100644 --- a/drivers/espi/host_subs_npcx.c +++ b/drivers/espi/host_subs_npcx.c @@ -191,6 +191,7 @@ struct host_sub_npcx_data host_sub_data; #define NPCX_C2H_TRANSACTION_TIMEOUT_US 200 /* Logical Device Number Assignments */ +#define EC_CFG_LDN_SP 0x03 #define EC_CFG_LDN_MOUSE 0x05 #define EC_CFG_LDN_KBC 0x06 #define EC_CFG_LDN_SHM 0x0F @@ -205,6 +206,13 @@ struct host_sub_npcx_data host_sub_data; #define EC_CFG_IDX_DATA_IO_ADDR_H 0x62 #define EC_CFG_IDX_DATA_IO_ADDR_L 0x63 +/* LDN Activation Enable */ +#define EC_CFG_IDX_CTRL_LDN_ENABLE 0x01 + +/* Index of SuperI/O Control and Configuration Registers */ +#define EC_CFG_IDX_SUPERIO_SIOCF9 0x29 +#define EC_CFG_IDX_SUPERIO_SIOCF9_CKEN 2 + /* Index of Special Logical Device Configuration (Shared Memory Module) */ #define EC_CFG_IDX_SHM_CFG 0xF1 #define EC_CFG_IDX_SHM_WND1_ADDR_0 0xF4 @@ -217,6 +225,11 @@ struct host_sub_npcx_data host_sub_data; #define EC_CFG_IDX_SHM_WND2_ADDR_3 0xFB #define EC_CFG_IDX_SHM_DP80_ADDR_RANGE 0xFD +/* Index of Special Logical Device Configuration (Serial Port/Host UART) */ +#define EC_CFG_IDX_SP_CFG 0xF0 +/* Enable selection of bank 2 and 3 for the Serial Port */ +#define EC_CFG_IDX_SP_CFG_BK_SL_ENABLE 7 + /* Host sub-device local inline functions */ static inline uint8_t host_shd_mem_wnd_size_sl(uint32_t size) { @@ -995,10 +1008,10 @@ void npcx_host_init_subs_host_domain(void) * modules by setting bit 0 in its Control (index is 0x30) reg. */ host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_KBC); - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_MOUSE); - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); } if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_HOST_IO)) { @@ -1007,7 +1020,7 @@ void npcx_host_init_subs_host_domain(void) * module by setting bit 0 in its Control (index is 0x30) reg. */ host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_ACPI); - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); } if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) || @@ -1028,7 +1041,7 @@ void npcx_host_init_subs_host_domain(void) (CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM + 4) & 0xff); #endif /* Enable 'Host Command' io port (PM Channel 2) */ - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); /* Select 'Shared Memory' bank which LDN are 0x0F */ host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_SHM); @@ -1053,8 +1066,23 @@ void npcx_host_init_subs_host_domain(void) host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_DP80_ADDR_RANGE, 0x0f); } /* Enable SHM direct memory access */ - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); } + + if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_UART)) { + /* Select Serial Port banks which LDN are 0x03. */ + host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_SP); + /* Enable SIO_CLK */ + host_c2h_write_io_cfg_reg(EC_CFG_IDX_SUPERIO_SIOCF9, + host_c2h_read_io_cfg_reg(EC_CFG_IDX_SUPERIO_SIOCF9) | + BIT(EC_CFG_IDX_SUPERIO_SIOCF9_CKEN)); + /* Enable Bank Select */ + host_c2h_write_io_cfg_reg(EC_CFG_IDX_SP_CFG, + host_c2h_read_io_cfg_reg(EC_CFG_IDX_SP_CFG) | + BIT(EC_CFG_IDX_SP_CFG_BK_SL_ENABLE)); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); + } + LOG_DBG("Hos sub-modules configurations are done!"); } From d736d374aa57dd82cd6d4333625e12a3dd13821e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0616/1389] net: http: Make sure not use undefined Kconfig symbols If CONFIG_HTTP_SERVER is not enabled, then we must not use Kconfig symbols that are only available when HTTP server is enabled. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/hpack.h | 8 +++++++- include/zephyr/net/http/server.h | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/zephyr/net/http/hpack.h b/include/zephyr/net/http/hpack.h index 374b083ce091a1..35bfa49189f130 100644 --- a/include/zephyr/net/http/hpack.h +++ b/include/zephyr/net/http/hpack.h @@ -94,6 +94,12 @@ enum http_hpack_static_key { /* TODO Kconfig */ #define HTTP2_HEADER_FIELD_MAX_LEN 256 +#if defined(CONFIG_HTTP_SERVER) +#define HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE CONFIG_HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE +#else +#define HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE 0 +#endif + /** HTTP2 header field with decoding buffer. */ struct http_hpack_header_buf { /** A pointer to the decoded header field name. */ @@ -109,7 +115,7 @@ struct http_hpack_header_buf { size_t value_len; /** Encoding/Decoding buffer. Used with Huffman encoding/decoding. */ - uint8_t buf[CONFIG_HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE]; + uint8_t buf[HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE]; /** Length of the data in the decoding buffer. */ size_t datalen; diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index c11dc8b2caa434..d493e5b3251eb5 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -28,9 +28,17 @@ extern "C" { /** @cond INTERNAL_HIDDEN */ -#define HTTP_SERVER_CLIENT_BUFFER_SIZE CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE -#define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS +#if defined(CONFIG_HTTP_SERVER) +#define HTTP_SERVER_CLIENT_BUFFER_SIZE CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE +#define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS #define HTTP_SERVER_MAX_CONTENT_TYPE_LEN CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH +#define HTTP_SERVER_MAX_URL_LENGTH CONFIG_HTTP_SERVER_MAX_URL_LENGTH +#else +#define HTTP_SERVER_CLIENT_BUFFER_SIZE 0 +#define HTTP_SERVER_MAX_STREAMS 0 +#define HTTP_SERVER_MAX_CONTENT_TYPE_LEN 0 +#define HTTP_SERVER_MAX_URL_LENGTH 0 +#endif /* Maximum header field name / value length. This is only used to detect Upgrade and * websocket header fields and values in the http1 server so the value is quite short. @@ -297,10 +305,10 @@ struct http_client_ctx { struct http_parser parser; /** Request URL. */ - unsigned char url_buffer[CONFIG_HTTP_SERVER_MAX_URL_LENGTH]; + unsigned char url_buffer[HTTP_SERVER_MAX_URL_LENGTH]; /** Request content type. */ - unsigned char content_type[CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH]; + unsigned char content_type[HTTP_SERVER_MAX_CONTENT_TYPE_LEN]; /** Temp buffer for currently processed header (HTTP/1 only). */ unsigned char header_buffer[HTTP_SERVER_MAX_HEADER_LEN]; From 2c6405b5b00eef8d467c084c330ac7298e521577 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0617/1389] net: shell: Add command to show HTTP server information The new command is "net http" which shows all services and related resources defined in the system. Signed-off-by: Jukka Rissanen --- subsys/net/lib/shell/CMakeLists.txt | 1 + subsys/net/lib/shell/http.c | 98 +++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 subsys/net/lib/shell/http.c diff --git a/subsys/net/lib/shell/CMakeLists.txt b/subsys/net/lib/shell/CMakeLists.txt index 5cfb5c269b44ce..ea310b5fc71b1b 100644 --- a/subsys/net/lib/shell/CMakeLists.txt +++ b/subsys/net/lib/shell/CMakeLists.txt @@ -14,6 +14,7 @@ zephyr_library_sources(dhcpv4.c) zephyr_library_sources(dns.c) zephyr_library_sources(events.c) zephyr_library_sources(gptp.c) +zephyr_library_sources(http.c) zephyr_library_sources(iface.c) zephyr_library_sources(ipv4.c) zephyr_library_sources(ipv6.c) diff --git a/subsys/net/lib/shell/http.c b/subsys/net/lib/shell/http.c new file mode 100644 index 00000000000000..72c7b61506fe36 --- /dev/null +++ b/subsys/net/lib/shell/http.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(net_shell); + +#include "net_shell_private.h" +#include +#include +#include +#include + +#define IS_BIT_SET(val, bit) (((val >> bit) & (0x1)) != 0) + +static int cmd_net_http(const struct shell *sh, size_t argc, char *argv[]) +{ +#if defined(CONFIG_HTTP_SERVER) + int res_count = 0, serv_count = 0; + + PR("%-15s\t%-12s\n", + "Host:Port", "Concurrent/Backlog"); + PR("\tResource type\tMethods\t\tEndpoint\n"); + + HTTP_SERVICE_FOREACH(svc) { + PR("\n"); + PR("%s:%d\t%zu/%zu\n", + svc->host == NULL || svc->host[0] == '\0' ? + "" : svc->host, svc->port ? *svc->port : 0, + svc->concurrent, svc->backlog); + + HTTP_SERVICE_FOREACH_RESOURCE(svc, res) { + struct http_resource_detail *detail = res->detail; + const char *detail_type = ""; + int method_count = 0; + bool print_comma; + + switch (detail->type) { + case HTTP_RESOURCE_TYPE_STATIC: + detail_type = "static"; + break; + case HTTP_RESOURCE_TYPE_DYNAMIC: + detail_type = "dynamic"; + break; + case HTTP_RESOURCE_TYPE_WEBSOCKET: + detail_type = "websocket"; + break; + } + + PR("\t%12s\t", detail_type); + + print_comma = false; + + for (int i = 0; i < NUM_BITS(uint32_t); i++) { + if (IS_BIT_SET(detail->bitmask_of_supported_http_methods, i)) { + PR("%s%s", print_comma ? "," : "", http_method_str(i)); + print_comma = true; + method_count++; + } + } + + if (method_count < 2) { + /* make columns line up better */ + PR("\t"); + } + + PR("\t%s\n", res->resource); + res_count++; + } + + serv_count++; + } + + if (res_count == 0 && serv_count == 0) { + PR("No HTTP services and resources found.\n"); + } else { + PR("\n%d service%sand %d resource%sfound.\n", + serv_count, serv_count > 1 ? "s " : " ", + res_count, res_count > 1 ? "s " : " "); + } + +#else /* CONFIG_HTTP_SERVER */ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + PR_INFO("Set %s to enable %s support.\n", + "CONFIG_HTTP_SERVER", + "HTTP information"); +#endif + + return 0; +} + +SHELL_SUBCMD_ADD((net), http, NULL, + "Show HTTP services.", + cmd_net_http, 1, 0); From 988f74c865985c4cd7ca47300cfc4af75df9d2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:38:58 +0200 Subject: [PATCH 0618/1389] samples: subsys: settings: Run sample on nrf54h20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Kconfig file that makes the sample working on nrf54h20 Application core. Signed-off-by: Sebastian Głąb --- samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf | 2 ++ samples/subsys/settings/sample.yaml | 1 + 2 files changed, 3 insertions(+) create mode 100644 samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf diff --git a/samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000000..3746c13c741b08 --- /dev/null +++ b/samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,2 @@ +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y diff --git a/samples/subsys/settings/sample.yaml b/samples/subsys/settings/sample.yaml index 3ab57ee0923c4b..e4a9e148c5a1d9 100644 --- a/samples/subsys/settings/sample.yaml +++ b/samples/subsys/settings/sample.yaml @@ -13,6 +13,7 @@ tests: - native_sim/native/64 - mr_canhubk3 - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - native_sim harness: console From 227591956b66840c2b5b52e971f9d5d600abc0d5 Mon Sep 17 00:00:00 2001 From: Trung Hieu Le Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0619/1389] boards: nxp: rt1170_evk: Add XMCD bootheader Currently, only DCD bootheader was supported to configure the SDRAM. On IMX RT1170, XMCD can be used as an alternative boot header to DCD. XMCD is more advanced than DCD and enhances SDRAM access speed. This is benefit for SDRAM access application. Signed-off-by: Trung Hieu Le --- boards/nxp/mimxrt1170_evk/CMakeLists.txt | 12 ++++++------ soc/nxp/imxrt/CMakeLists.txt | 4 ++++ soc/nxp/imxrt/Kconfig | 19 +++++++++++++++++++ soc/nxp/imxrt/boot_header.ld | 4 ++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/boards/nxp/mimxrt1170_evk/CMakeLists.txt b/boards/nxp/mimxrt1170_evk/CMakeLists.txt index c564e77e49273c..e87e07401d077f 100644 --- a/boards/nxp/mimxrt1170_evk/CMakeLists.txt +++ b/boards/nxp/mimxrt1170_evk/CMakeLists.txt @@ -28,16 +28,16 @@ if(CONFIG_NXP_IMXRT_BOOT_HEADER) zephyr_library_sources(${RT1170_BOARD_DIR}/xip/${RT1170_BOARD_NAME}_flexspi_nor_config.c) zephyr_library_include_directories(${RT1170_BOARD_DIR}/xip) endif() - if(CONFIG_DEVICE_CONFIGURATION_DATA) - # Include device configuration data block for RT1170 EVK from NXP's HAL. + if(CONFIG_EXTERNAL_MEM_CONFIG_DATA) + # Include external memory configuration data block for RT1170 EVK from NXP's HAL. # This configuration block may need modification if another SDRAM chip # is used on your custom board. - zephyr_compile_definitions(XIP_BOOT_HEADER_DCD_ENABLE=1) - zephyr_library_sources(${RT1170_BOARD_DIR}/dcd.c) + zephyr_compile_definitions(XIP_BOOT_HEADER_XMCD_ENABLE=1) + zephyr_library_sources(${RT1170_BOARD_DIR}/xmcd/xmcd.c) else() if(CONFIG_SRAM_BASE_ADDRESS EQUAL 0x80000000) - message(WARNING "You are using SDRAM as RAM but no device " - "configuration data (DCD) is included. This configuration may not boot") + message(WARNING "You are using SDRAM as RAM but no external memory" + "configuration data (XMCD) is included. This configuration may not boot") endif() endif() endif() diff --git a/soc/nxp/imxrt/CMakeLists.txt b/soc/nxp/imxrt/CMakeLists.txt index 25cd1b81554513..b42829869e4f60 100644 --- a/soc/nxp/imxrt/CMakeLists.txt +++ b/soc/nxp/imxrt/CMakeLists.txt @@ -13,6 +13,9 @@ if(CONFIG_SOC_SERIES_IMXRT10XX OR CONFIG_SOC_SERIES_IMXRT11XX) if(CONFIG_DEVICE_CONFIGURATION_DATA) set(boot_hdr_dcd_data_section ".boot_hdr.dcd_data") endif() + if(CONFIG_EXTERNAL_MEM_CONFIG_DATA) + set(boot_hdr_xmcd_data_section ".boot_hdr.xmcd_data") + endif() zephyr_sources(mpu_regions.c) zephyr_linker_section_configure( SECTION .rom_start @@ -26,6 +29,7 @@ if(CONFIG_SOC_SERIES_IMXRT10XX OR CONFIG_SOC_SERIES_IMXRT11XX) INPUT ".boot_hdr.ivt" ".boot_hdr.data" ${boot_hdr_dcd_data_section} + ${boot_hdr_xmcd_data_section} OFFSET ${CONFIG_IMAGE_VECTOR_TABLE_OFFSET} KEEP PRIO 11 diff --git a/soc/nxp/imxrt/Kconfig b/soc/nxp/imxrt/Kconfig index ce96362b49d6bb..2ab29a50ce61f7 100644 --- a/soc/nxp/imxrt/Kconfig +++ b/soc/nxp/imxrt/Kconfig @@ -114,6 +114,25 @@ config DEVICE_CONFIGURATION_DATA initialized at boot time. +config EXTERNAL_MEM_CONFIG_DATA + bool "External Memory Configuration Data" + depends on !DEVICE_CONFIGURATION_DATA + help + External memory configuration data (XMDC) provides an alternative + configuration sequences which allows to intilialize the external memory + at the boot time. This sequence allows to configure + external memories (such as SDRAM) with more advanced option. + This is a new alternative boot header compared to DCD, and DCD must be disabled + in order to select this option. + +config EXTERNAL_MEM_CONFIG_OFFSET + hex "External memory configuration offset" + depends on EXTERNAL_MEM_CONFIG_DATA + default 0x1040 if BOOT_FLEXSPI_NOR || BOOT_SEMC_NOR + help + As specified by the boot ROM, the External Memory configuration data must be + placed in a specific address location to be pointed by the boot ROM. + endif # NXP_IMXRT_BOOT_HEADER config NXP_IMX_EXTERNAL_SDRAM diff --git a/soc/nxp/imxrt/boot_header.ld b/soc/nxp/imxrt/boot_header.ld index e46fa5789e340e..b96e5e58b3f273 100644 --- a/soc/nxp/imxrt/boot_header.ld +++ b/soc/nxp/imxrt/boot_header.ld @@ -18,4 +18,8 @@ KEEP(*(.boot_hdr.data)) #ifdef CONFIG_DEVICE_CONFIGURATION_DATA KEEP(*(.boot_hdr.dcd_data)) #endif /* CONFIG_DEVICE_CONFIGURATION_DATA */ +#ifdef CONFIG_EXTERNAL_MEM_CONFIG_DATA + . = CONFIG_EXTERNAL_MEM_CONFIG_OFFSET; + KEEP(*(.boot_hdr.xmcd_data)) +#endif #endif /* CONFIG_SOC_SERIES_IMXRT10XX || CONFIG_SOC_SERIES_IMXRT11XX */ From 85f9bc23bfbddede7e7322ec6a74ebaae03c7a15 Mon Sep 17 00:00:00 2001 From: Trung Hieu Le Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0620/1389] boards: nxp: rt1170_evk: Enable XMCD as bootheader by default Configure to use XMCD as the bootheader by default instead of DCD. As XMCD gives a better SDRAM memory access speed. As an example, the Pixel Processing Pipeline is 13 ms faster with XMCD compared to DCD as the bootheader. Signed-off-by: Trung Hieu Le --- boards/nxp/mimxrt1170_evk/Kconfig.defconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/nxp/mimxrt1170_evk/Kconfig.defconfig b/boards/nxp/mimxrt1170_evk/Kconfig.defconfig index 395d8351794c16..a54b1b8a145f82 100644 --- a/boards/nxp/mimxrt1170_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1170_evk/Kconfig.defconfig @@ -5,8 +5,8 @@ if BOARD_MIMXRT1170_EVK -# Only use DCD when booting primary core (M7) -config DEVICE_CONFIGURATION_DATA +# Use External Memory Configuration Data (XMCD) by default when booting primary core (M7) +config EXTERNAL_MEM_CONFIG_DATA default y if CPU_CORTEX_M7 config NXP_IMX_EXTERNAL_SDRAM From 4a1a91b0f12289f770e9619354f388f1f2a2f8de Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0621/1389] xtensa: mmu: Simplify memory map Simplify the logic around the shared attribute. Checks if a memory region should be shared only in the function that actually maps the memory. Signed-off-by: Flavio Ceolin --- arch/xtensa/core/ptables.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index 0628879d93302c..ceb840ba1ff917 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -214,9 +214,10 @@ static inline uint32_t *alloc_l2_table(void) } static void map_memory_range(const uint32_t start, const uint32_t end, - const uint32_t attrs, bool shared) + const uint32_t attrs) { uint32_t page, *table; + bool shared = !!(attrs & XTENSA_MMU_MAP_SHARED); for (page = start; page < end; page += CONFIG_MMU_PAGE_SIZE) { uint32_t pte = XTENSA_MMU_PTE(page, @@ -245,18 +246,18 @@ static void map_memory_range(const uint32_t start, const uint32_t end, } static void map_memory(const uint32_t start, const uint32_t end, - const uint32_t attrs, bool shared) + const uint32_t attrs) { - map_memory_range(start, end, attrs, shared); + map_memory_range(start, end, attrs); #ifdef CONFIG_XTENSA_MMU_DOUBLE_MAP if (sys_cache_is_ptr_uncached((void *)start)) { map_memory_range(POINTER_TO_UINT(sys_cache_cached_ptr_get((void *)start)), POINTER_TO_UINT(sys_cache_cached_ptr_get((void *)end)), - attrs | XTENSA_MMU_CACHED_WB, shared); + attrs | XTENSA_MMU_CACHED_WB); } else if (sys_cache_is_ptr_cached((void *)start)) { map_memory_range(POINTER_TO_UINT(sys_cache_uncached_ptr_get((void *)start)), - POINTER_TO_UINT(sys_cache_uncached_ptr_get((void *)end)), attrs, shared); + POINTER_TO_UINT(sys_cache_uncached_ptr_get((void *)end)), attrs); } #endif } @@ -270,24 +271,14 @@ static void xtensa_init_page_tables(void) for (entry = 0; entry < ARRAY_SIZE(mmu_zephyr_ranges); entry++) { const struct xtensa_mmu_range *range = &mmu_zephyr_ranges[entry]; - bool shared; - uint32_t attrs; - shared = !!(range->attrs & XTENSA_MMU_MAP_SHARED); - attrs = range->attrs & ~XTENSA_MMU_MAP_SHARED; - - map_memory(range->start, range->end, attrs, shared); + map_memory(range->start, range->end, range->attrs); } for (entry = 0; entry < xtensa_soc_mmu_ranges_num; entry++) { const struct xtensa_mmu_range *range = &xtensa_soc_mmu_ranges[entry]; - bool shared; - uint32_t attrs; - - shared = !!(range->attrs & XTENSA_MMU_MAP_SHARED); - attrs = range->attrs & ~XTENSA_MMU_MAP_SHARED; - map_memory(range->start, range->end, attrs, shared); + map_memory(range->start, range->end, range->attrs); } /* Finally, the direct-mapped pages used in the page tables @@ -297,10 +288,10 @@ static void xtensa_init_page_tables(void) */ map_memory_range((uint32_t) &l1_page_table[0], (uint32_t) &l1_page_table[CONFIG_XTENSA_MMU_NUM_L1_TABLES], - XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W, false); + XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W); map_memory_range((uint32_t) &l2_page_tables[0], (uint32_t) &l2_page_tables[CONFIG_XTENSA_MMU_NUM_L2_TABLES], - XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W, false); + XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W); sys_cache_data_flush_all(); } From 08f731deee00f4cd4e5c57c95ee1c928813ad5d3 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0622/1389] xtensa: mmu: Remove duplicated macro XTENSA_MMU_PTE was defined twice. Signed-off-by: Flavio Ceolin --- arch/xtensa/include/xtensa_mmu_priv.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/xtensa/include/xtensa_mmu_priv.h b/arch/xtensa/include/xtensa_mmu_priv.h index 631760f03cb189..2fd69c198e0b20 100644 --- a/arch/xtensa/include/xtensa_mmu_priv.h +++ b/arch/xtensa/include/xtensa_mmu_priv.h @@ -41,11 +41,6 @@ #define XTENSA_MMU_PTEBASE_MASK 0xFFC00000 -#define XTENSA_MMU_PTE(paddr, ring, attr) \ - (((paddr) & XTENSA_MMU_PTE_PPN_MASK) | \ - (((ring) << XTENSA_MMU_PTE_RING_SHIFT) & XTENSA_MMU_PTE_RING_MASK) | \ - ((attr) & XTENSA_MMU_PTE_ATTR_MASK)) - /** Number of bits to shift for PPN in PTE */ #define XTENSA_MMU_PTE_PPN_SHIFT 12U From 25056eb6f074a3ad259f8d28299bbd313a4181e4 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0623/1389] xtensa: mmu: Fix macro to get ring from a pte The macro was not masking the pte correctly and it was returning a wrong value. Signed-off-by: Flavio Ceolin --- arch/xtensa/include/xtensa_mmu_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/include/xtensa_mmu_priv.h b/arch/xtensa/include/xtensa_mmu_priv.h index 2fd69c198e0b20..af3a28057f6b11 100644 --- a/arch/xtensa/include/xtensa_mmu_priv.h +++ b/arch/xtensa/include/xtensa_mmu_priv.h @@ -71,7 +71,7 @@ /** Get the ring from a PTE */ #define XTENSA_MMU_PTE_RING_GET(pte) \ - (((pte) & ~XTENSA_MMU_PTE_RING_MASK) >> XTENSA_MMU_PTE_RING_SHIFT) + (((pte) & XTENSA_MMU_PTE_RING_MASK) >> XTENSA_MMU_PTE_RING_SHIFT) /** Get the ASID from the RASID register corresponding to the ring in a PTE */ #define XTENSA_MMU_PTE_ASID_GET(pte, rasid) \ From 35eb8b67670460f48c6842832a647324dfdc611e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0624/1389] xtensa: mmu: Avoid k_mem_domain_default duplication We can use some extra bits available for SW implementation to save original permissions and avoid duplicating the kernel page tables for the default memory domain. Whe duplicating the page table to a new domain we just ensure to restore the original map. Signed-off-by: Flavio Ceolin --- arch/xtensa/core/ptables.c | 40 ++++++++++++++++++++++----- arch/xtensa/include/xtensa_mmu_priv.h | 26 +++++++++++++++-- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index ceb840ba1ff917..1953a246124f9c 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -218,12 +218,14 @@ static void map_memory_range(const uint32_t start, const uint32_t end, { uint32_t page, *table; bool shared = !!(attrs & XTENSA_MMU_MAP_SHARED); + uint32_t sw_attrs = (attrs & XTENSA_MMU_PTE_ATTR_ORIGINAL) == XTENSA_MMU_PTE_ATTR_ORIGINAL ? + attrs : 0; for (page = start; page < end; page += CONFIG_MMU_PAGE_SIZE) { uint32_t pte = XTENSA_MMU_PTE(page, shared ? XTENSA_MMU_SHARED_RING : XTENSA_MMU_KERNEL_RING, - attrs); + sw_attrs, attrs); uint32_t l2_pos = XTENSA_MMU_L2_POS(page); uint32_t l1_pos = XTENSA_MMU_L1_POS(page); @@ -237,7 +239,7 @@ static void map_memory_range(const uint32_t start, const uint32_t end, xtensa_kernel_ptables[l1_pos] = XTENSA_MMU_PTE((uint32_t)table, XTENSA_MMU_KERNEL_RING, - XTENSA_MMU_PAGE_TABLE_ATTR); + sw_attrs, XTENSA_MMU_PAGE_TABLE_ATTR); } table = (uint32_t *)(xtensa_kernel_ptables[l1_pos] & XTENSA_MMU_PTE_PPN_MASK); @@ -272,13 +274,13 @@ static void xtensa_init_page_tables(void) for (entry = 0; entry < ARRAY_SIZE(mmu_zephyr_ranges); entry++) { const struct xtensa_mmu_range *range = &mmu_zephyr_ranges[entry]; - map_memory(range->start, range->end, range->attrs); + map_memory(range->start, range->end, range->attrs | XTENSA_MMU_PTE_ATTR_ORIGINAL); } for (entry = 0; entry < xtensa_soc_mmu_ranges_num; entry++) { const struct xtensa_mmu_range *range = &xtensa_soc_mmu_ranges[entry]; - map_memory(range->start, range->end, range->attrs); + map_memory(range->start, range->end, range->attrs | XTENSA_MMU_PTE_ATTR_ORIGINAL); } /* Finally, the direct-mapped pages used in the page tables @@ -357,7 +359,7 @@ static bool l2_page_table_map(uint32_t *l1_table, void *vaddr, uintptr_t phys, init_page_table(table, XTENSA_L2_PAGE_TABLE_ENTRIES); l1_table[l1_pos] = XTENSA_MMU_PTE((uint32_t)table, XTENSA_MMU_KERNEL_RING, - XTENSA_MMU_PAGE_TABLE_ATTR); + 0, XTENSA_MMU_PAGE_TABLE_ATTR); sys_cache_data_flush_range((void *)&l1_table[l1_pos], sizeof(l1_table[0])); } @@ -365,7 +367,7 @@ static bool l2_page_table_map(uint32_t *l1_table, void *vaddr, uintptr_t phys, table = (uint32_t *)(l1_table[l1_pos] & XTENSA_MMU_PTE_PPN_MASK); table[l2_pos] = XTENSA_MMU_PTE(phys, is_user ? XTENSA_MMU_USER_RING : XTENSA_MMU_KERNEL_RING, - flags); + 0, flags); sys_cache_data_flush_range((void *)&table[l2_pos], sizeof(table[0])); xtensa_tlb_autorefill_invalidate(); @@ -738,14 +740,25 @@ static uint32_t *dup_table(uint32_t *source_table) } for (j = 0; j < XTENSA_L2_PAGE_TABLE_ENTRIES; j++) { + uint32_t original_attr = XTENSA_MMU_PTE_SW_GET(src_l2_table[j]); + l2_table[j] = src_l2_table[j]; + if (original_attr != 0x0) { + uint8_t ring; + + ring = XTENSA_MMU_PTE_RING_GET(l2_table[j]); + l2_table[j] = XTENSA_MMU_PTE_ATTR_SET(l2_table[j], original_attr); + l2_table[j] = XTENSA_MMU_PTE_RING_SET(l2_table[j], + ring == XTENSA_MMU_SHARED_RING ? + XTENSA_MMU_SHARED_RING : XTENSA_MMU_KERNEL_RING); + } } /* The page table is using kernel ASID because we don't * user thread manipulate it. */ dst_table[i] = XTENSA_MMU_PTE((uint32_t)l2_table, XTENSA_MMU_KERNEL_RING, - XTENSA_MMU_PAGE_TABLE_ATTR); + 0, XTENSA_MMU_PAGE_TABLE_ATTR); sys_cache_data_flush_range((void *)l2_table, XTENSA_L2_PAGE_TABLE_SIZE); } @@ -772,6 +785,18 @@ int arch_mem_domain_init(struct k_mem_domain *domain) __ASSERT(asid_count < (XTENSA_MMU_SHARED_ASID), "Reached maximum of ASID available"); key = k_spin_lock(&xtensa_mmu_lock); + /* If this is the default domain, we don't need + * to create a new set of page tables. We can just + * use the kernel page tables and save memory. + */ + + if (domain == &k_mem_domain_default) { + domain->arch.ptables = xtensa_kernel_ptables; + domain->arch.asid = asid_count; + goto end; + } + + ptables = dup_table(xtensa_kernel_ptables); if (ptables == NULL) { @@ -784,6 +809,7 @@ int arch_mem_domain_init(struct k_mem_domain *domain) sys_slist_append(&xtensa_domain_list, &domain->arch.node); +end: ret = 0; err: diff --git a/arch/xtensa/include/xtensa_mmu_priv.h b/arch/xtensa/include/xtensa_mmu_priv.h index af3a28057f6b11..608cbac9c46522 100644 --- a/arch/xtensa/include/xtensa_mmu_priv.h +++ b/arch/xtensa/include/xtensa_mmu_priv.h @@ -50,10 +50,24 @@ /** Number of bits to shift for ring in PTE */ #define XTENSA_MMU_PTE_RING_SHIFT 4U +/** Number of bits to shift for SW reserved ared in PTE */ +#define XTENSA_MMU_PTE_SW_SHIFT 6U + +/** Mask for SW bits in PTE */ +#define XTENSA_MMU_PTE_SW_MASK 0x00000FC0U + +/** + * Internal bit just used to indicate that the attr field must + * be set in the SW bits too. It is used later when duplicating the + * kernel page tables. + */ +#define XTENSA_MMU_PTE_ATTR_ORIGINAL BIT(31) + /** Construct a page table entry (PTE) */ -#define XTENSA_MMU_PTE(paddr, ring, attr) \ +#define XTENSA_MMU_PTE(paddr, ring, sw, attr) \ (((paddr) & XTENSA_MMU_PTE_PPN_MASK) | \ (((ring) << XTENSA_MMU_PTE_RING_SHIFT) & XTENSA_MMU_PTE_RING_MASK) | \ + (((sw) << XTENSA_MMU_PTE_SW_SHIFT) & XTENSA_MMU_PTE_SW_MASK) | \ ((attr) & XTENSA_MMU_PTE_ATTR_MASK)) /** Get the attributes from a PTE */ @@ -62,7 +76,15 @@ /** Set the attributes in a PTE */ #define XTENSA_MMU_PTE_ATTR_SET(pte, attr) \ - (((pte) & ~XTENSA_MMU_PTE_ATTR_MASK) | (attr)) + (((pte) & ~XTENSA_MMU_PTE_ATTR_MASK) | (attr & XTENSA_MMU_PTE_ATTR_MASK)) + +/** Set the SW field in a PTE */ +#define XTENSA_MMU_PTE_SW_SET(pte, sw) \ + (((pte) & ~XTENSA_MMU_PTE_SW_MASK) | (sw << XTENSA_MMU_PTE_SW_SHIFT)) + +/** Get the SW field from a PTE */ +#define XTENSA_MMU_PTE_SW_GET(pte) \ + (((pte) & XTENSA_MMU_PTE_SW_MASK) >> XTENSA_MMU_PTE_SW_SHIFT) /** Set the ring in a PTE */ #define XTENSA_MMU_PTE_RING_SET(pte, ring) \ From c98c989efec274e87b788503d65535b2af9c3c00 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0625/1389] xtensa: mmu: dup_table does not need parameter The only page table duplicated is the kernel page table. This function does not need a parameter. Signed-off-by: Flavio Ceolin --- arch/xtensa/core/ptables.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index 1953a246124f9c..f44e17ad6a953c 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -715,7 +715,7 @@ static inline uint32_t *alloc_l1_table(void) return NULL; } -static uint32_t *dup_table(uint32_t *source_table) +static uint32_t *dup_table(void) { uint16_t i, j; uint32_t *dst_table = alloc_l1_table(); @@ -727,13 +727,13 @@ static uint32_t *dup_table(uint32_t *source_table) for (i = 0; i < XTENSA_L1_PAGE_TABLE_ENTRIES; i++) { uint32_t *l2_table, *src_l2_table; - if (is_pte_illegal(source_table[i]) || + if (is_pte_illegal(xtensa_kernel_ptables[i]) || (i == XTENSA_MMU_L1_POS(XTENSA_MMU_PTEVADDR))) { dst_table[i] = XTENSA_MMU_PTE_ILLEGAL; continue; } - src_l2_table = (uint32_t *)(source_table[i] & XTENSA_MMU_PTE_PPN_MASK); + src_l2_table = (uint32_t *)(xtensa_kernel_ptables[i] & XTENSA_MMU_PTE_PPN_MASK); l2_table = alloc_l2_table(); if (l2_table == NULL) { goto err; @@ -797,7 +797,7 @@ int arch_mem_domain_init(struct k_mem_domain *domain) } - ptables = dup_table(xtensa_kernel_ptables); + ptables = dup_table(); if (ptables == NULL) { ret = -ENOMEM; From aaf265c44e723e538a077b6a04c48ee5e9d626c3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0626/1389] samples/littlefs: Fix rcar boards selecting Flash API The rcar boards use block variant of LittleFS and Disk Access API, but have been using proj.conf for Flash API based access. The commit adds section building boards with pro_blk.conf into sample.yaml, where rcar boards will now be allowed, and removes redundant configuration lines from board specific conf files. Signed-off-by: Dominik Ermel --- ...a77951_a57.conf => rcar_h3ulcb_r8a77951_a57_blk.conf} | 8 +------- .../{rcar_salvator_xs.conf => rcar_salvator_xs_blk.conf} | 8 +------- samples/subsys/fs/littlefs/prj_blk.conf | 1 + samples/subsys/fs/littlefs/sample.yaml | 9 +++++++-- 4 files changed, 10 insertions(+), 16 deletions(-) rename samples/subsys/fs/littlefs/boards/{rcar_h3ulcb_r8a77951_a57.conf => rcar_h3ulcb_r8a77951_a57_blk.conf} (59%) rename samples/subsys/fs/littlefs/boards/{rcar_salvator_xs.conf => rcar_salvator_xs_blk.conf} (59%) diff --git a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57_blk.conf similarity index 59% rename from samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf rename to samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57_blk.conf index f2dffe4fe097a7..6b4b57ac2a0bb6 100644 --- a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf +++ b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57_blk.conf @@ -7,11 +7,5 @@ CONFIG_MAIN_STACK_SIZE=4096 CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 -CONFIG_DISK_ACCESS=y -CONFIG_DISK_DRIVERS=y CONFIG_DISK_DRIVER_MMC=y - -CONFIG_FS_LITTLEFS_BLK_DEV=y -CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y - -CONFIG_FS_LITTLEFS_FMP_DEV=n +CONFIG_DISK_DRIVER_SDMMC=n diff --git a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs_blk.conf similarity index 59% rename from samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf rename to samples/subsys/fs/littlefs/boards/rcar_salvator_xs_blk.conf index f2dffe4fe097a7..6b4b57ac2a0bb6 100644 --- a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf +++ b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs_blk.conf @@ -7,11 +7,5 @@ CONFIG_MAIN_STACK_SIZE=4096 CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 -CONFIG_DISK_ACCESS=y -CONFIG_DISK_DRIVERS=y CONFIG_DISK_DRIVER_MMC=y - -CONFIG_FS_LITTLEFS_BLK_DEV=y -CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y - -CONFIG_FS_LITTLEFS_FMP_DEV=n +CONFIG_DISK_DRIVER_SDMMC=n diff --git a/samples/subsys/fs/littlefs/prj_blk.conf b/samples/subsys/fs/littlefs/prj_blk.conf index 011f919a568084..b18b8cfe362621 100644 --- a/samples/subsys/fs/littlefs/prj_blk.conf +++ b/samples/subsys/fs/littlefs/prj_blk.conf @@ -16,6 +16,7 @@ CONFIG_FILE_SYSTEM=y CONFIG_FILE_SYSTEM_LITTLEFS=y CONFIG_FS_LITTLEFS_BLK_DEV=y +CONFIG_FS_LITTLEFS_FMP_DEV=n CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y CONFIG_NOCACHE_MEMORY=y diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index 89ffe9f16ae8d6..4c53a55d59104e 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -20,14 +20,19 @@ tests: - mimxrt1160_evk/mimxrt1166/cm7 - lpcxpresso55s69/lpc55s69/cpu0 - mr_canhubk3 - - rcar_h3ulcb/r8a77951/a57 - - rcar_salvator_xs - stm32f429i_disc1 - stm32f746g_disco - stm32h747i_disco/stm32h747xx/m7 - stm32h750b_dk integration_platforms: - nrf52840dk/nrf52840 + sample.filesystem.littlefs.blk: + build_only: true + extra_args: + - CONF_FILE=prj_blk.conf + platform_allow: + - rcar_h3ulcb/r8a77951/a57 + - rcar_salvator_xs sample.filesystem.littlefs.nrf52840dk_spi: build_only: true platform_allow: nrf52840dk/nrf52840 From 4379bf9bff3eda782bd76eeee492a0af1ccf5f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0627/1389] boards: st: Add support for STM32H745I-Disco MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supported features: - GPIO - RTC - PWM - Ethernet - UART - FMC - QSPI NOR Flash Signed-off-by: Tomáš Juřena --- boards/st/stm32h745i_disco/Kconfig.defconfig | 23 ++ .../stm32h745i_disco/Kconfig.stm32h745i_disco | 9 + .../arduino_r3_connector.dtsi | 42 +++ boards/st/stm32h745i_disco/board.cmake | 15 + boards/st/stm32h745i_disco/board.yml | 5 + .../doc/img/stm32h745i-disco.jpg | Bin 0 -> 92684 bytes boards/st/stm32h745i_disco/doc/index.rst | 272 ++++++++++++++++++ .../st/stm32h745i_disco/stm32h745i_disco.dtsi | 50 ++++ .../stm32h745i_disco_stm32h745xx_m4.dts | 38 +++ .../stm32h745i_disco_stm32h745xx_m4.yaml | 17 ++ .../stm32h745i_disco_stm32h745xx_m4_defconfig | 21 ++ .../stm32h745i_disco_stm32h745xx_m7.dts | 269 +++++++++++++++++ .../stm32h745i_disco_stm32h745xx_m7.yaml | 23 ++ .../stm32h745i_disco_stm32h745xx_m7_defconfig | 28 ++ .../st/stm32h745i_disco/support/openocd.cfg | 30 ++ 15 files changed, 842 insertions(+) create mode 100644 boards/st/stm32h745i_disco/Kconfig.defconfig create mode 100644 boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco create mode 100644 boards/st/stm32h745i_disco/arduino_r3_connector.dtsi create mode 100644 boards/st/stm32h745i_disco/board.cmake create mode 100644 boards/st/stm32h745i_disco/board.yml create mode 100644 boards/st/stm32h745i_disco/doc/img/stm32h745i-disco.jpg create mode 100644 boards/st/stm32h745i_disco/doc/index.rst create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco.dtsi create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml create mode 100644 boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig create mode 100644 boards/st/stm32h745i_disco/support/openocd.cfg diff --git a/boards/st/stm32h745i_disco/Kconfig.defconfig b/boards/st/stm32h745i_disco/Kconfig.defconfig new file mode 100644 index 00000000000000..b6242139bfdfed --- /dev/null +++ b/boards/st/stm32h745i_disco/Kconfig.defconfig @@ -0,0 +1,23 @@ +# STM32H745XI DISCOVERY board configuration + +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STM32H745I_DISCO + +if NETWORKING + +config NET_L2_ETHERNET + default y + +config ETH_STM32_HAL_MII + default y + +endif # NETWORKING + +config MEMC + default y if DISPLAY + + +endif # BOARD_STM32H745I_DISCO diff --git a/boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco b/boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco new file mode 100644 index 00000000000000..7dacd75eb4bae2 --- /dev/null +++ b/boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco @@ -0,0 +1,9 @@ +# STM32H745XI DISCOVERY board configuration + +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32H745I_DISCO + select SOC_STM32H745XX_M7 if BOARD_STM32H745I_DISCO_STM32H745XX_M7 + select SOC_STM32H745XX_M4 if BOARD_STM32H745I_DISCO_STM32H745XX_M4 diff --git a/boards/st/stm32h745i_disco/arduino_r3_connector.dtsi b/boards/st/stm32h745i_disco/arduino_r3_connector.dtsi new file mode 100644 index 00000000000000..4ad2396a16210f --- /dev/null +++ b/boards/st/stm32h745i_disco/arduino_r3_connector.dtsi @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioc 0 0>, /* A0 */ + <1 0 &gpiof 8 0>, /* A1 */ + <2 0 &gpioa 0 0>, /* A2 */ + <3 0 &gpioa 1 0>, /* A3 */ + <4 0 &gpioc 2 0>, /* A4 */ + <5 0 &gpioc 3 0>, /* A5 */ + <6 0 &gpiob 7 0>, /* D0 */ + <7 0 &gpiob 6 0>, /* D1 */ + <8 0 &gpiog 3 0>, /* D2 */ + <9 0 &gpioa 6 0>, /* D3 */ + <10 0 &gpiok 1 0>, /* D4 */ + <11 0 &gpioa 8 0>, /* D5 */ + <12 0 &gpioe 6 0>, /* D6 */ + <13 0 &gpioi 6 0>, /* D7 */ + <14 0 &gpioe 3 0>, /* D8 */ + <15 0 &gpioh 15 0>, /* D9 */ + <16 0 &gpiob 4 0>, /* D10 */ + <17 0 &gpiob 15 0>, /* D11 */ + <18 0 &gpioi 2 0>, /* D12 */ + <19 0 &gpiod 3 0>, /* D13 */ + <20 0 &gpiod 13 0>, /* D14 */ + <21 0 &gpiod 12 0>; /* D15 */ + }; +}; + + +arduino_i2c: &i2c1 {}; + +arduino_serial: &usart1 {}; diff --git a/boards/st/stm32h745i_disco/board.cmake b/boards/st/stm32h745i_disco/board.cmake new file mode 100644 index 00000000000000..699e51ae5959fc --- /dev/null +++ b/boards/st/stm32h745i_disco/board.cmake @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena + +board_runner_args(jlink "--device=STM32H745XI" "--speed=4000") +if(CONFIG_BOARD_STM32H745I_DISCO_STM32H745XX_M7) +board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) +elseif(CONFIG_BOARD_STM32H745I_DISCO_STM32H745XX_M4) +board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) +endif() +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/stm32h745i_disco/board.yml b/boards/st/stm32h745i_disco/board.yml new file mode 100644 index 00000000000000..e1da9c4b2f44e5 --- /dev/null +++ b/boards/st/stm32h745i_disco/board.yml @@ -0,0 +1,5 @@ +board: + name: stm32h745i_disco + vendor: st + socs: + - name: stm32h745xx diff --git a/boards/st/stm32h745i_disco/doc/img/stm32h745i-disco.jpg b/boards/st/stm32h745i_disco/doc/img/stm32h745i-disco.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2e5d12d5c5118ec96f134354448fc69430a066a GIT binary patch literal 92684 zcmc$_cT^N#vnV^8MipKYwoaT2oy?`K3JY00hDt1Odm5Cm@jHdv{k&#b>Pg28OJl|8~5waC81|m;Vj| zW1LNafL{=3oKM63Cegn)_`kTm?FzgQXoCdKd)EKJcm#jpxBmgt{e`{Uo!tRkdH=!| z&aQvqCjd<9s;&7PfL{VItMz|_-~Kn)(#p*OXyX91G5Z&7PMIK(#0dz5AN#L+Z<9cv z`Y;fPZsA||*t0+&@(>WHZv0>Oj@AF67mudX-O3xl1q6B}@D$|y#`Vo#7=#a;H{QJi zfsP75pgRU25Y-3>L~QgQc>L3X&<&XAf1v;GesJ@k=OFwWH~#(u2LbR;c#DvbfPj#g zi0I}mQesk45@HgPJ7ko1?~qZDk&xV_xl2KHkD8jAl$@51<{lm8J?eXZ2f@P!`VbJ_ zCM3Ll?+(eGd;gCQTsw&37TzqrK0e+9&A9n{hB$?4fS`r`60U3eh;{~+tXDEl|MC;+-{5D?%K5dEbK z?}is};!_Y1-WR+{`Ba1GjSJNSp^vxjJ&Vn%?6}P)tcj$4>pDtI!!EMQf%;3@Ka~C7 zBP{5DMA?54_Ak2TK&1G10Q2xEKoHQiR(9k=(Et2=x%Po3^5ORz|8+hRenKLD?=_x0 zr#$_4!t8jF8jyxOrwyJ>Zhy{$k0vDYoGz+QI{&NrfA9Lg;eUqUwCVq+`#WI#mt!M% z|BU%}-2Z>h8!U-ikb4jtXc+Y7+9HDd-pn=?^+H`~uWBe!76q#S%->?E&G)(m;#i5K zeJMwUEUg?w7&UaMN_O3m6T2#)W9?UDWeFzOdH@%ZW5KYXKVQ8@M;_|LD3`y9)0|G( zEE4wd8#b;S@I0eG@A0icCKQc$ms-icO4+%@fy|(mKIN@;r)?FVU?O#gI1u^!R@nF* zJuGn!GO*VxW^UYcg8CJ~s8MJ562kvG)?7yb?R(w{yTnI_VXx3WWQbV zE^{tWve~}Wf7!B1{z*W+AlFHS9J&ApA~-`?hwSCUkr^fAk!3l9qD8R&run@_?yZ@- z>Tis_{kKA0sCDS3r<*rb4{Zfn_Dd41-M{ZB+iv_^UML@~#er6Lmx&>N$k)JE=T10K zUm*?@R^k5;2l@^PhaN7%aUhn8KBLb*j@EJX2=8~%kut82bQOpQ?)u*K)Al&Cf7mJN zp1I_IUf;vF6L{-7=Kt)TgJo$&=3qZy@8dvlPaFv23um&|Qb(58me_jvCdR;^eg%e> z#->K|GGDqvc)c3v%o3;uwso#y!G_J(8&WfQIFJB@Ah4|q2O`u*8@UO|lLfCCjq{?(0%wyj=K{4(~b`ZawMmjZTll?ql^RPFL91*)Tj)@OQ1kY7;FMC4*~5cZ7~#)r{qRl`GCO4^+D3ZUKW%N9VrKl6Dc@4n_z^in#3M#s8CBtw z1&Be{yc|7rq;gFilZXQ$CQ%7y1ho|r5m^4s;}Wp8X)h1t2ktFnJ? zptvjT8QsVlKfk%J@^E!pl#jjtSkcLim%_N_DF>r|A@BFt-;(qavUfbj+E=U(I6Uho z(;rtv)>UI@FTk~Jx33#pBvJUv zG@tpj&QZ{*g{{oCKs#nr6sqyK>Zl;#bGq#h?8=g$X7LE518tjpoXWGnX7E-O2Pg- z0uoy0L)&xvK8ioa@x|GYeX)M)5z8%Zf=DX`t&FWKrgyE3Se71SgU5)BA`awl1VznZ z4kpTE^p`38!G0{M*12|U&#=SQ$(k*y;raT!Mt*XV(NUT=*w}a)B}EY_)1PY9$!#yK zHnZL*jqGUL-cJ~&k43QF-F)1WaQ7+Uhhc|F-ewYU&-!EWg7EJ8GWm11(`hVAAF=@l z`UPKuTx|lnGiD4}6f22B=A3GDDd^MBcMrb099D&&yNFTLA#;nL-jZibHyM8Jojg? z46XnCja9CiXmPaZ&)*7nd!!cC7|FlQ6da7nV3zk?QV#iLK+BXEjkRdDjtoZRb$)EN z*-Jf5y)>Ho7|lYGmQt|mN_t8Be3{W8@-<9mTy-KWygM%t+5yf6BhLgvmQMuGFziJg zpbKiC|2_>{>B%Af0&6@UbM2c%L&M7E?PBK{O<25YQ_QE5DSfPmeeU7&ItzS@5qFle zJ9dgl{QI(2}df9ao#_k|RXVoLQJPYB@NozPe_-?9j0k z2dXXIf9J$a|En~f-(aTT=S_tJ;S8QyF!}VFXGPhJH{>aDqsdnMc!2bEDoo7JJJ$m* z*GHu)5tL@0A!yig(~MEFCvS%;pYc{l*073 zm>}ePSoZB4mD;fyD5-bdou`vowMN;8x9Z8X2JY|(E_FNy;hnDQ#iNJ26g!rNA4eVPH16+gkV$E(;_6k8vy zVPNCgEH9t?wv$Y>oKB=cx~YgZS$hb5Jo^fgXBG#tF$?yE1h+jvKPnS-G+05g#E|ZL z$!HD|KP$RtQyxx>ccbFfBmz;mVk0?{3-`@lkN5R4F0sg?7O=JQb7+Az)Htt9*y76lap-K!1pQaG;MoI8gWWhFSOS!y4G#>!77gze3h0 zG^%M%TWKuP?&Z&aIT;>yY`F7`6lmr;%&E<$xfaDlr3I9Xp204_)hPm)dj%a>R%;p- zCV0a`JO^V|eA$~y_*_KzMI9xISYj>Y&YhdbT8*O~i*>^CPTon|Bt8P1*TH-b;?tw& zquk6Az{Dr1%z@LdW3UGYlMmdjuGm1ol-L>|>(e9f+gM_6)m|Kk*kj+TTPmhm$c}~e zu53t1_v`yd&j}L0#nwNjRPiH&GN4K{vO>Fcqpj?mH>&m8nwKvXPI6$GY&zwO*q_@4 z7JGsKd-TvRA)Dj?Z&82UxFYE4uGwuk;Me`7Moy08(VSM)*}%5x z;n^#y1aUHAtq(uNbSs!ANkuN>QoACWrPjj zODQZ)8&2B5Xc*j@i4I$CC{u8kv5ya!0~n6UC9H zn*B%ju2F+oHKYBvxHDy?7clG8BuPoI(8mGxlX89Ys+}($4;GUyzYbDIMM_P2xL4r>XnczVpPSr-whCFh+tXygBzndQg3tH5^+6w|5W+Vit z@~cof=JC~v=~TjOaiI0WYe36|6=OI7M_Ml&2Ra=3>q!Hya0xOM`_YsQa1F)&afJmi zgf@W>y+eB(W%yRp#d!QaeJY4`ecKpkvC+r)?!6B{>yh+HDU8Wvcy*ZRj@WL8FLT*c zvWIB3kx_@shN+n6n~z_UKrv#m!)}H+(7Tn!Mu)>4mU(&%4s^i{(E-fT4jd2!YQQia z|8EEX-|?#WB*%swkYlSy``9CH)hr7A#*QujZbfb;=P&gB$$H-CIwmYO`bCLYcDKJq zmIq67ATmVTImh|gXS2I4gce+m^FsA`* z$^UmIXaH(P2dxIEnTo&mAQg(0HA^;}inm^^Ao9-X3Vev%4~4A_agqk*N6n~6LU_yj(o zgkEh!dXup%^2lIpkU9<&z=fV(iw=$TD7L4$G|7GIw;M4vN7qG2&L%cVFM-b<^NMGr z0(--IiKkVQCt;kU?MI`k%!|`tz~I5)R~(JSC`#H3g`4 z0H}`jX9dIzpnq8zE9wNqAweM+-sw|mN9k9MDaWrHU8q}Yoak(gk#{NEEw8@tpn?sM z;t}qLgf>fD6OJqc=u44;Nv7Ws+u3a~5Ru5(xRdMTZ~DNSYYqG$9^ zO4%4;{mB|vfA+Yz*37Sq#)h6AKpZ%Y*1{4SAP0NpSZl_3-4|W>`Nd<|QS+rX6!f!S zFA6~1g4=U7@YQwjO~@Z99O!%--U;V|SPc^ouE8RXYJ5MAza4i^-QA7Q#1ny$$Gvrr zru$&>X@&qPbsVK@)|VNQ1R-wGE10v@J7)-uFWMg2(XH@d$VHVTX)%3#MZ&}8D#6Cg zLz}ch4J}zbHoS_~?v-ftQj8S})Ued_04w7C8NkQ%fC;Wg>ml+o zJ8>XdJC=K&4eG`$Qxy_qwjU_dzb)=zP)n^3Ss*@OBM1)eC>y;s+ ztJ?lrfLazs8?CCAJlq;T9qg}gq&%D39D8Ue`Sxu)MUy;R!kZu>6$})uwW5wT$h=!) zc877apbyG(n?I8F2%&B5de1}p^@{IWv(p@Y$Jr%W@`{>5=h-FVWy84D_`c(*w0q>v zqGP`K^8^kf&Sy`VR#r|*IX<*MtIFcMNNF+~6VvRKI4(}{WjpEmn*&J2epuoF1cBzS z;sXTXywm9tA8<}EfU|+x!Pw_TGbrlF^Z#2kmsDs=fuRbI(u-S_1i2C9X*>wg+!J-`=Oo-0+ z%dlBIT!>xheb@A6=IcjBH|!`_GT7=2CY34XYf86UI9O7lcq>_?qw;- z;+0>ouNR5C$emso4vbOHmK@65Ks&Dh>71iG-f0`6+)3a@r3A35i#~g#+5je0aXB zO)S^+HmYU-9F-lFYP6E2ry);&KTJLWFGJ$ZFj4TL)@_9{aG7~AcfwTxboW@&#BRn8 zuGjlK$;|8Y0_;30Prbps`u`@$W?=dVMIc9wTq-IxzA>V2IOxGjL{R+5;*xl>9E=FV z#Nt2-3 zzG{BFb%g^xl)!;LBvp*VNcH;)z3Y|gzXon>Ep$!W@Di;(srZU$N_6o_0`q>Zq0~K% zuf>{e25{XTD+p`X?y2<&j4(q@BdMMsX(MIi85S9Dx$hEf$W03xw>dyGdtf28`Phb5*M>G(I!xu0{TBP5Ars9!%O=N0}q6c}uhr&f0+r&5;S z;rY0YHXuw59kyCOalp^_R(zD+s@B@TT&;_r*uSH4oGGUEm-Ka*^PRT+wyP~^*(Y*s z`K?^5nIADGfG^_BqZdG9M1OdybTi$f#HhdSsPf_?yX#W|rkI7O>4dS*n(=^K7=BY2 zYKH7;cGJ+(@-#_&7ART)|89*xGfWv&LWdMC*}dMbGU~{$LlisC(h0wy?_JTmPh!cE z!^#w^j=ocdW>lz|4vPvLK8w)Noh;8;2xV?5b`EriQ=h5~WYD*1s*e`!@UhAp&WV;= z)0Wz+>buioYDehbOLB0_IhV9Z8b&PdeNXt&+U``>tMmk2Sb1<#*kopP&vkT0BT8Dk z1?B7Q_0)-?PcD@vDI}+%c@|dV+-#}e^(OgXV?H?6jB?(jC)Z!wKH30UV;*eyuG!@4 z@q{rm!WN4hCYowBdWKvI{%&kPM|+ll{Cr1#jMh=%@Ej?nu=CP$=f>UKn_eKQ?I5Cf zBX8H;ZaIjb>MeE(^`fs+dS8CUhNjx^J^Z~QeBO)|)i$BiE6(8?lls2C-6L9{xNw!+ zxm;ZzB;YSuU~Fo0cWGIjz;!?xsb3ZPM}paA}dtJ80oV&RX5&6Hz_(L-CuQT=;F zla*0N62E@qen{EdqkBY@auY@8T%980mHpcm9kp6dF z8n``KF}v7j%er^cPpK5Vq~hLj^e6BzL2tK%#sAExXqKp?D@ux6xvf`HMOjJoioe?W zY9q%hM~WKTZMr$?Ve7%3)SN|5Gp0|Tu!68XD@W*F=eM!#1S>)2-wo6Zu*Y#$*DHx1 za=A8WgqkYNN4fV)P_GNh7B+k=*Dg=vy1A++NpalKC+!wBmEY=>V`4XW9e&S%7YrBV ze{d{(w13`fKbL4lyhEdIb)M!#GNd-y*5_l5NL>zZyZ@sK#gcqoW?^sdb-#AZQCHG3 zd9UG0m71q9ERjl>>Sy1@3i_~T&MO=v`h7OnH>5YG;5l_eTce+AG-Y?mMxl~UyC&%M z!TQ4+*=R?eg2Mg3(cd~ie zNDZlb{o8M@4ok8|t@x~)Qq`fYP)3GhycJd`g1a`p;k1I!e{Af%Bf6hTXEF=qiC$*# zjCerrdPBQZ{AG)c%yyc78XGE$70Epr&xIw+ho=qHOS?YZ?s0v)^-A-z^JdebMLyqR zgY1}0*BUg64W(PZ!mN96z*D9)ds`I3q2u2;uhAHrm>9S{_tV*@gSu!994(%~gbItu z8d(WdlXHY>0&$me^oN9>J#23qbTvQs6ChtX-zv?F6jtMk#&D0%|E^~-qG!*1e-(-y zYm$5SbW2ufMv~=gnP3T;WqyqdRx3b1vuH=_x>N6Bxczbyk4mKcWt9}w@uPNPA*tiB znuIKF-`<^hs&`|J3;u%WjEo1<7AWd0LD^S3OJg?OM}3a@ixCHRAFucq_b6&U z3nhKZqJ~=2uL$I{V@RwKG@99Qc@DK^(p@8c`rxKoKm8B%)xwdhv#?2D2mU=Xr+CHc zhKV?4%LUt`B&A$ERgyY+UFX>Z%g35xl`omRjt`?QqkC%+^RtKUyU|=4L3CvYh&Fd& zb?%3{iFKex2kQ++mmsOJJdA32ub^2=C2i-v=CaC!jKXoV!Wi01BZ#sxnN#62u>=v* zxeW1{?DMn2+KF1>HNZV0P>{Q?DBDsu9h;uy;_##@a0M^(ar7@T-!zu5D8N{r-*GHL zhv#bkGU{pyddo^SVgafgV8Tl~KNCF(gSD8Dg(2?Smf9xQ%ZY{_2;ZzR6UY}kJmsMu zaDIX>cYSqa!KJ1hWld(kT-I#1ewkjmRlQ*yg6``+Yl3$Rgc+t9cgSp87Yr0K>JR}A zpp93o%Jr!*wx9hrwu>U zD;4;8_ar#e|9rgkz?P9-{i|>xLDbe3BvMyv#$SGVt+B4ICb2xljB|+oJ|5O%hA}<& zF`I0(pHn;RBmlqr+?00gR2m23$EyD@e(F%IR+|$dMmJcH8h!Cl3FLpR+oHOb-%1|Q z#=2{m*qYZ9Ajl^x7jJ%(<~7Z!_?Z~R`;^3LF%hsw@L?I@i^MKGN{!8 zAy9pY?p`UBoR>?m?5w*7VN_>}S^B{U4xuhC7F;Ozd23gzUwpJ%wh}9IX62 z=k}uLEnlnru+$nkr(VR4LTP2x5dqN7AMnsO$YBiIrGu^Qo!WsGzI**~MLv&(JRJ~B zOk44$clix`1*vzN-Y2fWA|Ur#1S|^dXj435a{2ZTMON+jemOB0hf(}AN%&?J{Xt@v z(`ByFZY1Z|?qsARkLj>ei)4wxQ{f2_r`fGeQvs7##~RZD0ta)VjX?)fmkUNc4sSnQ z#5?L*ed#|c?yL72IL14NaUtLzmS{%XWW4pdeAzF{0I58s4L4n6D?Pk*yl!w~fPq>f zf&xv%2xQuJDnyrw{ckh{zl>AUQ;0+DwLB+`(o~bIZ;aT0IeZeaTJw0_!DPMpTdCJ} z89Tbfgz^{;aT0ZWcCsU7GSiYGE7hy&y=g(&yAp^D;rJLEbIbpWHhv!;aV@uk=p*p~ zM~XoMojggdvKSQ;t}X_y54DbZU0%s4>fw5tepWx=P0?LX=pN3pv~M7vQ?7#6@60@C zf`-6ZYQY2;<_Uk%LbT9)cN3FTm5Fj8)MmhzS4)MiSn#zg<6u0p|D=rkwl_K8NHf-| zGomvNu-NT`(;}$Pd%0h{aW9Ue%2>ek{4+}(o}CwxY%Io3{(^6iXGcG$wH)Y%;G3$w z7+acie05~h7s~mzGTC+hsmzKs^{Bt7fxmPf`sW7g@gcNoRji((likRG20PjvqjaIS zF`u!~erSx2=WJ3ZGgWq4tzgJD9CTs2e5NQ8`-QM6plLKJI%D>Ai{(b2!*q#2=wSc) zWsgBKGc+7-V=J1-P%1_-?_Ig#XDje&cb&lICvz-NO+>@iFl^X?hM;uX=(gv2<9$es z{}@(Am*<44#f3hfRBz~)#Co$eOt*1hr0UTo&=tsDbF`LXeTr?(q5+GeIcEEQ}NeuW^@>9)OWTpClj+K?F-H$it8=#lHTx$h) z!)vWSx5$52FX&9t75AbTaFo4ndr|Qo_31Gpe{|rqqhrXYqDR)gE8_twEhRbB{d}y{ ziS5{_EJcGg@?AnQ_p=H{CB$4aIO4Levt;N|%^|sst8Mjs-P_3|6lZL#1?&Cj$8h1* zde?Sq$!!z$*&$8MJikB|__)w|N^3E+g9k&0&ZF(T;?t9#Jdwc2uR5Bn#U1s$pPPF< znik9yd=Nh_(a-$YJ{n~fo!|zt-uT<9c#j00`(JwrLMEEylN}Jee`EhoDHTEf zkk#FEMID$1997%8plefd>s50$WpCCRQ*ElD)7Jl8R(E;N$`-}TC{&FG=}lqy(Zq!bSdQ`kjPah zkAw46k)jM^=){Po>eDct4~V8&R<9Z>bNp^gd5aR2JImf6=>Tro;)_J3MPAaby(&J3 zlZdKD6Dc)RBWo8+xgD)C*T*f5u78EUdfA?&@x@j6w>0LD@{li`K~YalS>Y!md7bu02Gd8YBg#C#HA44?IipR$vK2>6D*dSTa{ zsHrn`E5`Ppo9?l9`^VY+EV@@;t)T~o!E(?}K70Nw_Cu7k{PEgD&Fu|1#{jeTb*A%t zt)j$!)LO%zH49j7$um@2N)GpgiKJ_FIXY=>vabVv$85nZw2WwY-R%*VI?J`lwd!cqD zhhAX1dvi4^rZyGn*S>UbLXI76xZIt=Jz5*Ue{iI<{=?{V_~(8~^@mD_4BU$BpBds9 zC0x?nV4mpARkNGk^@OV7fdfhB009$bOdXvouAn>xLen zYVk#5)t1Vl9z&ihsreSGJmRS0C~2-9hg-v$?Bs5uKblQT_%qaajaJpz=oOC1HudA3afpA0?HYmP6D!oO6%k454O3sQ~i?3@xhi#|7PMw zE=vqjw4XRy=%XuWs>^N1z2TkCc2iMxM*?L40vOr1k@5#|YA1CAJc4{e<&PUpvJ&18NHXaP@A4nIR-gj+KTX}7 z(tT_e%j-8lvlXMA^seK=wXd;kk&Dagg2@XDYzp^xpzRSQu+Sx`QH-jiJ@sCSf9dAj zJMO9+Hnt+R*u;1Adp?^@nb8nROH^$|D6jd*`x8FO&NYk$-q2?)m9-N?-c z5ewFwR^+xkT2T)j!%&YOa#W5oc134L)ZS51wFw;IdK}Ll?QZld#yxdiNgJea^Oj^q zoZN$*Cb{o2d}J`!X|p$@eEa1a51znn?yxny#;g!&wBxfPCXPo+RB25nwdWE97^_G8 zPqM#fL~YpbX3prX)Rwmfcpw%H7x~|eZ(WI{6AU(z&XA79E)=qod!AK%=~KBDzW!|S zA@KJS__2kXy1P~1IcAdy3)1Uz!M-uVk5iqImWq4rG?2f%Z0|puwVK8!^XhGDHk{k_ zqJ-nzbZeA_8u=~{VH6SA+1%~DD4dxPC|XwH&w+9Z%Mn*|BFnRZ`|!@x6v}#Lw#X)P z&9z#rM0ujnl=A~XddMpNHxA_I(ub93I-dh%yDL*CW>`?f zMXTV|PeDh+`5E*TATMxwZ{IDINxtj}k>>s=t!Ie)BQeXbzQ-uCBwlzS97(jVzsbqA zh|y9iiotxS&oVt?Ol2Y-I0Zf?ZxFpaMp3DSDWgKO2%A2Id{w#U$t$#sMscAkhQR2D z;lWs1nurY?s2tn-c?if>S2I*u7+?^veva5T&)GM6E8%{@h^{(E&4+pZ8WKo~ZS)KLd?NW|*4Zve1@5eLk zFf-ES7EaJp@K3+pl#nGp$(kL>BkcS?E$aL~v$S5+UH&eJmGfwr)1K<`_1)7vNVIR- zOy-LEXl4+Uw2ghipB>$mhb~_v&FR@xaGua`#bN@!J7ezpl2%1n_L= zGD=%VTPH3p8BQdsL%Gt&3nDv3N}d{-NG6@Z6*89cTOet?btgL|oyz{{^$-W3SRq}(n}Ze;kF+HSl(Qe~sDe(S2t6{mctqr3@s z9}tQ(;JisE_3CW0ZT|oV8vNPUjzCrY5~Qr)u-|Kb@XUTPkaV{Y%Y>p0H9fVkA2}bL zD@&_V+9xdC(^rc7{+gCGRF6)wkLef(!pA(aK)|9{?vB(x3>+<3-nmVRT#w!kQtIDI z)0=LBg_i{~d#^$9|76^(ZWf-u{%+X&qcem9mPq8J_9-~Ne`T}eao>1X;DO5d#HzN5 zlLw0l0!lGs_NNUr?xFTfpXycfcs7c9L37aQEMRKmI{^;l%_Av9ytjO`$4=fnfuKIfH<1n8>bP?Y+RFD4Xy_s2o%%YY>nSo!CHhAs-SS-U zC)V$)&@g#viFz~c5x;1nEaO*fd`FtB1nX_w?8iK6;F zC@$ERTmQIYos@~8Xf1&AV7X&1($3Hd<27dI;6BS%7on5&N=aIqQrn4(iPSCfGNk2A zS^8BV)gQz!JTvjLK4*LoI63Wx;>egh0&;i0CYrXhl|d}t^C)?$y>4S}7LgY8^puFY zs;^6RX#09aU-=|bMsdZ?U!p2<%mo-&ab$KXn|EicK^~l8QQ>Bw9JGmSPdR=y;<2c5oPR9E2ock zvRXBHu01v0O{+2c;tNexdU;EN!m*?TfiR}^#`<}edxc69a=4>=I%UyATS{||Hf2Xv zBSn9G$-gyHh)xKWT4Z)m?kf9E?YRN3ia#CF6{a9oaH$QQlVjaSI(2--f$Hscd|DXc zyEqVN%bTITbvPBHr{z)6qT&8AKVsnD?(aa z^8WCxW^qNFY#*EqY{pG=WjmT|lI5CEZ;lij0<900tclWJ-*dRckKbs$x%CVkP=pTcS1q*_n@jAjuo+n_ zn6tq1q^Iv}dzscx9rc0op80yMFZn#i0C-(y`||nDJPs6@b7juU;h}NI~p5S|Iw@_^m}vWQ4FJt^RIH{)o>wU zN^hC73f(rOSs2EvTz2vL_qS|2;hlG?pC6SXXx%pTLvf%u^Qf5dN-I1ie72~RgP2;x z13@6O0&fR)+Bc^$cKC(pUum#VIU?{`?>q+B0kVIdje)M*St-r{qi9t1u{1WjR%av< zhy2;i8B@K~+DYn`xB z=Rg5Vj}Grr%J$!B<(H6()s<627DT>pxnHR6VSA>G9d+W!9Wg2R#uO{jRb=L}U_M=G z?ER?RD$J}o{-vXex8sVG<=K1iaIA$hT(;j$;P5e-OUR(Z%~t6v#a{S{nhZG(6zB*? z7gzGb5!)NbR%nlvB97l)EuI_IQPv!-VH?VuKLQ{WEz}DBgMc!m{N^9v$QM&)Tlh4O zueCLCv9&&)xK!T?kN)eIisrbX=5nP6trliTvamIEN>gLwwnPgzvMkx}K z&AkzFQwoj^I>dc09nxxE@VO;vEO{8q&8W)@nq`cRgq<8v+MeyTVs>?Ej}=*RB#T^z zpb1p*boPdCqvQQtR-^G%e~hOrE7dw`y|y-yqIVorBMBFeV9;Y1viP7t_H@|rnEv49 zxJWWpOukc6ki>BC{-MmP}AMf*JK(XYOH`ODs$`$nLpN`lKeLWw|s!H`Jkyfg!Rzrh0r2oq@2NA}D*W*bgg zCaO-dO)C|czB*W@u3ax4D&3nw&$s4jPW-q*x|8{H($nAv>-E2$1X6hi>sB=ip}D%I zl;1F@^DPdYjNXoY;n-n&_9I|b^&!3_D2Qiv{}fOUb;%?yM8PeDq&s;8mDkbwkLXw_ zem_=cITgUL<3KcGK2T&Bn*8SxCX+`j)zezqB_oYY%Edrc2Bw6CAaD7|Tq<2mbXnM= z7`i%#v%GbsLt9koGp78C$`TiYT(MB;+gQrSPdA%@n#)gmXH%ZOt$*|r8}S#ae;;e|Gf7-rm_~u|lPg%F;#aQVd~ncX z`2e5{}H-#>(U)53`6*q-fgJldp8(rfLUbm*3{; z3(&hUS~{}BUuvD`^i7A&QD`@%NJcNdGn?q)WC`r<`>%D7MecyzNmvKZGVL5X(9cIk zIM+y(SDiWYoBx;oF?lC8_6&<3dL%+o_cc2hGZPq2j|(xXOJM9>Fz7&&j>5_Mi{dlx zg(V(zh3tt}wYPLfm8s(WZ~V-TFC*7M#^SHNnNC-<)ujsp%8sRSl690WoYn*)oc!-K zoqxy~uaTCPOj#`F7-!j(Pkch9SpPfm>>BxMM944J)NHfjJZ#I%W6>U{#Xfw`VxNiU zO}6PJY0DWo`3=@6vb=8=P5>Q{Kzl>?L-Hto|B*Lbju>ZR)-M6Rz8Nw*B>xQ)g|4jfc}L84e_E~0PS4{?=87{mwW^WE#c{-b2+-> zcC5(t!>cFQ%fPp72qAPo(3BtTg6?rrGV6t$sLC;5A2}(WP0B69FrdqXt4y*B#MSnt z#un_bVB5?sZ#qf?7?-$tweXUoRY)207ASOm8OR7j6SjiqMXvr)Dq08r;(yz3y`<#& zJGssxastT}UEse;q*cLvnFfv-7x?D_=mJmvtJEMx!;Prlu-rv-ic!C#%y&m~aen&F z4_T8E7-Kyjiz^xLaT}dV^DW1FP8_+Xs9xizYScgW=v$Of zi`{;0(}&xLu|_vycZvAhS^_C{JKKlv>Y!6QSIiRJlU1cJTm+})L>FbJPbaSPk>arT z7-|>R7}196ufe>eE^*SqGt(Xcs7-u_&Oz1qeWHVJ3yv&XOevTQw9XY2o!MFEyp81> zPwvqjEtGFD@K5~?!mME?q&+hSl74N0eO7OFItu?*5r~BCU9G4+Uk&`cwh!$|W_aNx zrtadgxzKT!d@CHqKy7VaJm0XOk2;$EXb(Q3ZUV9`(U_qC+Ep`>KP)oid?$xw+lE>- zo+-wB?oGySNzLAg1;=@@6GcMrwPwuED#l!>WfLU^n)ypF3OUD=&oD3{^el4v8QQUQ zTWkr8x`mQYU#!oV`=mzG6DUkJ$&vVlqS;fp!Qx~5?7)?BFE-)ICmOG&`+wuj`MQ^8Mv0x7(!~uc)r_9_)Y^ZJxZj{(^YFWl&4!K!Y511+ zJJQ<(K~gNWWA>)_Qx5*jwBe9dTIBScd1KsfKY_i6IT{i#tDt2|GhmN8LN0vKq0_>n zr;T$sP()eY2#TBL7Y@VM`%JqtKELn32sjsRI# zu(`0%n#Mgsy)5Lkly=Tyv~@jh5}Q(2Iw!0>q67*96o3)+(oC*u$M+EwXW67BF&(=VnuLvSt-_q&9RMI@{94a>iSHb47?~Xnw4@ zhbOoqnR%b6X)K_rc`uF7@RC)^;aXmp=WtQ>XCuWUvQuS9;7R@nE=?fwXP5!qAxmg*`u}2hDG{5 zI6=Qz8O9K%0%>Z^%*e~fO#Y9NdRROl>Db5f+fAP3w`|bf2@Sd;cMBG3N(?^R0!U=a z#eqU9@}Q$af19fQZ94pjT*Wx{@1W4mnKAgEZ{C0h1_C~sMI=Bw=f;u?x&#QJEBD|S z*Oryj+?=?-qkcrCs=dl2Z6QZ*k7ZsLy#fZEelx$C{890`3vdPziJLFp#@~ohIwPqb zC+{s0xa7>Z2|g!{|BEU(TFknj%M2g7Ql*ZSG_{gvs{H%%%qW`Y1zk|!RZY)<&!}t_ zd!?V^KqAW>U^I^#aKrw$O~D{bho>(i#<(iJqN{=scJ5vezS2ym?b*GB18t^x1I58h z<4icvzTt84!wr~uv+P}egGwM&2v`Aroq_lPk?7!WU4I3MlVd?Mf|sxZ(r}2d=;png zvVV}sFX&aGDgdUM09>A+ejJyVjL@mc!73kqjK5w421flnzAKS)&$aJ|Nk+OAs#4@! zFStFBNWnB}j(-gz$)km3(9#4x*b@ejW&>kPyboC>T=o@t{Rn6G1OvyUK7n^ys8_sk zpoNhM=-#P52AX-EiF$@+JkRvQvRhhrAnzrof&tmu-l{BuxqkxNKIh2A|?WR z8!%%G0Qw$?iyV2^VAx81&Z|2- zCUb^`V($9MsD|R7uG2i&S=uxLe8hw1y-L3gpfgg^>-w<&FGIZ+&bY4gPkVP)p@ii5 zL75nxCqQ1KZi}nSlpL%^0U&b3do`NrD+!=|l>z9UI~--uk?NIY3`GU-VkMw)4Rli< z>4d#C4H(o4@DRNSz@YMBL#H`$L&!0&w>ZF0djM@M=xUB=#U+glP{|P_3S`(y296IE z0=EBQXAQ(=(Vk9@7HI)(%__oyW{YcZAaJenZ==q(JK%#qDv&d~qrHC+VFTt*+iVVB z1D~iP4UJ0S6EMYIU)_b@^9^A3&7Gm(4XD^Z_!0e^;Dnf|V<(t>^J5}s->F%I+rS|(GSS%EUZrZ{z577EQ&U<2E0Xyj{i zUI2()QohRn;_N-3nrhc=;UGvAP^3r=3W#*2H;Jfp0Rg27h=7y`NbdweKoN*^=_*a6 z1f+x>IsyXHCG_4Qp@aZQ{FmSU_Bs3C=iEE)IgF8*L`p{1dY?6)Ip;H9x{o6cU8sv8 z`mbPgQO9U3N{AZ4ihtdptOYE#LOP?9wt}X@MG3Z`D=xs2 zGj8Ha#lzQ5J}i=$pHdbYQE3MUH|lf4xt%+arvUph3mzzrt9~{?41(=3u36r?m40kS zBoFB!gbY9!QQIuwBZN6ZfS9BXanO&-C4B-;e)FTRgnA@aVDmRfYP=Qt`txs41Gwir zvw>;WE5N*NYM{mp#7_LrZYFftDUv2K4){2!0)e;9)9`g6L6+ef2|*;-vkdKYYgXSoSfH_{P08_d zJ^cH=PpT7n!dXR_z7=$(R8arhSYx2AeUT17hxb4}mz-qB_p*5DP$eM`=8JjnO_wI3 zPx*}S+?acMqqZZ6W?rqlKIwy8E1%5q^qUm-3VjtU$mrMC(x_K}VVVRtuTguq`RrQ&wTT{y-0G5D> zh^q5@9e0qr{`0X)9Y$t!LPy+64>RxFMGTNs-<$VOh%H zHu>%D?#}%Cd$S(=bX+%jUOx|R*)@uxeDSP_eBpTe$Yyctr#Jyxa1Y9oRhH`^Cbkg2 z5T<#dQfehCg->K9r9J3J9l1=$y3Jzlk7i)*so`*RVoJwaDj5swq_d{?3pW@c$hhS@ z*WZtKGJI=ABdZbU;#g6I^@#FWO=4<^?2#9wEJ($bV*6)v3!K>yHo>sMX@BgD4!LLo zqqrkZiLXq3a(OLsfMNH%A$Bf|Ah$3>FGGL1%a~)UFUUs60LrAr#d+l|_dO}{I&I9Y z-pqsOc~|se@0|pGX}6sFIzHFp`cyb3gRf>tU12V+n%P zFB`)4m(J>DMy4mYTu z;4NkEucn@lnz@9*jD8g4YQ420WmyJ9{Z+BmwUzmp`}s{Lxw6ckG{Q$ndXaeBJfGboycI) z{dzBK&&ra|c)}g`Y^m_MXuLM?9kU?-54rtmVdOVRPZAj0*%0B#qC~1d@I8eE@tER; zu^883fzq!0a}7sNE6XX)uvRondnfEhq{dRzp|;7-IUdw<4xW>QsrG~3qET< znRuY5Sk{yCQ)9d2)|nCk@*7nC2sYki>V*&@rpNd!dgJTpwJE zG6rPTtU02$+nTiop0gDPX8MdAX_T;ESa;c$o>A5hbT7E8fj z1WpWaAPKJl^uARLQ#?&yXT^K3d$6jq8SX-zl z)+izhn7m}D?G$R=8XJgS}bp_cla^24u3f(Ha^Nm^Q$Mb0l+J`A36MQjozRLDkm9@^( z>H1_`-F)tsIj6ot%O~h*OAYp4F`plXU1W*d4?LJ+S?hfESY8MbXhDjoGXml(+};HV zNW>7J9?I-_o&M)GQhZY{Itf$UY_RCCZ&@$=@l1A2Dek9K=i{h_o-}V%J=&M=_J=l9d{@3GH6=6TH`0lA2qzenSgf;h=%E&}jC8(z3&!oHOfac3 zE9L7(T)CMp*)2byH?LZZw62gSUIW%tGg?a@rfF8q!=5yN!3Ar}$fVD!u5r-W0gV2&qCv z6CvN`euH$ktc5bVQ@-gVHwWF$%YI&(-bX}^mjsC{HoOvVNg1!G@*BX66cKJd3i0}p zj>2@4?n3}%Il(DG3i9QbyS!I^VT4{HF%L&$Pc0&9Oj7|Iq|(12J* zMK!ZStpqUHg^MDPZ|^v%yzElEwF-nT>+;4jihYw24{p+D>7MwEms(=|G(Q*B%!|pd zj**<&+}@s`7b&vDREe^yqL-ld_kzdCB7%`kZl0c9IWkSd$!l#*P%R7r-IXs8ndZi_ zY3eU0cW)rUF#fxb@Y+>F)5$n>vR%KgD*PDl7Z#+uQIt)eePBAte1coLp^!A@Fu%JkK_B->soC5A@-!nZ+M za_<@~Jd5>QFQgiYEN*V>+L4En#gm?QDUD;iCHBM^gbutRK`8qQ_~b!LNVraP(?c(W zC^3~1;xKm(_Dfv&NSn}A+_jse4!`3m0Thv?`$u$PgKvVdGY1AO0h&y;rjPDbCAzS+%gP-C_RhDOmTzw2u?z1N) z(=WBERPvXPjN{9t67<=-AbJRMY2GzC0MCl#$X(HXsO5ctT=sXvWv2lYHx5FeZUh>P zEr{WmSCR5ZWkH_ILWNs1`gKh=EkA@L@6B;G)BA1BcXugCL?z&HXQrbPtTUg}=L|B% zp9?(J6l?vy9(XZu!Uem8yN9)I*`d6=1ZL@640JKk7F zjOHt+GlDnNZrhb1$1e3q1ZwQ=6^~$5bWkIU!!KNRKl;ls(mP-1jhPoM@2#DFZTIS0 zq)~QE$?cX;++Ur{lN%FyR?T`6xjSql4R2)z#OyageRW>hQPuvlqOtt7B>q_s{~)}7-l&Ya&Fxh}#U?W~MRsBI=)R(m z@AYb#x>wTI)axRpL|$9|*pKMr0Szc1B6eWo62r|Km{dY~4xqh=kUVe)h#?X8#Xc zMqf6pDi(I6tVan~7xgch<2l>q0z#snLN_3lx$#e#LW_qV1~Pz@6NeE54o77uv$iiK8vKHuCWWEwvGB>WmK+>ibd!2x1McZ>P$CQ?NDNyfJ>HZ#c|nrf z3}&Dr4yWQxmcycNd{O#yY|20XFOn9^$d}d#@e;ss`NePmlz?jAqn4l`z&RoCS80Q- zr<6JcxgW__pmxV#0Po0$N!7BPyFe1MEvg#^d=xEjq52wF?!DJR0vNb)MPrU$ZPl2! z(D|9Fn1uVyF10=v@-9Wp41aOF1Q?+hng!KS{=0|yU?Wd4-QsCZ>qyvz1ZuX2V6W-PNKBJnfn&6n} z8(2{J-jerXO-U+~iH!HcL=_&{9U_{8gX4WYA+7q~HjPg$+gb}bKbUKcg--YJT1H>x zCijrL)TQR<`^KBDUtU!s&hK!t^ZUOYw9>)x!Uv``sS>ZBV zvraB`F6h_LzD@;ic$gl;E%?t|xg9RCLc*cC_2DHQ~kIX z`B({jp|Ao_K#$;8GD$<(K&Mm=oGPbxMS#U>2R~8BiGtvm!KY$d6UsmZ6Qo%Z1?&{D zgQR%clNXzFrp7xYhl(iq!ANq_4GGSiQ+wOrpxjQQ+rqy=ZAXLcgIs`V0dna5@U}?1 z#>el2=1?QJxs8HMy%fjj$Z*n8LE;^H*Ce#3kt67~P}S0K#+~zgUio>hNuWRQj@Di! z?aq1Wqe3Hn^FO`e`-_JKBXDh(KM1d1_ao@fYr`hNidr+@06`EO8( zb$;;PLc?P?PN)J!eq2*8)-i;1>EnO>yqOx1h)q%2XKVMH;-+w1)v=^Q^m#Obcr0)~ z^aQxJ=Evr|C7qkrwYh#$DxP7Y207@Eysu9@%jUyR4B#$084(Oe#k}8Th-iujL8NaE ze#t8Deu<;F`{S3A`&Io6E{@Z4`X^WAP&o0y-=Nyf6S+k<72%w}8qvEZxrwlU*1dqa zc5diHOjmg%`nZ)N|4??d|7wnjjhokYu3aoOr#;_Q&0Q19dPsP>4{Cvv@#1E-ag1A| zF6f8g{6)MM*~rJ6gE5S6c9i*+=taz%M)Jn4m1nscqeXIG^k3ut z9@J8zeuaD_(>AVp#~iW~TV{@br!ng0qG=ck5Qp3@BG# zVOq{)Yyd8qWXm~s2wZ#pF28FU`ehxYf!TW(a?X5RMTCbv96kjo@k^Kk2;7=Anx`i)EbY66Bh_uBf09#&z9)p zoMW2?*G2xVf&!lDN=8Bkkh%rgW@Fn&JVf*rVo^rxHzB)8KmrRtaF(e40`AU701U<- z7UO?(dkF?Zmf!jv1IlC0sX#I6ztmW$&Jw(+Gxj&grW!WdhAFaI$;>21pq8%2F@+UfGWYrN5KCHz}u{jc{vZW{Fal2N_9 zcMt&ohzS4dTwJm!$GV?_5l$QG2SSIW)m9x=lpOCh7he zn(m0U^jGG5FfhNnp7By46ATDvCi^h z#>z5$ZHf6V-it(8wyJ|5#LX*+F1bBjl;ze@nJ+G}>YYA5-`(l5)-7aJm|R1GQ~sIG zc}Syix*4bIO{)Hw8@wRsp{dSsDOgE=Q3htGbb&N9$6$9f3Xt9JXPfSI6p|#_x==XA zdH@IBdcwH<9QDnE@C~PE~qKbB6zYd zNbCtg8oO|42@pXV9N$Y35#b~;UpSl?jyiNNF&b|Cke&CYCr^;MuvDggyn|kl8ExpF z_mRTcMa1yoKbu`z^$i`(nZIG*zxKy}+TN=GQXDZ4k}zD#xpX@-yj8%g+9ZeR%?Gh9)GdlAp1eOKF$xzI;_I& zqz0M$p%_3tNw^F&P|vmjiZc$8NCMQ3?^6;)|0&q|Yec!S<|h?qeC#7ou4XfcER-tE z2Hp7GuYG|btJD#ON!^$*L1!ghWG9r0E7&A)`jXiRjAhbeYwie&Ofx8bdn-ShsC`Cy zZi;l|TeTT(&}R&i$><2UZ!&&L3coNMHCd=1ShEwIAp52*F)@xR2yT8Piv_MsqqQTC zc}GZN%$0AesR{C7V40F$4fo}>595Y~z1;%7wiTxkoD5d5wg28yQmSl`O+I^-p=j>@ zeWv@XxQ%7iF6BX?(r?U(XlcC=JR6?d6BtLZjH1pVvWE&+sTf)Ie!KT!XC_ zCL$3#&*U)Hn+Zh~YtS+`8V)cM*6q5daP6e7!5I#InRCUGetT^vBJg4ee5Pw=~D{Mssl=2D=%Hm&p!#9dOYHK&4yygCMLcP?4G&;{B>FCO;sXOzNXG>6A)Xr z*8ipVrLjr`UhM3ipZ>gC3yd`gg2D&QUdLvCKKRr2Gkcm^bqXiP-4n4%W@c(38_*Ka zlE>^w-TziKfLuHugG(ezcT4Ob$cUYO`}%0KFd0Kh@f(scyTRE zvyy-0Mf>2(rKqICmXn7;#d8WqaXcAGpTz8TTlGA&bPCWGB(B0Q1dE*Z=Bq=gZR14_ z3&e|T6%`GZT`PGp#e<$zvBULs6h&m}=a$%&quw=IyD!mYP^Aoyx6#o_SJc#0GOlzp zRo-Oxc`hj4EdV#)Rp!RzK8C$fq({9uydJKZ6=n%@>~%5f)v@L84xuru$Ss%WWnrhv zHza9xUz}55#2JV zR0S~sw!9F+0sFhm&RM$5RZ+z;=0~iN5@;7ucJd3&cr4~*DfPJKIFA3#(QlB+b?PH7 z(v{<~ZZie^@lr0J1+bw`HAPmWK9EjH8o9|%Gy#=t3#Pw8?{u*sz$Q=tCq$18W+x8? z33n5O!EZE3=}tMPGFzE~(b&a6CcfKFdCMaiO_DY0eER0vM&k*ge;48#+J6A+|D`Cu zr+2MND*f{V|AuP++Zy~YMf(37wg2((bNFzm;NR$UqV2}}knaHk1k`59Vcm1s$Fv^e z`5+c3sUjr#xH+|ZTa1wyS_V5566Tlo>wZ&mJ+-AiGQGIoMMHC3IfZIvj;zM#-mWnX zHI8N9y2Fj$8EJJ>E$TsI#t!RvvwpG*pFgVBy5ZG9@c71hu*g>FRkS`eUN`Msr8$(p z(p&KCR-MdpLdYn3u&v)(f2gGDwk)nsA6fHU?ke&}*WA^8l`V<%Uwj`$89XgdG~}vN zg$85wCkx2hvtLC`qne-OaLUX%x=f{px ziKA)kzMS~v^R>8Xlg1!=;wM+qIcPI83L~3AS?wPDQH`Op03CTCP;XHjb|snOX*PF(Z*>t#S*i}x~6{T9?C6FzWvRN0v5Aa&Zob{TuNf3}2;w=$t zC4>s^GQW#=?wYzkYCPMvc|Ac(!oJEb;@68S3N1!eWVH$Y{Xw}7fUNWq){Gjcm-Jg) zdJUhjTq(^?t)3|xk3~-)S3Or5!aH;}dxu7vapOIk$!9q~VcRo6tp~TD{;u^}2w7qV zYB?OwMryqYTbJ38!5HD^iZ%Cx z7ZRMY==++i6>A*BNQC|Q%Z9MFL5wev-dy7Ece3Pyd>zCLai9yAh*W+$cSW!8%_FB& z$aB`ID8ZF|-1gvEAQl)YJdH^;7aOV`eNk9m|Bz1Aldfx?=XEg%`Wb$~p!7$wPYHTl z$htpp%KyV?e{tJfgC5C^0G~6$I<%4_Vx)nt#Qg?fCeg=R%u;X%IV=Dng6!>oK8U5l zZR~y|S+TxLoG5w$gJ_yV{se>NEI>>nU0f zh)Z-6jj&OS$a^0?NLLq1v4qe&TxgfJH+(eakYBxG?7OoEbjcj-nxOe|`dJ44pm!;+fbx2YbHh zFOs9B)e|&$Jzl=)CQpo^Jq$!m`dV_>N7l%^v%?&XXSsjXQXV(#^o3rqb77il9=;GB z(sm{H$}g&QJ#RdWDl#GBiEajIj{v^TTxov9Ld;nV=|XkQMLA7$t8jsjSphKd?n};6 zce^9$7~Uv}vb358>`D0e&jgN9nNn8^{;^!y{p$2zy7Vy#O|A7v=o@4Q!+J|BCv28C z2DEg&1Rp+cFm!#)2C(j@_c|S(LDN>@-@$eJ=4zDBwb*UV%r4pXi1!PJz3VA~RlF41 zZv><17jye3 zIDX11nYf6^;MAd0Uuk|hRHol6n?Th+p3qY+nRBgUiv-5=9&q$nb_TEQV2ODu%#0^R zJj{S&>QCe@n>MP-w=MN)F&5lb(h&+8cj*yCVkedu2_h>aB(}j4*?0MtRx`h@M%Xrd z*i6|S{&HYfBUXLws;OvgyXzB=m&%dDhuvR(@trFX|9oEmp)c)l_PvO&c?)LE7KfH9 zPb)b}^FCHXK0)vne;UqD8M**{7XkEdFoIYP6;C$*2nur**3~TBlCAxH)M`s5 zOMuIQo+)kVWJ#`R)W%CtPVS(k*iUNZ?Yj-K)q+q3I^NtrlpGEyHF{gJj}A<>bFkeV z#@QTrI0o%xeB3UVPKgM1<3fe>+C`)_RuU)Hg#8At*sjjtrsa$a0(CB#i=_VASF$=b zTt&^erR`7diCa>)Hk_#m)QsyK)V;%6ck@s+Rt^WrmEf~2P7pF?M-C{=2J-AKQ)S2d zeo?)J&~su9kvlO|0$K>6cipp8;b#sHtuNtg%*?f(Man_y(#&NpHMO~(WJT93a^g+m zj#4pm?I{7v=G=`qtkVmUc%lklU7X+pflu)+FMrU8_TJ>ANoAMW7`GzhSU%0G#2={F zq-v#8X)a>MGy5qL`J&ipSf5=b<9|QEe9lkVWPP}8=yi_FUZJ(za!`l!z(wP2e}a`P zKCo!>{gm1wgj=kkn-`k4`+lae(dFS;#Y)9;nPS9RbOga^9=;veGuNRad={wX?!xj4 zxKP}?e1rB!9#)9APJs_5vzJ2-vmd-jc!s}J5@a?SWRbfbu3y!ds26$rT+b3rNdLog zBKiwO_pA4st;!BmZ-Avlsbj&-X#u(96@kKD(2{9uT`1OxbV=Ef%rgLa%$H4rB9IIv zH~p{b)5$Jyo|R1a11p?T|Q! zz!`HN`-7}+vM<{tLE0kSV9AZ4XF-B`v&KAq{aA$;ZmrrpKBL_Is`NqjvzT*y&-(V0IW=2b=lwI~de4r# z-FQ^?cFAU}N@;J!*73ZxI8vC-TwWfuBF2k8e~0^whta%@)M@i%@0C1}yr{YhIXznE z_z|Mtjp7!}k3A+OL@%Lid-xiNxyqpRbKk5L9HTHf0vOz1rZw4j=%pI=4 z04vSsW~fr?UWm?tLqq7~2N*4&fk!~FbfkJG*y*jUjGi+1g2|s8(l^#eBRYUK3xBfW zH}vZ;PcnVRX>?>9d5h_foDyGeI4q}4`!A0{E`Pdf$(#ot&!q>96cv{K(O~Sz0V|D& zcizWyY5D~Z$#if3`4#`+k!Sz6C{^vk3~7C)3Ar92M($S7DAL zd952*nrp(>rN>$JO*+B!&c{|V^puJI!ZYS(CzK+-HnL)Tg058k#}@LWjYFCBl}oFo z0)bAaA8bP?eA_kf27+&@ly=+u@3-u8`gmyc|B60^ z<8DrbT-*S&r_BCXAG$pr&NgX}bf74&t7oWtAH{T{K3xvE1;TNWyrCS|a~Jy6E$A)u z>qjIOyVIclboYeq>;Ql%k0?UffqyMR;y$11dXRpDv~8W-f(uK-)q~daoPJi?aRvRn zNgm!^i-0N=YHVJ{9XKnB$((7UoxE@X+b`!Ikt(TlEw>tw8WR>4g=vRWJCj90vK38X z1A$X?GxpM@7Ta)z1N&I3{?|9wC?XGVCwBAUIRS*Zs{a6j)*-`l6_$m740B=13V;QL z-e3Jw#eAW~)JYl_Soih$&gCZ7s3>topHL2xROSJN6P5*SkAD49Sl(Zbd3GyhU}uBd z<+xIG4&7*!?3aH%Wq>FacytC|hu{F4SOOz3y7`ahK5rr;q<=by8Y4jrdkXMW&|&D( zABGf3PTJ5Ri2M=HA94SmoRDPr9l-0$UY9V4Lry%8jpqmQF1#hhS19hjW>Sh%GsCGgcs_G~ds-PyI~ha0C*W&YpeyelDBN zTVsvjWi65OJ|eA?p?QpBZvEkHvvagt%kY>O7#f)TdYkhC?~C&ra%<+8!`Gi6c1lZe zB^SAU2tAM)ii(5KCzUTjkcg0gARV24TMLYm_14hbOxE>TaMhE6Vdbw9;&%z%0_7m` zU$omVLIgubQbQ<#avD8;{0PRN!HA{^8yMj+ed7Q5T1NB^>1LC{V8Hy5J`g3{(KoNF zuk+JeOs{R?Zl(XOiETZ(pVTSL0L$ciR zd(hsKwQzzFc6F(P=hl!4$CKIaT&L3+Y`T0dQghfOt55voP9InBbas|7LNPF{ZyM5(k%;e31l^;5`KdZFF zC!IU5XXRkcDR6L9VWqiRAy(hb0^R4+fEtT`9UZIk$N?GcS~{!q?p;#Ml|#;P{CZzX^C zs|VR#_b$I~o>4gBiI!p|Tj1lTYQ@^CH$g4jP&du7qhd~$utEJQKswk{4Dz^jT0wQa z!o~G^fiPr`no@kjHY$#_b+Q!yst{@Rn6;r*BpW&E=egxu zhm}q9;!AXb8i?k@V)o^DIzrunN?hvVX*%vr$Bi5x-*Qb5xy+sEe$l^MICsC)jfe1P zbg%K!N55cA{7i_u#&N!an4l zF}V-?mU}Ia$L;f0TG!OLJ`Rvgj>yasDDh@&aRqgwG9TWp`y{-uc&1G(u>3kF3wfo= z1-m4_P7TrOUbxM~Y2d<>XqPhoRJ~@CnXy0wGfl-f-fe)}bru4~vVj4{;8nhx5j6Y2 z)?g}kM+yvrnfNFlQ^auK-Ea?TXO>_b4mtRI??K}A0HPp%1#>#mlA032KWwyp8vG;Y zc|#4@L(XPj@${S@Pzmfpdad^r{kloOFdZP6a}bqY-Apc*u2huq)dtJ#Z3aoOK8^@d z;VFSNon9g^kw)SmjQVat#QI-PU9WLJ~af6;anfm{WnaWMMeW=5vX zRLB%b`s^{T*r~+1;c%w(+3-D4I2SfF==&H2w3_B|+jp`D6N9o*PllAqK5jO1kCt5> zwZn>-S(skpoMN}Hx$z{o=zQ9fPXi`S8?#Lk^Mg?#qWGNdW17XDrJu}7sxcIz;mKUfChJFr<9T@rQ`Xmm(tV>uFFGuyU^-_0i9>-G`z>? zqu1+VcNp6V=?}gld!b8#%FshqEP?$kZ+tXHfzSFPpAJXFXwqeV?VEz!lN!fO8X>v0 zh-a8hOM=eOcB6w&y(PddMKcLDjBX>*Pwuhgq#HZt8s@uS61=p08du#$uuTul;mopG z9=@MmBJ!o1C)`1xH1Edtl%b5@&-Wm(EQ9B0=Gf54^d<^XJ51Y`w1Ki6JW+s0eE?Df zHXw)hlQ%d9_V89D$jotb`xl2ToXr!+c7~+>nMRPxC_lXSgVhg#F4;QP;jCZVehNEt zanSO{S~&<;W5`-j`KUe#xLO_+uSm@;1*L8VQ_>VvNrkX5;sJu_BAh5a{2O#=JE34H z*9IU?R)(_AF#IttY&=LQ*ku8>T}-p%)ucGfX_kLr zxOiCrwf8|%zFpe05w;z3DUu!G2i_Yz36l9g-vzrNU;U9ej<>^&Ouqp z==1jYOn`;Ma|F{j@g|$VCkat=sVdh?a zLIUy|Dea@$%TAkMy?rI`_i>tr%XTqwNzRA&>uwYy?c9c}d|-}l5xIyC7%k&jEU-VH z*T|U~L6|#4z)ur4?fQqUDPGR8m2lHInV5yEe{NhNaY!xb6PZ!Kk@JR}NgG{?>Ni7S2|O5lsJW9mi% zk>c8>0o4UXBkx?o5n6)c_JwIDfbwwudgSUJuD2dpxwsDv7Q3p@J@DxKa$vj#3~ZCr zsmR*o?^NmswJfg~KB5cOJGiSJy=ti{mPomHbNfv(m%t@;P1>msiQV4;Php6_7QiGC zJd5!S9TPb&UDw|Y%2Jtg(fJ%n z2g?_X@Th7wYWaGTRxVOwNbk!*5k|f+={CSq4QUQhPdK} zkUwrBs?OZIzt4XQkoVJ*7JxPc4xYGu{$?)Hy!Yd1>)GZrvB5R`-o*FQHQaMz0pUEx zc9F4z&W&|LF5X#|gM<)!{dsIwfz=}RM>}Zo&gJK@`a2W{R+q6Norwg$QG$1wV?B50 zSE$OZq2b>C_k7GcN{19{5iL&={0t^uS^4G%nc!QQWVr62>J|m#6=nXk0?UIU0Rj!idrT$0aeD*xg zM@FMJJ|&H`j%N$gU*DV1smWN+E)|PlZL6VDHDPTH|QUQf5O3=Bw7;ok@-%U>G2 z2xUu^>iPWjyVo7@6daioF6$k$hZMP^`M*f5iH)=1w($rRJvXzAEA?Oob%B{GOCv=VQn zEQY;nQ8+?ib}{TI1eCb!d7C#6RpW*tJwo=LP`+?6)L;;gS)(2w?y=Bua#1>xZXeZ| zQ4VX@N#BKu(|yG|z&zcvGH9SIcsFW7a`HUVl=sE7t%_G?TM7l3q ze!~k?p@eRhA#vLR@$tRtuae~y&@Y*JVl!=Xq(?(U90Njf10BE-Y8~zmuwt#v;6~aG zN^t$sZ77fSS3Plttr0@MN`>~sD&dFD9)qP*O|fY6_40|Ezd@S|4Ne>oT!RnJ2JrK>Gp&M-1JglAn$VOA$HCHqS5W#SpZFOe zfPL|wEWhxw;73n+<}LCtYMDS_W0We1IJZ(LTaDcL9saOcs7|mUr){C>n-4t!I-jJH zgknD!d}mkaJ)U1O%+iMn*mL8~kP5|*BGl}QPCL&o5Uhttl7vf9kA|0^S~~~pjCntxHou@|C*!uF4zUa*n>XWvy4_aWnYgY&8=a3H#R(8>Q7_;seC+ ztxdzE;wCF(&DtmoIoM5qd48@MZJJWPq59(V1?0h)eUr4;+a*M%1kZVITa%~@6~u{ zp|yGxfFl|>^b|AK1%8vRoA*rzYQNC$L7nG$peTA@M6M3RajHy7nN7v`wt=|(8G-I4 zpfc(XPRfM+qP2pP1B1p<3G%vvro%3cYzsu4UM(3HaA%LZ=LMIv*%RJ3tS;|~2YGo_a{B`Wnza{1|ec=qcF zuk!cBAub~$2KUm8RxI_kiMi5SE_{pRPQYd;X)0;9P7X48sa;0~;{x(pnqb}w=VI(Y zQUlPQE#qU$Q5gmLvGLqMZ=V*L>)Fq??`-t&k3n`g5hte^BofEgYXLnW3oOfxCb%mx z^Dt0oAi@`%bG>XwUxj*+jX)x{kKATd~w}@xV6^6Zvi*+cti4T)s^Y~RKnaq^a z`>cyyN=_~=JN)!lg(y6_;;yw`kVN_CB-}C~ac**$LGCu}84hkiP7U?%kRy&k3e zllL(*#uKY9&$Hr2aPnrHxMY0L+K4k# z=Ka&SDj6-r@sUDMI_W>nh}5G=rCN8W|DI?9z}0`S!hatBJ2Oo7Z%pxD&s8_nsPaMj zf9d|GG?;zj4$9t*{=U`?90O$ErublYg7}OmvNsqtw-0S*i2>}qF*&EVixswI>Xz@3 z?gX$A1A!*^^v)QzuoK{sSpYlW(S{R1kq=Ew+Wz(b0RSF3y*qZG)-Y#I8YZzOKB$g9 zduUeG9X9J9Bg99{zD6!j@#UDD4=J;5&taTexM>rMzvj>7V+n6LYg(*4riaE`vRu?+HT_Al&8zf-9JKRU zXFy?C&Y7nwhLmdWw76qnR^{|~SIqS}XExg7t6VKjgO65M%UulPUw)wC;DuTm8q5}Z3@BrP^;hWa?wNza(dZu+-!1&eI!)A^;~`Z}{!8b%Ij zL}elxzoqQA?O8|53)Wk3eymwAW}LhG?12A<=ITu;E3-2*zqqYV2zyoFS%Z=YTd?@h zu!z!N6(Mf#S{luLI}h-#WEh*%o~1#_inxx~uKVEgkbcsD_5R&PK&X5A0djcB3U1~8 z@1Q%x77}}!a}Use{>6Zmr))UPlf>!?yGVdSF=Olm6p| z5mB#{2S9RZ=nl0t$ z_dMdT=clEbj8;YBKKb(%${dL|ZfZMem09b}!cTu5*hao)@@X2>#>zzzXcmI+iYPSR zThw`*S6SW2V-@8JGMkUHr;_vk&IIz?q&FI>f>A<^&3AgCD!j4M8CL@q4jY2LU%=k0 zg5`PtXd#l7SVwb^VvBn63f`k{nO=<-;E>Ib`Fzff-_2xGiUA7rA-`TXBtR zh45XNJr6lx!U~e;#84;KstNiFdz5(N{o&a)6D&okr!6!jQcQM^OfbU!p{M*Z73eJb zz(wj&O~q)b`17}}i;;HmJJYe>zC6{=3~%iM;(tc{2D?ugfvq$p^fA@hul&UhQ!D$N zZrqCPW$TUbiHw6J$#(gYy`3y)s?N<)lTONNR{MGj*?y97$`}>IvZ&m8OU@Zt3wQl^VV3Gq^rPv{ zmI2}2?iYjq{E zD$amZ%+z2p{eT_({?(hQ3haAN;~>uY!Sm1@1}`&-AL%L;zJ9n$=;gT%UN`9;W|4B8 zIttfk$;TQ$oV#C6*I^4Ef4%i(_2}?GDZwCs|AjTd3~y0Hkmq5pi|YPiIIE=T8nJwx zIaa`ojCD}tT2HIx_lGu9!dm@4^{L%C41NYxJ-ae)SDeSwSMma0r$qI{Xplt*-g?3Q z{6dCFppYSLd^|xr2_`hf=bb{X?ks zr>A-^*L-DG0|YyBqMA8>0_!$du!AF(6fYVJY@<_juFp9^-d7EM=5O=9(^q`8buD~; zAY%brj8B=zhqp7j*na`Y60Jo}3oTditHvE3ow&EQR;m;q2WkC!9tH(my%2K!PNl`H zh1mQ#W9#eeMzC37jqiD$Ve(Xk&IawniC#;AB2GwsJv0q+^a%bA!bJ5JRgssL{u}gQ zT-2p(?d-vg)JuJCYm>VtoUW^;gf3p8XYB=2W+CUXV~BQ6p%hEj+a3zL&0|g>!*BZI z_b27rBji)#J0fynYhP7m z(Jxc=#}{Q8qc#+gzuH@0HhU*EDmx%+k4wuBZOkJ+R{`YJ1&>Fb;j6EZm|fi311u1p zp_qAUr>G~sTo;B`N_#I=@-$EUu99oK-?NVw-g|%$&RDnYW30}SabZ3_yk(Xe%Y7V) zD9Kd}LUOp2WifS!g{U%TTeT;&WCm~B7I<$rlI6yVv@_waEomX)<~0$b-YnG#yNe<~ zj`5SJnX+TE)=RSA2?-A(Snk}afOr!`@m0!?bAhc2M`jLRw_Ci^-`*%SqUo8stR8u_ z;VKO|??sWe9|uAUF6OVrabqt~3wsmISwt?eD-(?Z6@X$3vzoHfpi7ETi zy}YjFVDf9I@>;9Va&dfuieX0?gRZ;z+O`gM_SkGx{PIFJlHc=5pK#6h7T!AESEyIk zHiRemVk~1Dn3bTD@6^m!i>#=w<#}W$gr*fDRShzR`~)+(4)o<*?(K!tze~p>v&IZP z6HFX_!fe&ut#COL@rx)-7vu^e1Z=gjHBUK0pPlt$-n7c6a#K$9ak_%-g}$4r@lDYe z+xd7WbTOQ`7x+5NT04)-aP?p$NigNM2U_0dolcJSFK)eiy{_y?GU5*wh1(3&r%Y3e zsOZ9MvD2e&mDjX8RIz&_dRh*nyXop&$PfO6FYt@H>IMeJ0RU$sC1m$i(r|U3R0V;2 zB1Whv_qW{KBGy9#VfD(dwDCKMF&Dk0~n(#lKGP!Jtm;~E8#?|_ErViLsA1c=h(V3 zwM$~M@Bd@#yQ7-ux3xh~6cD8MA|OZ?rASxlB1DlMAtFtPfPnNs1O=pbkQ${(C(=7X zLlZ=LFQFqnp#~D-H@@fI`<;8%{Ug7{%$f|4WHS5N`zaQJ!dXIr(@n8gl9LG=y_DSjZ+Na{zYxdZjkF=Po#zO^(ezcXBn&z4hq5(-1O@Hh zl3zwDBIT(f4^_biKnqW4I(&M!5obIO$jlBvQ-HVD5IE>pCc*V^sRiqWEPs!LKhapw zN^W_gVoK$0ry-VN)$Wd&SuLWs+)+`+7IyOrV=Ic0zvp>I_YPH+?%bGLZEaS0{pGeE z|La?~p-~n7Y{?~_2Kv_7D(R+A%xWwA)x%mu9m`=#)c}#jO2ncG_e#m%S)rbu`!T5)r0%NBfobG71u^wEZo;$h zoq5X*WF{Pt<9%@3vM)vugP&oxUoDVENR%~EyP3cgo#2z&)c@QTz%OoR*iralmRa{Y zqSHF+z_B)!coh(+0g)`ZT6~w<1g;ah0wv`JG6h^H1A4l*yQeQdQQ197 zF!=unhwJ}BGyk^lVkYD$>JZrmBZDtWfJ*8TYsh zRn-;s`v713qN8e9y@~~X@C|_Ma8#rOIT$)He=`HK!?rl5t~F{HS2`=7&QpF?>`$Vqvp?ED?EJLAp!X@pa0K?L`X!5zp`?0W3;H?`wx{C-L1 z(AObe(sWS~(`(QtKOBwhlQnfRq8|z@R3BD|AHN%fK^FIDz+il4mxhJ4?|`p^Nc5 zrxusAb!RWRXB6VxfN@bqt8Q(H zju-A2E2fN{Nri{rG>&Y^vmLEL(ZDP+Epc)g_=<7#Q;Twm>kZ+WALKu~AM33|WSB&= ze~1tQDOQ2fLtY#BrgaXG`Mz76=wz^23K-boaoy`fHMKme(wB&aeXrs>daG2G%FdPY zb_1fJMc@Ezw6TZ?BtSBdnU+dfo3wTsaW+fhunl97`uWzlVqy`*afsx?&tXAb80w=r zMnacmhyO}OTFP+%s#Z_7K&4^jao7F$3q52jqc$>={zrbI<3@pr=eo%7Qf=;$n2Mk& z(t!HD28;&4Tmf$9tm1=P1L}^5)9Y;)0qmn%Pl{ss?S&lyn9w`_iwO<56j|Ps*hfqw z;-*kbX6J9E)eoPVtxSBAo*LZQY^ji4PVqk0kTIxnjhL*yUJSL{VmD!og zsvf?A!YB*4bKI%?UIhG@4Cp`%X`|R-jXpzwHxtLiy~fN>X9KU8mb2#0rGc#I^MWX07spXA zG1MBx7Mpu4ho%r{v)eY|vLu@IdBP{~3%%#zN$tq=U6>wn7G~6h?GIgwx>>=&swYd( zPR@u>DFwR7}ec3=b5M)V@4BB*0dmQExvH*p*_y8Bd zRGpcR+0yx|`Q`;TRfl>b7CM=3kx1;VTK8M2*T>2bw-J)t!!CrT8@am2r5f~ihaYB_ z_XRlRTAr^Dp=#;TkO+8ncqmb|%o?A;ajBF&Ug-67FV);EVw1U4>WGBp$NCDC1@*yc zNIzW6Lq~uW0i;~Z6zX;ipIhU!G6FPkzJ3$}XUu1BVmMNfl48er%ak+_&0?~n z*amAw_O%|(xKJAx2RKTByfJYFgdl-V9M=*hf^ijF;#;QTq!KB`_;A>$xA)(tP<%%bu~ceWE=)M?O-K2{>T6W811 zJmJRjz`dlA@!7Pp!f|$^7s~MGFWH6SUs9ZPJIJ|-LhJR$pk4%R8}MSCS&gltA|Gyt zt}5r%*6SuK3+%hhR#yuy*piVa_50Qng%J$krEgdWQJ8YcbJ6U)y!|I zP>jAP#GBwWmZ-jEEA8oE5z#^;fJ;U-`uKSV1=>Yuh2Ay2;?h+y5+5@?W9O3Mi}B?~ z!o3#rN`bx!RXBnrMQn`a6-dsc?}n5CZwyiXS<}sOLfhJKs0b&#d3xetZvtu9J&LJ8 zes_z2kOSEe@Gd6bW}8t#9jFFNEt<^RPF`{Xx}>EpYQNaX&JljBi#NdW9jA>rHpAKF zN zYbfyk^!VE99`Z}tZ)l(X3?xZENOdP@+JDm+$J>mf0ct6q1%@Tu&B%iu@I-YzpYR-^ z?)_@r@qkG5fi;StO{Br?eFue1v&9wQR6DL=@;%C1sx|j--!%%+Vz{Yuz52bxUBQYw z2PVI=HB!zF0=fGFa$~XHZRX3zW91}T8lJgbn9#B z4zp_rex;y&;yyqT+P>i4UM_A{sx;|PBCaLn!f9|`2zAbwspPIPc4WIcQ(tJU8ebzXsCoz1Jnu?6kvmL33bJ^=~yA1P!haFqX zHyZ)jKLtav*K1@pzdgQSmh*9d=Z+#$W^Gq`NRy+#XteY8bsFpNXTeiZrW>TmfVB zY0`6_von^mGt`YV+;r&H==YP}Az!2s=L=U8z>y7JuLd_)yYapWxxp54rlC4L2TY2` znu2+|UN?VyPxZ0{!brN)j|=!#XU#SdbZ1g3#-%1R07Nt2Q5Ek&L-#J{^(Wfnjc0LP z($m*l>~o<(j3aNXB;Q!nUb*qklyzUrM@8**qI`lvGUIEtz~-;N)MFybkW?{+>|(!2 zM`t@PkDL|8cch|v*1AjzjGTr|wGrJ;UUGPPZ22zb5=Z=9KY>IRJ;D00TgBYbGh|v1 zEN>UB>`h)_`HiZKO)%fV2+CQfX^YX z;-jP^W)|Dh3-M`PruA!`i;eYIlEa-DiLW}fA3tdN$@oF`2eSf_Acd$Z+ByZkD)sM| zk0=~(w};sgv`1EzW`Al__}|*r@^oZ;bNlEjpKQjda;rRG{-GiiSl~baAF9k82M-hf zkVWSRy-&) zSx`T`K7IcUO|1ue>M#0x;_Cx+LGwWzqdUR^T6 z#2U&tMbAPNRCPA$^v&v}(QsZ1(|w^IOj^{pzx)gn%36)sihE^}xq+vT;R!H<5y3)t?G!Dz~Ghv|0B#~DShc_+?EePkT zLM}9kae%YAV4-LJKE13>B0zpG_?I8 zHduFsBscig6FnN0bKa6M*thkh)bNQu{6I|?zk}7c8fp;$KaAapA?kgxoYzq*qxU}X z{xbFyAHSj~K}Y^gaFt~(h-?@J&4)c6UB=aJTlUYAD8{8Ey;9<&{WzjOOW)B>?CtGA zpETP1_}z}E`a|aI^3)Kq&@l*}14E63Kide-fE$y139tC11TLO#gi>Z<=^tX%dCj#^ z-1Ee_$@>82qnEq6I^;6_CUxHAeOUHV0)z1*#f!`oUqkM$A3jU;Fn4+i1qBq^0oktA zUOq-XQ}A?b$MkrF`@+y7;luodF~Eb3*%KbstJ(`dyhW8j9keV{yzJ~5K2E6ppFfaG#bA|DoHfcFFHMgD+vqS_BPp_?0mbNASwAEqE_i}HOO5iKLiM}HEuH>gWuM2k_?s>Rgnbo7b*=>0sA|VB#PMIyM zPr|rK@84c6k1pk8aM?~ASv|kgwF`56uEwMPN$X0ck=4ujf|KMDq}$3iO`^{QaCSp? z8#GC&WjF*S8R&-dIeuJ;55PtqbPZYju4jEBVZfjtsLl3~gV|oCFXYz!ts20^J*=9< z8uSx_ttBcKY?cDW7#%*yz#_**sdHtt;zkbp4DDXs(^YLSH3y1fM9pJ~w%lg^hA}K_ z7DbEfhfa^TP4Czale#;^+R#%0<88R<ov*eCsBI~@CMv-U5S zxdf2(Q5|vr1utVV$3p!clq>i)l&YPz#_3S8(Y>s7$VQaRuBovp5G@CI7XyIEeBg)&?z)D6S14JQk?ZH;|53$~U+I+18UldnQf5xUBLLfTQg_&$S^0sKrV~V2x(y;%d$oLPg+rOKEu)6#MC^gl1F(1_J;I!X+cnU`B z$eYPTUc(vf80Blx|zW#^o31F5mlr+%~ zsA=G6LN-^2lGz8t&s^qPsqx#P=&r#gO$Iche2VgYT6*OV-7FJH&=1fbBuBv0RJU=_ zO2vvOJhYtC_q1gs$7ox2>UbG<$|eh#;1&dZD&Yel}7I4qLIus)JJ$*;H6e=yX1d*^jQ-m8#irInaZ z(SW>Lo%4uhgUA5=qE);Rw@9|uFQ@t82UnUI<=Z^>-ggJ<<$29M~;V0X?7k1F9`Hqv+nBcudkp-}<-u6J8T)6KJ|dhiPxft%>Wu)~Z;Rb+D{Q2MLGDY;cNZrs+EdeR@!s}$-os-Cea z=FaR5FSs|mGGglWFndSDixDY&jxT%74r=4(q^H(Nx^BVnZF(1g9oFg3(zVgSxsFtS(h~}Rz>B|j(vQ7?<-TKb&=_Lh1;qs4hO_`j8bIFr*Jh6+ zX}CPDXGrL@=o&|!FPs-kt~Q=$1qtiWx=0kFCmOUkM6Oi=%s4V9BYbA3%+x@sJc4>^ zcCKch9jj7g{fOy0HThJ%CpQ`N_pQ64wyzV5^3w!ehyY(yu(#tyDrZ#;vY!OU8iLX8 z19=-hUpHSlrng_vRt^U}weXJ%b4&dFs3}XBjX%l`;l8nP0^L%jStR8xNvaJP4a3|Q zeTF!9KE-b1oqx(7!NuLb6LAriaza@)_0OXn@}Wxse5}3!-=^ow^L{t|Y*OuNEWz;6 zTKr7atG_V&3G}h+MUo#GUnWI?d!VIDO@0k#31EJ?X7hnf$E5*dlsjuXLG8}3%S`LR z4l(|xnce{=5Ng1@OLPB+pU+ygG~;RX)G;zwMQ_Q)b}=Q1qey<#mbv9A-63*>4=hk%w3f*&E9ckI|2P^LJ55B=m z!Rkf1x$@qKRaCi26%r;Xmt&-viH~vW!GIToZ=>7~}zfGPm6Th zuG8BVWL>t`BRE(F_qQJ;M%B*GoSypKIveG59RO*32SU#Y7<#L`zM}G_(ATd)KTbz# zQI~nVy&8asdb=EE`v~4b9<`Js?lvJD6z`>?<+P;g_INlF+%+`m3o#4`Z}_MaYHmSM z(%s@Zd)Z|u#e;9P_zQld69>CDMidQ1VzkPqQlQ`lqOvVVTg?0G0<%Nx%gXslw3DXF z#yyQJzrNNAWkwm!qgK}xqT)1x;^9CoC~R1BNN{9o#6#_yy2(sK);g{%Mx-76U~J?` z?5Px5FTR+=^vTxf#1um(PS}kt>LTvl^vuSZ@80!sn0n#86VHzL+d8h^WZ%6Jz1BV# zVq(U+eQlRO9UxY`^^DO-i}ko=_Ude;a|r^y%Y{g`K-8 zp+#e-c_(f4q`i1jO`SVD{1l-Coo9wHY4Yq+-k~CscwDW(L!b>9-$Tc+E*nm4m$P2? zC^Pm;)cmes)xe)~`7Ra8|M;9{nLeU+?kO1i(;sMkAIB)^$<1eea_Zb=W-nijp^W+} zHX!QJ5!myihbr!VD;61fxFgu1R7O%oJgXbtt=Xclc2Z**v1?*uyCfswA(GtAP8@v| zVlo=SRdMC{=C}R+f|H~Av<#6gYX2fs`+lGf`gp?n^6(*s&S^UES8*wH+B@B=aFgRL zMrZA7*lfzjJ%j#({+e5t)IyoZ;5@!`gwE+MAaoi*`=)p&b(*WsMR@UuvQ_u$i1`P` zyAJz3kuP)PW@>KpKUWG)Scb=pyIbmfF3->}`#t?$2s%Dv&0$}YUN?K6Zcxw(yyi`- z@otd1RC?#hvffegkq=IC*_mkyZ6ndu%Qp}1T7CaYexa20`9j>sJC2HS$L!DQIjG%_ z-Df6D3IQ3J|F$oSyYXyo6d`iDuw9xJAEg&7sk~^g9wtZ7bIorsJ|ISv53|@oFum*j zvsH`QciOkC?fJeVIcBwrAGR@%g*bhVSqw0RRPShc@Ck;n3@#jmv23!!0c!`x^CDh- z{n0VbRX3vp-4K(85I;_{+E=m98Jl~UKH27E8K?2pIL4?vaV!RdH@%JKt-yw9Mzc=w z`Sm$=PTYw--?UFD-E%{H$#uBxyv5AV^f8h314nm!GsNesA(BA!q4hgSz^5{8v5#;C zUMo;j7rZCEBWGb#=R0n`JSkzgn%p(~jZ3%r7W(cBL&dmIf1QX!)H}1Y`3NL*+}nla ze6-yDRpQ36^s7kYN8GGGJI6G%?@=W+J9Vr3;gq@{?=mo9ZW3~9s1(4oKH~r!@PYAV z&Yk8SvClfmiMemVUd~IRH^2IAEh(zcM zx>d9ym-*HC8;^vR^}clhazyCwF#wT)^m(wwY?YHRtMj}!0R5Sks0N|%&Fe6o-ZpiX zJKeLB2yrQnzZTPS%R~P8wbwcqih{O$qS7nB19O>0K?=u&7;oL=^7O6gay(?!o{ z1ngdF^FkJ>DM3v$>c7u1-A~=`^{Gdhgq$fSsCG7*XQ%RL`1I4R_uJpl7ug+!eU^Ea z)cyoLk#|!vlhmf8Q=gotd{n>i+#pN8qc`LzgKP6MKn=Gb< z)}in`n}28p?}WRs^>kvVOlqOZPvEQXTmj-D8BOd?%Yp~od)CC_%^VXNLn-H@z{}k* zfzYiFJ+yI-D6yr z9XT@a7PYmGQm0!Mps+Y2Z2>J$4kRLzcRaKVc zs3yw;!!`CEc9md=1->55`70eaVl?U{dRY9*O@*qovrstUi+*88ye9YZkEFYb@hk6s z3{arD)b3(g0JDNU#wl}yATu)pv)T4>?~q(gn6_wTb@OhnE*CZ0_o7KK#gMvvz?7Sc z;}WC>B(cT!?#Kjm`++yTG(YVjSH#^Tk@2?JI$k<@2JK#zx+*X*bpq$G3gjJoMyH~% z^f_|UripK-8akqJa#F6v|&^V4&-Afm9Q&3 zpdW6f7z+O$2OauD_7cO2vF6WEy;0MwXSyS6^E~87WQ|xtOQ5CPweC<6zMCS#t@_9Q zxQc{aX9YF2vBSz@XSTGn&bo3|gwN&1{erNmT(xHhqBq$=Ay*Vd%3+N!ioe`*Oo<(T zW{YD<5DHnd5IVB8*1kib&!+9`=fokd%=Et0DD}EoUX#DNY)}+wjIWj)-;E7f{w{+L zIvZZXm6vbBew3NsS{(|0k#;q@B&VJBxCriuoGyHZ7sPIkXpF-+N1(Uv^QJfjIu@CK zZHTb=dGj=xSuo(jq~KeSCGq$Egz8O(5P!1>IJ7tgaforj{0^s5Y}*g})n`;}t%UFwKaKZv*7@O3$g)+-z9K)uP? zUCtK<0^|v7F=^*f6ad=WQWj{zZ+pvJ$h z*)0D!g92no9w0IZc!swY2lMp*ph4i||L4ya`jKayXJ#1dYc{|aC~{FveT@@%WmHQS z!2b*t2l=Sl>9@-lr3sf%q*&*OtFC?$wj^QTSkyMKo^c>XS!wg6$>X<1B@X%;LW(CRpP6G_Vj8p5a z)rQIrCtuY0%4TbydC70PC498fa{Q_Yi&P?gNBD!9ULE-hoaT@6yUbz^G zA}Kch_*vfc?pG7HP_&WTj)i%wi#7RYF&wuZp>Trz+46>s-@Q^L~}xe{do2z*>axfM|); z=|nK$4fnpaab=?W9l7HneswsF<1lCl?khvm&}D0X+sFl~?|lG^_6{J%fn(L+BpK71 zfiU?YXZZnuCb0fqXhtBr5@Tq7Fi0;_Zm%JUw%KgLx@Gp)g|vwkJT%NIw_k~yLr!6B z7s7*4+w?$_4nSg8{Z6(C05ewukS9^q{sYA>wO#lN#iIWcirL!52*>0lXyjceE4zL9 zQ0{;afc0@x{us+97Z5s!XT)tTB9*+X?J+fRl8rQa z$D*mbOsoJR)?A6U#)iNuIAS3A3ZHcBjc{!1X z)rC+=Y2@tC!kT%HO_r^gv)SGV)^RI?)QhNk<5c?wLsxRJAIJEMN(FK1cg&X}LcHC* z{qe?udNomT%|#SNVstvFIpQFIG?GpymTNooGRj^=Ra^>6IlR4iMrbic@sV^7Y(E;M z5gQ@lr+ihC1hJqW(rl^IkT6d5v=ukTM>@T?S_1RFF8Du9JGMAa5{y`~Qbvn26`9>% zvZ(t?#m{gYdrxR$`M&wV$YIfx?Eq-Fn$(U2oB@r9@KZsr*up<#YGz0K>JIS5RFqw? zJ8;=M_<{%KP(Oh-V64?lb=LY0$FG-}$5!Ww!Uk1NIm`*Zi!Fc@<7ytsTA5BQ1^=T~ z_2v}Ejy~Z+{rN?G9Nx$h9%QF@B6Ly0cN$FqE+X}r&zQo%ni z+VP;SgqZ&HwLC-8{@Z4~yBBJ@w|@`>Boi&p^X?IZJh|T21OI6+T+*JOf*(?|AWycA zWWjG(b+-c((^M1-NeU1Ct}x+YZs~jyG7m0#e5b3~qKbS0k=pVwU1dYtuxWIZfdT=dw?ohMDLO|9s9HOcwM41lzyuFSZ~KyDjM!s(ogMU+Q6TovgwqbwN;pS5~e#su~yO{(ocpkvp zIpS(zLqM+42HXB5X6l)_^>^S?dvn0qOXi~kA zi2B~@wk`4W581~lk~%Tr$I%)5U`>6Z=NuM(Y;Yc5>&N+mc_#1NhX1 zWjP#T=NsWtKS31?WTtSab`>r-37c0uZ&a?3?Y7+q=9mJnKgaR!P$~AqJ_!ONd+Kw= z^Ry!ZDhh!G#YHHId?-wN9QCkfv`liPL3vI9Y$K~7QqkqAO7>*BQHI&wPdx0#5|3_O za?&=z`AELNGF7t4x?gL011Y$`_dbUYi-~9vTvmi>Idb(e3R-S@ZeF3Dtm+oOQzLBb zgl6Ehp-4#BPrRoh(y4j}t)y1&L=`4Nu*%1txAd>E?Wfwdi8}xt4Wa2W|J}Kqlwv?A zw525d-YbUhVH5PGS6`{`u0uqKve>RT@9t;4SMf?ayeR=oY~e%`ETU7?(WgYkvPP_` zdIl(}XAsGWR6ptNvu`2FeNR(W7b}NDk*k67)}XTk<<||a{?7^Ic|V`4nFkqN_V)gz*yqxYRRw7^V|S~0vrBw^dK)~N zO+{4(r@G{;7|SOrmzuv$)|x1ns!eEniT0{fH)<>YaNTy7nvfBVu@hVulL-}R;Aw07 z*j-3e#!r;_((6@M)ztm;H<;O+dC{22j`Zo~JXN?^$k-(>O5XS_!C#%l?mRn4z|x{m z6k9v$9Ve>0mf_2yFY~yvQi{xbwm~CgYJv0MTyu6qq24s z3GWgTB6mabA`Pz;!+z;`c3H*w;H4L1crgSiUx7INrj}uiP5-XKlJ`~a?kYnCs42C6 z{&ZqkM0zJgR!Q_pr{HiMCROAW&Vmp_Srn4Y~A%};$z^Dg;=$X|F{ zB=O#e7Z5~3qQcI_MH-xh^D8KM7dltp^PZhO^+=V-0gL*OzoT!_QS9`@`R*;#Lbxb} zM~oV9H9lQTi-gQO5&`YgHuBvu&A#jP{aM7Z1Fzy2h1R8oMpryqxhB@jhcUh5gGZk^ zVU_C!XK>4$IKVD0hqGn8Ki|JTY*%u5_$lG`$#?(ZS?~-(MPVu?PvEWy>=#JYGilJ1 zbUDcY%UiB8%`-ML=PYluk=X4U*`D9RZObks&6~~w?pEsVAb>dW@APqLVN2NK!t<=^ z?!0c-uV7(^58;O9ycBSTF5L=o^jS`|dUTDS8$U>xYtk-J)|fo`u0-Qryv%S5s{BRq zNQ`2?oNMexWE~g%P2(1qys^VuUKkGFNOg{i0zV)A@i*NB6_CnJPHBmF=FiXUJZ|ZX z*M7o(2J{2aI?EW+r=)qO;DVZX%kMehEYHw;T)0bLg9NvrOOOxNB4fjB^#&SG8=KAT z6km2ER=cPz-z~}ESUUrqt-wDbTUHH4YkX^s17mgue|uq~)Fj8e2w+0CO~xL`0qSHr z&mxm*Ro?!HR~3o@VqHS5MF6*^`wK6@9s33I#k`d)1cQ|hwQlnIId1dl#o7Mog=Mm6 zTSSVNl=RvkGT1~Vkq!&#xO@b^F$t9aE@hO4C@4o(S-)nm{ zntMV@d^Yz~DEAC9RPBE)k8z@4mqrR|L&knkb|J zYgeWEn9mARs~${sF4qX?;4Pr7IR9<@0qzdzo6o<>{vb3>^Kmg&z1oV8n3CE&z)cJD z$EO2dtj&ApH!RnGp`u&a)_%>hefK*-%Xf#gyi|Qr37jd|Vy0vr?cMzzX07_78Yr%o zip|n^VvhmqDrY-jA-jI}Kc+N#3AzUVHKws=Hj??PY61>pe(Le^$0w>M20*;q+kZ^4 z0Fx|A5$3;9bN>u{I1}H}X54<6`(NvS>z$bX*WBj!f6Z&R5fIQDL#PUd2=oqyH}F)ai?=;mC)rx$qwA0a6q4phSEa z`4X|u2E3pZrNphz+pkCQ7Ux%j22lH&Dp&s!)F6KeYS00cBj!|q_tIa28uBkeP3~0o zZ#oF?f2M;}_x&Mr!kj8VA|S`o^FU-#D)M{rDRPc)I*nw|yySBpm4-RHUWzTgzt6M* z$;YN)#m+;qP7_3W4H;43rYixOZVNVHzZgA)@meSvYQ=euYW6r;>jYx^$EwJOe`sMzsofV}eP94o1 z{rl&!7aAo6?WpWmJ!?D+F^C|!psuF+?IWxLnpbt)YrP(4HJ``Q`YVFcoN(n$qGrb? zvFQ{de~J7R#r_J(F}N4WZd`6Q)$2B^=S(Cf9GXX-_1=oR4L(+-IBq%*UBrtormMIu zWcF0#0__4+YC{yWHf6z~C=PdWX{i+ZU3JmC)+yBrP%SY;SI1(McqBTMQhH%K>= z(%`%#(7yUz7+)?RS_rOfly(dKlIP~``YIv*>&N(S6N02OP+R+wCcoM!X ziF*0Frdc@*N+$i->T*@5TBoQ4o5~5ls3SUcpZ&M zOwuwa_DyrYnkrjI+~T>ip>gcMqkxnK`OQM_x$U=zk4ZgyCNb@1-CbE51@61sL6_>l;Kz9uEXL!HScS39J4yg-nxk0 zGut+RsV-SbofzX-%WaFNL528==}nW2@wKNyX;&Lo^?4tCT5%*<+Qwz>1;}A`^a{-< zW8~MrooM!zOm9Jp(B;hot@4TY>@FMEJmHDXe@zV0pl8BqS5rlNL7`&%wt1mH0$ii+ z=(<$P{Ir=#we}p~Kgh{#B^J^^=rW4ATq+Q2zW9ie#HUeBjzvyyy?D`gyC@hdcURJ3nsVE~4g{LYs;U*cf}5^zvXfU8-E-2-+hh zr17mI*NDPr(S3#;>4b+aBk6pZEU~rYwM)7%z9mr=QG2zt3M;1_Kk{g6>-5FvpCi** z;={VsjIMC3_aD(m%u|g9$$^m5HJ0uTqn67A@8x@uOE*8}IP6n|ph@J2r7ma(@*#_i z95*&Gv%Vvf*aWNHSB<>mUcfhh^OXJU4_Vh$@lGGhvkiaK&$jt9GZAIu1fzzgrn&Vl zvcTbFK_{CNy}bl;f2xSjtvKuVNz;AQTn(Ih0tr5Exn=mh2B->rf+TU{QA-d;dB%YbLAH5-Y2&ig6Wf5_sSiwor&`>$Z_6|f zw}7SWQWUP%OdQp%9f4yMe}KTMa4RWy2;)&EoPnr~Gc1281lB({+T3JNz+B$1mf8i~ z6;#P6Sd7Dyl1Pn+H6ZM!^Ww_Hm@%9@d9AS%1ZIp;0fpp5L; z=ZE6+RFdLftAc8Sfbc+AE9eBCpkV|!DV?G)a=Vynkr*{GJXJS_-V1bTrqjR5+Iq$* z)n_-#>6V-LPUJd&?sD&q2zD`<#LLJlqupmP%wEQs$g%l(t`|JS`WBXD3$MLyH7t2! zv@BKGe6rtPDw@~1Godz{);&9~Vw>AhZXnWN$VvPZ78}V~l#SfEvrHew>017U3!SfJ zM-t%d4E+_%-}t75@}q#?W!eX#%FNN+>yj3zI@U_u({6wHge7Tii{H5#WCtrlyN}94 zn0bDjJhnH!md+I?Gyx}Ql17qz&AR-BntaeP8V~BCI!xzV?Tp5P4imXS!L+rjxJGQkREi#pmyOUzbm+f2&8CahhSg zIUT;6TRXd(CM~D+YvB5MD1c8lVGKvj{}ergZTuQ5q(M02$cTOmu*Vpw`X5IOsR87Q zAKzgQfjg=JhLm{2(-C@txp7*Jx`^eq!5&?}LpwK>Buo)!k1slo{UIY~Vtu!Cs0u56 z4yOq%;b2)2Y>fMq_0)&+fpc_7?Ef+EeDp68O4ZGtFGKgJ|JB+gGx$eS@wcM-?}uE|uu;9`!~Y3e z_+L+>&rJdVmW)W7fm5x%q$u}?&ft+7R_>Qz9KPsgm? zRQ2!fbF41V@`GTJ=OKT0n|k`Q@K~%KWA+*G-l}qbz%Az)ViCd(^IKl3t5CfTG>wPN zOSc2yr!+8C-~|M>&%`Y8%gYnQlo;r=IOJS7vUy*9xqkKRq~-s56=hBi{LA>LBjCK zX29z;*Ahibbyj<3w$Z|mayJ_b(&<>=JBdHE*Gnx{TB^Ch! z$H`)4rt96Z450Qe8CuV5I0_kbUn@V2Vbc&0%s9W=dLBwt!0jzep!t}61D-~GBMGOW zQ!n5;k?BtUrYyX+CGkejVy!%z8wTV~SLU|1kif^bcA^V1HS(R8r4kn&Dl`$q`@^1L z*!pa8=5DRv3H0jl)k2Eg2HTzuh)i}j%MC+w#T&BoX%Ej{A@fdiDy|H-q}Ug(1j-Sl zgF38v&vR-Kc)i*fJ;3yF#V9pN5|!p+gJ>DLbR*-z-2=K?SK2xH?cm=GFRNE~MJw|$ zegh=@CoI!Mf%94t6Vck&<@yACk!?J`ozwBd@l2{(LVprhz}0VY1s-s$QPCu+KlP_J z8;Oxdn5y!U;#rW_=`N>vu|rKkG)iv#EO1Wpci=_y5pxSM`N|mVDiMXh5nBS^Brl== zb^PQUdSDUs8##;#-CBcxlR5$}Kcn5RaPf%#AV)zP=V8+0({!&)xQpOA_8K}fFK>ga^I90N>m5xDJ>PQ4YcpL z4tnd=ssqBZR@)cWxXZ15cCd7KQ4z}M(yV*p3jKsdhHMiV7S)-Zrd#3y{fg_-J>BgD zUXEkzhEp|e-T=WEHhNgh78TxB5N)t~9SZW*Gn&W#p|Ks=RrV4>R>5YH%@Pf#uV4Eu z)vMh96j-VcVV<39ww%3Dh1sl6t9oRgsO1ox&2>Awm%UhYP=?z9rS_|Mv^*{&<}4^x zt&rSEws;!6Mbbey&+{aKaTj+ALij^OhaDW^DPvj4WPWVb+}f}%UpCf9Y*S`l zK5~7mt;^?2z0soO=7n808&y%P;Nmg>J1lONj8f1+=4PKd3+w_6Bpo7%l?<(G!2Xt(H(S;SUne-l>hah;O7$TJ z!y3qzHxSC>vH=)6*)xYimm9HpZWNuW`OA!&K4ECOZmNQSXRr0JUscqEV+0x|Sbyze zbn8>Es7*P_D$tho;(EdalP^A8Va%pp@dL%IR^vn>+>Wkt=~iLa5U;=GjVw1rmkBzD zd@2!GNEx`SG%;kCRBjaV)Ou;^sP%|c=J&DtA&cURW7UC$lkhjve5iM6#)Gm0tn(W= zymjVp3?AU8(@m~rQk*m^bd@xyc4&FY4rn=FZQ#tu-FT*Wkhvx?C z`{)q@iFxt2`*Q%xUP-Jrx;s^kX;ek4Xm-li4K%`E)0Czc;VMPZ=jUtu*6;$cFliJw zU0I8m@@rAWNv-RSdWD6fAJ3&IB+ST8I4~q$jvzPca7VlBjYOWdSXt6=n1I-BD#OH% zt#blg9Q-GJ9~Q9xFfy|0M{(il(UxY>M9{_97^l1*{u%igXjx~`edipQ@AKa@3jH+{ z&20f@dozn8IkJe&>x#n;?N|aJn+q%*&YB~b)H$t| z2lr$t|L$Zu9FFKq2_)}H;PR-7zcSe!O?!fh=ZVxfyjP4qoExaqks>Brtv?Mv^aYv zJxWZqZF>}dAfKFnC?~PP498Uj7x%dPDE(93D`gD^e%5@FS?Ei9bxoo77lY7sLv3R_ z?qF**VJDllO_3WVgX`$7$3@9jN%ojnz8Zz^qAGe{z-U|P$QL6mHcmyo_b@aYuciBI zP-e-Ey;!yTIkgD{dzcg6W!Z`yy#QxYYqarUxHWlu_EMcxFGfB6ZLVrQdGtzf4@X7y zao!+|s(4dLb>ah2&qmg?O(OhJqIs@Xvpj_wtf;bx@c~N8z02Rg9R4ycBETPR`wT%$et57qN&Ei1w1pXTB27hl*k>J% zGf_cIi!1>alSRxsz>^|OvVmdY3QFE)G=ydtHpZadb zIXT`oPz6<8@$OYWDULUm8u?jj1#z%pK04U|(@6%Shz4zZ@JXWupr#RpE~DZg`=(x~ zvsK_+`8cyl)^(CFh915x;tA9r_Q*JrD*T7V_#d*Z6eKCB)9RF>)w>0;W)n-|yel)F z&m;DC5kE8+2kIsv!<5gT0n5*S^^RC_vc)wtfcUvi#JLw_P291v^Xa1Fp$L}QcA-8P zU^iU_eq(NG^Yj9V0{(*)t9~9_4j3R#_(76DK%&?1^Z$%_QK>)v%<-3c`u~d~?*#TU zv)#BIr8@*=nEoHKN`IhNrYRT1rTa+}_3&Kzy?XFJRg*gvPW0@Kn&FY5^_L30`CQcZ`4W_s+9Vv$3e;BMLr=IKi`GoQvmL4R5Ki}%O=tg87d0czV0;Y{!a!#mV-kj#0EbK0A@3w`vTd1WB zlBWNV@sfCnkn?mK$Q9q*5u=u*XEn(iv5(9W#Jc5|2J6_#8?K_od)6~fA1VLDevEwM z&an0lYF1+Hbg1f#FfBEF`emE6*S7Q;=qs(vIHsa4>m2|hbO5ksj%R9m%l;ikGQO)LG@8a zO^xsCzSt*!)qImem4fP%Kr-%lG$-E)p12M(!R73A0*Tf;7_E_Q*Q2fXiJMD91(*3_ z(BG&Z{IZ4I6w7U}`hLqy{SMR5m#I;jWH zRA?I;%mBL>ZZLXze64kG8)F$F{#&K9F_N0-P)x=cwv5TPwp)EULH1u|ns$TX6IdH7M%MdR9}+s}V`B%Qg9Rr(YFjWc?!Q77~KD=3DgE z%`IOSS{I1;Nsd=w#tUEcZHfj+*_9m~frCVT^4`Yfd|u|`@wJenaJ3tjB^cZY`k86= zN<26zsj+djd4i@0aY#U(ZDM{-V0Zynv1mRDB`*+nAzhG8@~s2Ltf8*bD#0@J_x&9~)=(0-?DbW}&kf;3qy85!^EdmC2L zXtxhQTSC4t_jeE@wiVeyqiTyz^|bzNR_9^BRb$4~ViYGiHkc=~B2Tx?Fx*0TimzNQ z_gpd_cD9rZJ+75Ib&^$%VH7q^MjUC$pN5a@xtPzdo zk)WxE4997wJkl|;^ig_C0}K#+wQ(cv>R9L3Iu~!JN8`WxWbIygTsU67(1@a+#)r@| zY(U-pqs!gd(GSbC4XN09aHd{-Y*5frx&Kw2?@d8bMfWN6SQ8w-2uaiCymAhD(TuC9 z#~Jf-j~|I6SvJ5fw5}&l_F2wW7)EU?lqdS6U#_w}P2I)N&8b(+#mKlyU$vgV+oOIi z2k~1ta{~DYI*z5!0+A;5qZISD+5oQxi9VhBIw7wbn;S zy1waI%bDNry_ERNE|$uh``*+W_iNAXAgRw*T;$d;*Ieb4Q9StAKqr-Q2P^Hxy`+~` z)#>a#x9;-E`*IswsvoDUey#(TCJzt&@a>3M-E~DtKg!PAKSqvlx>En@jv8==2+otF zJEPDqPTdT?&z)_-kY>78&p7fGzJ_y!4%6WYKm+h6&Qj>wVe3UAxga@0v zm;WDI-x<|J8+D7KB3+TDC{aLAs&u49M4AW)C`gS`rGvE45*xjQj?yAcq(*ut^xmWs zO6W*WC?P-+@4Vky_x`x|{>jRk$;>>HnR(`%efHTK_e%aaGqh+ZwW)I;tl4JF&r;7&{1ehYibBrDB9sudGKHV7Ix3TQ*~qwuewmrlN|ISV-g0*E`SSGSu=2 zN{|)%owY?W^D@A#ci~?j)BB=7X*D7?*ccV7kWiIt$SX5iGJbR#taJW~GKg{ex}*3c zRWvl)p}WoJx^@A?VQh!TILSKN#G+qP^Y&Y|O97JtyVU1$TlI)2lC*u^mi!Q)IB7hI z(T}ufG%H{+p=`Sv2D>GG&TOCjey$hDG@*F^-I`-2?-c4djb7a#QURiYgsyrx> z>ce;8t36km9fNHaK&cII92w3R@R|hxOnf{bzn{aqUK54Lv%}>3$xY15Q=m$*4gky_ zLCaF&y3GZ4n1$KVRRUkGfuwqBGOgiWLCKa$e?d2i0rpz<-0)*Z+?e`2Vh= zk-Bi7^-HQLRn5^G;n1FH?!B9uPNrwRjtT+&2Z(^_Ed6AQ)a10}R&MjKOF8 zj;GWs!=$7PH%c9l;A|?so^St0wa@$qXu(n-zF+J%jrIEV-v?^c3d%AaU#SS-W%nAy z&UTPz*NV?Za3`dY9r$)R{O{AsfZI0!*o!U@DDuUNEW*#JP2qp@N)KwmAF&5&jm*IC zodCt_ss-cK|FkKNrvGor?O}0pK6rKhKc44w(|_RBEi~h*d6e-H%`%`94y|dg&kQfn z*l@r^S0<-i|MK}yPu?5*noCnH{wNYljM2ELZU&xR>bK|%dha~;B;(&!2{!ODBo(_F~pL?g*lmkNp9zYfn}(Ylxu52LNI0$f20RMmG#YT7l#!B>5Y zo9h?Aai?1y5k zx!_P;F;6^Kuc(ig_H&sWGP&fe{yd~-{}9D^}>9m;g%5VQ>!D!3UmuCpJ0e6F>#sNpRu@x8o;BmUQU1lu<;paHIxH&nKJ z=}^$U{hjTg!2Lf*$7)NzCm!gG7Z%6cuc@Vvy&-yt0=7V+_Zng}*P@otemvB+}dxP_{th4m>YeY>|Zj8#wfHC zl6s<+ns;9x9s!ZI=n47+4{vL#Cqk`w9}M~$mvuj{_?jE`pb3?3R%!jeBQ_U6I)-YHH#`4ex7M< znw}@8vS79_d{{@=?GE=s-^8lrOhb_^$u%R6hK@+5h6$IHo$9zw7tRXuk*)DANYN%c zzS)4qT@y^V6_*EGmB>#{mkX=2c)A^2XS2dHH3YL7vRA05B0^P?H}vszmM>Zo-IV<} z7a!cw%AX02-!p>LyXEly)lMZm^7C&|>yoIi+1_%0RlFfE*c{qKbX&O+j2qU)CH-v5 zo7ZE*hU~g7j#vIhIz_zSLp@Pvdh&kOm-lXT4vMEvXdlC&(LnqpQ^g#L@``-87g@1+ z@{;~nwgAn$N7tCJO9FQ)Vw@&m^w6AEOLjNr;pIDeYJVEF1im^?sW;*86r^?h4e_)lT$P?DE=B#XFI&dZKwk-JT*zZExBef@7Z+KA}4NnCnYr z+_GGtpDa_E7o47vS*Rw+gn@_e$_2Y)q+ z2-kgQrFn&Td|JbD`#?xi3$K$m9A5d(^@L?W%*yLy`=Mk>G6>bbGp&^x*rkzc^xzYUaGuGU3ESZ>{~eLZW+X zkQN`zV!Jz^lfUkvoJ-EBAKW5ZsL!%5H&5a3v4t$9<}?$I7kE`WrOX4((Ql}5k>5Ie zRbQJt*gH>MSv(MW_jUo_2b$+PY+)m%DPmh7cOm($L$N<87rKw_(4bj;TzColhCc^!^QnL3b zI^u5!+UBj_1kYB!;qABeVz_#DW%?Fg{$zh^}cWcJD`?O@< z(eix+Ibg0{Q1Y4BN1)l7A3=?mbw4fZsH%Ta&yfCgto_D$FZt}D7{{Jj#>cme0~fEy za~^nfB4@c)kdcZ(Ipmx-fJN}q_UyLi;<#cY-ur$W11%@#)ltT;$qY|0k_*j7$m;d1 zToL#lkWYI|C~Lo(z;2L(Hj*hVy=Z`T1qE#Hi4>!RTSwUF$QnX0F?4^)kL$2Jrg4~X zIdYI(K;oqg_?DcS_FH~GS8=L`gn}K!u4@;U%%ys-hh9!EvajsBl-!f=x(v9#cAS(3 zZkulUi4A7d3cNQzfPBsb-fUn0QFU<0%M$WR5gX4MTv1HCMvSq{Ki$=xFrsi96_*=8 zt&b&8sLDS$S)KR56#p4^{R;)v1v(*MNe=+CT8baBn?jidv}~b{Mt_H&9CwnF?!`?Q zFAIdsr2XLb5CGoEztBr5BH+KdMC(I9PP@MtMPc2niM5!8x7o6FHbx2?2v?sP8OCbd z2`hmRbtxeDFq{L9O=G6WsutZZryhArPV(yif&eT^>BG-+r-Z-4tTMs2cOC#?OO)~z z#J0cQ!Ij2+$_;cV_7K~NJy{2$s^|&pWk{%LdSAj|LE%Y|hFV1;9INl_Z#hAr9%bGs zdOsV83a7B8%c_U3zJ-Ol3UZK>vt#ZjHS<6{tgK!s_+@F`QTI7V4AoYS!Wimdhp)aO zoy^9;vDTz*?dRh#&iBbW_V&wsF%!9xeq#1s+l^7|?e;WO%xwt3KrWFn5|I7UsnnBz z0|)sGI^E_gEjo=e6xbQd>OFx;5}EN0@5n-86c%s@_UI813@(ZJ%A6!#-95P8krWJX8ZO^i0l8NQA&@C(8Mho;(k!LZw7drS2-xSx599irtL zJX`FGMHjE~l4XD0)!&7@l|t;aa*$ae43rN*I3)cVZXbP*|9xq*Fj1oK^;W`MeH_uM z602VAYZt_H{5?j?LFz#37`!QkoUXLqyO zu3pHQhcOR1WoJ*{riPfcr10&HjrNTfeL)q~$tP{MgmG?7xYBZ<(5uuH&NvFkzNB%R ztTRKDl_6B*p24CEeo{7Jsa}p^JS5Q zsd&DM$y#jfNV(Q%|0`bZCG3L?#sMexscL@#(~=V5C*3%=H1d{#C?7xtrHI|>OWebFcCY%ioGZzOsR^vT;PYR$hJw6hpVEbt9QM(X$B#buX z^;W!jPqFfk5)*I*BD9B$?Lu4xk8Y`u1+fH~??7LMESPu^+*N2!^lVG1)1DQGupCs% zCJKRE$=y-`R}ASbu{`WamsX9GCnldv^G8M#=a!-EF=&DFcZVOSa!bPk058 z{wZMzGfW-EpbGD%Tpd7GhDA|;L3?5~SxujqRM?B-QgKCdG%_L0@+qHdz-33s(-VMd zK-Eng%@BCT%VJ_Kr{rmeJbyfUx*ibyjoT2E|*b@Bninr}(X;NayWuvz$ zGHKq@KO)vn#M6|^1HkUzXiKb@Sf$)`X_?n3? zh@NyqXiwg&1K{z=3Fx2teMU|OhW0rCWXeaV#8IGb246xw)VzGiKcc6S9suggMiQK> zD#O>1%NoINBgE?#G~%8j3^bRcL9GjSMqKvZmQ^){&?jpo^STKYm2Wt-YpSd3DX#;( zW9#?-s1A2M0iYXrE+Pw{q0_>)?Kt{&!yjJ6{>2yEk82YE<&iwd3~=m&q1bjjyp@Bc zuC3UxfnE7a#E1*820~$H&qj4zIvy_Lg3hp;CxTl2%T7zKQ1FpbBBw2VV0k5U?1%Cb zk_5?&01UkqHwkVE7bg{rQu=?lx{vhZncKyC@-N9HUJJU~<-|;3)BBA6OYaLXxAg#; zty50z=uuH!rb&tD&t%oQ1?{H;-Q)3d$tdlBz;RE z6`Z@T*~r6puz6eVQUnNVqmWNpH8bzPJ7ix8aPq>ud{M~jiZa{WvX8VL)h*h`JTA@x zboLP^Ry82A8)U}!o65IvrJ?IUY*ts|}ANKmSgl+iW%a;GBLM(t3D;oh+sFqEO z{1(AifMuoS)<8!}^(L_5yCae$_>bx$d>E()p~2*8)He6iRq6ZWZz7Aa-2xqYj9n{* z<(gMXjQSJJR7BsW@lt4F&61FDoUdRH-z5Yj&soPIOXY^PXOM*Y4{G7RKQ6S~v`hFa zBx^bm_%OS*sAAq?Q0Dt3SxFVPpC&m;iM$W7RTWKoG+8;@j7Ok*7R^_n(!A6 zA+5CZkNEBxB_*|9vi}ri1P}LOzGT|De9jwGhyg+Z+RKf4Y^BKSZ*pg3#-lhuVhgKB zEi0+8`Gh_n2(F(1Khh^X{znDFk{k{w{TS!#Qssd!aedjJwGMLSsBAKuliE6Q#_b$a z96qT&IjF4@Lb1W}l-?N6x0aU0a6aa>0w5^{IhJ|g#+LHGmJqfmccZJAPnSFe=j6%n zs;tkNxMvWF(?F;swiw@+vts=9`?QUqio%Uky76jqs?_Wc&cNp**Ugd+UF@D}lyY&F z>Z##T?JoD`8N0)5qToy!*6bNvOi1RXF+F{cK+wRJNP9OTykWb(g?F+Lu3J@sv$#!HQ)IBmd>cjyaH!Nax!GvyhaBK_vvFR8~IGLzQ+r}wro zh$B$eNjS33=*?{#U$B33)E{ruRU&)|mb8>1+iB`r<6&L`6_fY7HSvl~O^pZMV336LSDivp}L`EROF>CopMYsY$vwyTL*4*L1 zuvR09AWF+5^6a5gBdRwaFh>511MelG+t7RfH&106__&-t+<{<6QjwJKvf)N^7I#28 zwdiX%KHZCuanB_T&Do)E2kM>sl02rQABzqnL@W0nC9_wvkEk&`$z)R>NcWG|Yl79l z{=g3a(2E7WV?GW(%Gkz5th|Wkj~q%C5UR?Y&z&~8A|aU`h0rrSX9)RuCCX8oGr`|< zi@fhdLLdjM!wL)@Wd(Sb9g8435SY*BPe;6^h&g^7gvrblg3o~(XS~kT!)sx%{VS@s z!ymo$GolKdGnQUNVmJtq_@8CV0h};#tSNu+-4Lw>%zU!?;d2&QLDCPQ$6K=+bpFOy zD35V-@WacE7KfeQ=jiK}3_9FcQC(1oMdX*+_eX4(^CJ{xFDE8fVq$GM4Hqw zOi^lRZVJzx7f{y?ZmMDS+G z-gBwv1_JcG13g#oy@9hZL~Xo>RCRaj7|d#Npzq}UK~-@^kD6J&dCK~fTeI~ru;kOs z%3UEgki=T(T~9+|j&91!v9-FIgI_ z9nmAAj4?r-VdN=f?vwis&iTE!)$f|L)du~Df1;p@&rs0AND`7KM2{786jp>RE#Lp4 zt%8EfSJW$Y(!NE_QciA17ag*5(g9uF#f`T4W`4U&$#@;5*1C9);(4ojrPj&53IPBX%m5*1(Ek{RZTNHS;nAQJ=4*{<~^aLivLcn1!v z5&><(2=MJdB^TxnL?p)<0YR@4^z)6WLtMqssLD-a=*l$j+tFTj8@Ve2y)T`5i{Und zs>VsXJ5}A%yvn<^QO)!JlI@dmpvG!3EeX=_W3YE z{Oo?}yzxY7iza@~fe`U4jC`)?kgo-rln z)hkEh+&aJrqd%LLpfciosoA9@so7V^_UfrCtHDvHWjX?9J+E!32Yd}oOrG!=gPhI{ zVWYPeA}%__LfsdLARe5H#pk@IJ7 z#ru?_cZ%PZ9u33RUND%88&jOJ=7^N~<*n(uS~;#UlL^1uS*ms8LEJ6=O>Q&sI+faZ z)?FGlD)TZ_5ZUn}<{ko&EKep>!TST;P0b>p4Mlk%^RURqZWj~*o_^vAS%l6Xk z50V=~c>1T>LJHQ_zru=VPaa6Cerz^Q2^p}_ItT{Imnm={6JKG(5P`C6yNlXE-pH3w z%o-~28TVtG*L3l+Y4nVXf~1YuSGQN~D$XXv)*wVW(0#XcyP)CS<8xIL$o$M);HzYX zNE1_98iK`luB3=`kWi+Y7RN3bPmF;HX~Or|>;Y1Jk=RQdU@ijA`->UM&vS^|+%K9@ z60G-S)x$i<3o!Y8u*YW%X%6Ub^V#n0P4X>J%3N5KokdY4`vSX@t6U5kj zY2!_u-t}Q$`>RdmWt2Ztyk9NmAH+VRrhm6qB$gsEFqmMD<=1APU?AVA_{L3Q{x zSH*CJdllSkj1aJm;e0OL;ljN*D5RUk>UxiLg+^d12g0a=w$Z882#F=-Qa)=Ol6Os{<5p3h?J1wn}x;(X2~gueNK zBZYHBswLGWEKGoq?N@WDQFFsH@hR-&L|xuG;z)1CY3byX@d`-6w^02MuqMv80#ea z$~j1*$?Ive`5&3Kn;w(0M#D;BCk26Ocm)GIHY|6%^eE%Lo9iWyoto;lk8#ECb39q7 z=oF^PV1KY6l2CD=*4V!C9S2kXtgJViPWeJk%G@=vy&+5Ue5&{kc_d{HoN{_KKD_u?J4pVH;4*)WSG;Y6=2Ax#KEBy~#$75p{ zQoLA7bhB#^#k(=6{Sw_!4OQ-{{{3+NK~1D%wLDAEO&|Q)o(8 z^TUxqk$`0(vTv&gab@6Hv~%8=OX&pLmxp`<{WbTK-1CJsIpx^Ki21FSS8K_sim#XZ z>4oTn?AD*|Uc@~6JddulxgJJw!OLj~_8Dh)ecT;Xdx6PNe1!`{Xt2RfYL4sl+hCj0 zllyy*D7T!w-DK!HuXogMwW}!Y&zRR|Vk{ltMnd}L-=25r)9Ue0sxs-#Jpl~ z7CqK3*ol8|Q?_liE~@bDHJKIaJAz6)UF%9buLB(7=BEWKZP*n87(5|4YNcui%Fofb zl%DnNO~{N8;ae3^X$4IUcOdGzz_owN2j>>N{~QpmHuEt#M22%AgmvZd+f^I8W@vy} zWsSD_Z(Cnap0cl}(Vu!~YWE|~JPG2&&_z%vmW9NMy|&TJE`#5C5>&YGEK)1ekS0l9 zB9Qow^-~(rGxNLjaHQ5q63{cU^!@J`F}ZqtOIe;WYJ?H!xWlt7b^+^vGlhmQI=Fbx z^4g5ev@oYoA?}z3?8RkC@Vz5=rUq|_bI75hi8Vcw?_q+7orB0K}%;4S8#!*&%Jzn6$Rwn@hdw>_f z9(|DP#y9!0Gq9I0jK>ZTx=9i4ulq>a_9XOtoC)-4{7!`kN=hv3)782zCV&U!39pcs z{9(mgKr+I-?w4GE>+VR^4a1ZSe$;;U^58*&ggSab=&$6EWDK#?r(L6Y!YbZO+XN5^ z)y(o$IVjT9e4^(Z>oiWXI9Hj2Mz-JBESqigoO^~V*Zli7OjG>f6Aq6#$&cOiwddA@ zUa0E}?q5F$dqQ{KyG9)* zgZELo@GB!~b9O}R3?E;7bc5tZg zziLiP12n3Ca?v1(Ah_To^TqH*Gh;v!{|$lqcjO8vCMyMsw<~%` z**QFofMt~n8seRd>OpwPF-35Rte==y*t1Xy4X5GR6r0-ZxE&fGW}=s+0E_`T_#(gr zAp&hF74WT>xO@sd@*h=<@l7=WU9lf`kR)O3S)$@Ypwhho3^EBeygZnDeJ7zU)+}Z> zXUo?}gL2B$0}FN5sW-zphW*x@1Ijo}XL$vJ?Kt@;N-ZZwKFg2XziOE3oYUI6;=@!J)+ z{6WOS068D(Sr^J(BJ7B<`Qa1zMkXp}2$`lPluvnVfaLrOK9VGQ!DoYkfpVc3b6bj= zB7&Zrh!I~%fzEC+Uh|NN9ru#Un!8C^u_-qt9yXgOo= z?l7uYoY{umZX!e)%7_s8ewV`c>&Ie*>RP==6&JAwlMi=(()@LzSR%VUW(SOoj@nNq`&9FkU7L*-VVTq zLN)p-e-G82VEFp;OTgWu2rjKO-0Rv8@cjh+c}OISdKTmEXT&L`qE-#`=@sHw8qkXr zS!#LNPD~1M@&#lv!j4`V>*1M-Z1M|R19%WU(qdL;kJbU37nVEB6nHUu9|PFU!`oD| z0Ko7#g?z3@5p7JMu-8Px|GG|~apLGM1krRs`X5zRgV8^#mM*|m-Lgw%00A(GzlN&* zqe50U=N=MM`A3zEKIMkv^6BH@Ybc;ch$PfS(-EYv4r^b+l30L> z5}p;_Hac;GVjidfTq|t|g(o5J-onNNH#^ZpHoVwqQ`(xrCid}nbQ&E{nqwWMx>7>T zY+U05CLVo-B_Yqj+X;?HCRbPfHzGDBd@<5xRWX-)Uh#gV&eW40A{KSs%1AsZGn==d z3HxC%JAGwA^>*?R+aV|E&yr9#^R2+a?WW=&ZnMNjuRFTltUlI@N;8|qz})>2NlsFQ z9hT>CfztVA}>AJ4PShZ|_xZtt5b?MIQcE}axg-voPmuv)K!JD*V$@xq=x z*~hq=B4)#pDOS(=#z_M6{?Wmqk``_jjZc{eI6xSHhHp#uHA1}BYBY4dq5tRJSZ*+{ zcbK_Q*Rb4^r%^jfREiTy#srOV)b4Sm-gT2A$6K#s(i?s_^O~KSSP$Q8tmt+gzXsG? zJM`AzKhcB!BgaaYwXE^H9Th=ovPjr}-3|Nc0DR|MF~w2Bae{)343o`~&x`gz%gi&( zuO|~avJ_Pvu1~C&C3#YVgnG=c`E5v%Jqelw!(3%!JbpNtxfL5t?Z*(*Yhd-jwTc6K!MO=40BE8~yC)-x^`1_udAo zIncpr<7Ym-JDTtGG2P!uDcFuDei{SFMY{ppW)s}1AmOK_beVnv@M`gereQ;Ta}lBF zuL#|@lF-Xmmuh$;2J7&m`L=|NgsgMEI6*t{6Pqp-(l&}YV+6%yd(*_*!KrB%l|WKR zH|!VeJOCi-&9!xe0DJ~v!hz|)K{H%93?~gulJ06PnXVMMp7Lr+RkyMhWP|EP4a--mv)1>}V2eXcKt&iJ)Qz(^=aTCXe7+N=Mw#s4CFeEY`!upe zMe(>NeLN=_mKRyD`>Ww6aveb}m1D?!ULP^Y{o+3;R9sz0Q;zM-ocVh~Imp;cGTO15 z(ja!o_Pi8OAGryJ^F5TgrIILAhIY7xG{@Sbk3Lc$dRdlbYv5Zju_LoZL&a! z56g|X|5ST-)gC;A_D8=*pUUosg9)OJpflZL;wkP+D>pq}_Tz4#MhWqBtSb&0)73TA z=IQ4u_SWHt!Og3ptx2o>)SqfDd0Lio(Fz{j*9QmZRhR$JV}b4c}!>(_jbL59lY*495Lu3z7NASp`enpRWkUS?rurb4cWB=Z8&a zn~2%>tuOa3?rwR;{A_&A*3|TTWQ}qwEy%5BhvIr>ezc+0#kxTvp-(0172%ySDe^U> zFDlW2)ewdI8fA-ic|_lL@LaR`pk|27){+cg+DTwT#X@sCxfWpTb!(E5jY7*PYI+^6 z4$ol*LzR400$i~icJ`Qu!fqhz)zjT%0rVOJ;$@x9*G8A{LrB{q3n!U`0qHwhzQK*! zAyF718)4_Nt5|!6g?Bs%=j7{F7^C&Isx!>_t`kh2IZnR0k1STx@3yVF2;>rU(9Z<2 zZ3S|N(4D}M4&4}AsLu${sz;AF^Hhh*xUp)fsSfbrl?|pQZ|8@76KFh&+ zeR00hqcYst{DbfFY{g@_m69OFb7!dJQfTNuDtj_b7x$&iVa=)heV~5oXHeIq`*GMI(1~`$XOZn2su?6^*&m_O( z<7iU8XRUPar}DiSDRA2%lU5O$|s1zJTc&T6}cEiy7TT=f6x+Vl~z{GmjSxN zui+WOCvg+G`pgAGa#A__6DVy;&_mgczMUfy3LTqTc~5M;{2VB3e)gEU^`e3(+V%iF zNgh5i^DFgjGgWVThf)(Q5W{3g&)N?+*!RI4&m#$=IDxi(M%Yj)b5!63Ux(c7oyqet zz0+p{ov)YUWqXYw8P##Mem2}mapzY7br~!|DpE`N9+%l{iGf17m^7`7+U-A@VaZ`C z7a;xCVqi%c&P8L%lKa7DQ(~CasyBBB^4?&ZCML9Dlu*0g zvL9Wf9r$t3NrQQ7hC-ij?Lprj-)7n9qp4O40K|Rlaovk##Lk-2GMJ{@X$g=vZFO-| z8enIUA=>+DVn*N2+&fKKlY6&zBg(GcLhV+qzl+0bmHZi<8Hb4zZP)eZj9oykz&JGr zRHPTV#fqVZ%iu6&_LB1VC(S&N-3K;bbkDD3eTWa^v+9gWkb3YnmafqDp#5%%34S^7 zCEho}^*9akkw8lrDeq_72sSc`(D@-D1fVty?>=0hquNaXYM(eg^hYEk@PI#-hTnYS zP@mMfTJxxCC_kL1>is~#T{_LzKI#s#+?pUURm;nG!^M*?M`+9uk>gp@n?MoI0yDLm z0dVah+s#ELt;ciEKl^cgeB3%b`4(Tv&RIDu+H$dt0=S45kk z{PNr^s%Cb;op2_YFfsJm?<(Yy^kf=?r?w~SEwNDUdBtwJXudR+x#=gY+}{P7JUGw{ zjn+9pp|7BX2s_uQtop2(%b|bzp-nsS@-kTdp}Vo?gPWW~PP=*-G{KLkv4oxZ+;2H@ zcgzcQ!(lS^#pT4{`^NS!M+WHGoh#}|q&=E3wl>&E3g-3H7YdJg+oS|BS^H;YLw%-n z#Kw-6kEsF_ficNz-?ihHZYyN`@j!YuX~T(2CqQm?Va?wK*K`MifxtqMQLT!SCkxf+ zjn(>`ezZLr@Jw7mM0A`r4dCC)zwpuerQzfxbs*(gOmv(3+(-TFf`aC0mu3lw4Y0tY z1FTpfS4|w{zcydTLBd4y<3vdM41dU}n42%2XbJhbwmr@J;_^f?3ZJm-;t5!etKV4a zl@8mG5%kfW4`$vK`Z*klkigW1`}7xSpLcuVCB6zAoGc$j5&nbjN5WqSdH^mhwzM z0E$-FmCxjN9$!+VaPS+D7-!33Jfp!E$OPqD;B`DG*l-ycTqPoGkvCBqoYg4*wMO!V z(Zg>wTo=1&8JPSRkBi;HvGmF!fHdHp%zPA)SMQH^wCg0J!NRbXOmelGV;V0r`~6vf z4!_*ZcLW%!L0S;pP~N9?lioj0X5P>)dq{-CJmdG#^(6YAqnzU5BWHp6 zg3zNaE9i6fwAbJTBPv=*ok6jVF2$kP*IoTR#F^Rea8CESxjEEDV+bZmKTVjle^ z@NvNM!`+KFSIVg>-_^ME@OfjfN#4Gois6V#c*t2Px`;lAe_qdLLK>>Hp`E%7NVKR0S5szk`QK+5CSy@9*_7`&xUm&;Ztg!WQkutr zEms7=!6isRsc|xe`_-8C^#jb1z0noB+xE!k3sW!|jUtkcb}h+aMaRHHQTs~Kog@9( z=8H?s1Hy-u*FQI#2;9VYYU~WNeO+L}E1rmo3@zlnkU+J{17HwMkZs?HZtF zi44BbFY|n*rC6-gtAAQ_XAcks|J2^;L7f;cbBFHtD#*heV$g1kdVSznbBOK(s4qrk zmJ7Lei;t9n=>Kc}lPRF#yPhKokTSpORRX&Tn=i2ZRb5d=UO%?|i0K@%qT{1urKMfH zD8vn7g1YGwOO_GLe{Z!r)r&^kdj!~*zIA=T-D!(o0&Zi&tn% zLzu(3A501_j-yCgMOa4}mI_mgIjlBc^~U>kS>flPEVgzCyn6>ocxnzy(9GrL4u>=Q zvyZL%YR}s_rlUkiLbRh^m!t$CC7I+*+FMmzx`!#TSzSmzw_W%VL``chi8lx5hhm zG@boqR1?U-ga%d@sYj@SJP(qKN*AE0WwyzRUn1ES3lOe?&ac|HFVwiYiEsp4%3Z8o zF_6B0pRFwCb4{v@Wg}1MU%f{g%)3vvI*Z{}*0BzcZwKAVjc+GdhdhF4*IENMUMai) z{}44SVr)Ln7a>W`^3nLtFX>K}P}&r$DpB(yOWq2e9uOG?-q{;P=Tqqi(4v5Sh{Q^C zdeRQ!&zmK3l691%14k6O4P%ZZr&d)C)58Ypy9b??PIL7PZx_OOmeJx&6$S7ST_F0t z2q8HRaNli$nkoP$;jJR9pO<=7kLDzpU)aawj3)F3=%fa@S|G;L+`hsqC?kVQW?j*% z7oK;_gZI~T0&oe7?CD!HU)P#9GI2gy_k4Z( zJ12lcap#c}a~iSpXQ7j8(`1>dKL9xJEp*?j4nmnWN3Ktpx1S4!&XN;6k!OGy?nWwU z^42kyeAx}YzXCufuh6qo@FTYW_^d!C&}nF53*LZxq;=~!BSxKJec&So0BO9ihwiG_ zlLpV&=10gK8S6~HnOUlP(yg33wZU3XUf4gSTL6e!-T(FJsJ1QKKj(;$3Mf&1*__%& zU%Q&2Dw&b>iSMDajQry9ucG7!YJDOVn%4Z7b?_5!W>#2Fy~V7V<3px2_a^J4H3sm- z3GO@;tT#obKskf4zJ+H0&VnI=Q0sWA&}k`11T2rNw6}*Z%`Noa1Mq^gN_@Q1#LEk( z6Z1|T-0T&&@E8$6C5gv7quL5u{Pyq%2{Bs3*29Jnr15~b*PNfbxA1(L!+o~|c-#qR zAevTR8_A)&DHHE{a+({Y;8IHIjU6smacr$;ma)K|vFZFG77>))%jjph>>!N{@p}Mj zRkZ3*8p!d>sanlNI2C;FL~`H*xF`bEkkNJw+ z@b`VlLzP0JI;a6xqyiwgLN$kM>cD^8{mH9n#(9lsyfnS~b=T^yfB=P9>Tj~g)0qB# zNr1oM1Df1eSjWym&nB!cDy~UDTVY_jWdEqoRlbcq*};CIoE9$s<1K!Vo$( zkaDIJ=tQNIJRm53X935Uq!A@Bh`qu5gjh3&U}n0d(G~e8v!ubiFFlXJt2QVK2N@>t$8!eO z_rW~tiwSP7>{IWp1Oz!XzP%lo?&|7&(#&w9_x>{d0-mEl6aZzXjv3##8Z%l@ibu+5 zrt@1z^}M>qq@~|I?(?|Rw~N9%p(w6YVQFS6Y<$1*XZR}Ll77QS6(OG6*W?c)jvTBj zo<}aU*8ZcK#o`!XdGX}*R`9vUKdSF1mxtToGbOw0*N3xdndjj(S_m>-5fVuLDr`Jj z5*)ejJk_OjI;EiuLU?K-cTAq#=o~w5t3zLhCet_tRdi0Bw>55=>|FTPq{R)`LX=s)hm-arbwkWKFRtr$|2xNtyhuvAFlwdtG;3^&A1> z=o}P8fP}?LGqSk{Kzf3dwwKiKI@vjP%j1D1|ENT0vWg(Mq-j^TqkjEEcuY6hjHftv5F+Y<`li`lH=|U9z!BwRk(Z-p9g$c6TZKgz0&D}t_O&7 zp?hMaN;VWB8h&~N0O)Z@f-46FF4hG9e$t8hingN;=D?@~uDFkbP#bE)U*UG)xZhj1 zq-@q|xO$m&o35v= zN*Ykk--vK-epn5iNq#SLQw!7tS}@)4YkmmtPw-A$T&unpv@xr-$UHOr^7T1)UM{=k z4@*sWiLzTLxMKXS=2X4E%a+bS1oN^EU{Hr-H#3tSIuGMm2OW&Sqb=~hh@Gh?v0b=< zzCL$5>ZrxDOiEI_@F8e7>A@fD*^Yl=ZGdQ!fKe$=uOmUZ8N>{>-?U<6BqS)qLw95J z4hzsrZz#ijfb30~0HqmAa$2TU78Ll3x|~5ye7eya@!{8-kLBv+4|=IHiX}~Du$4cN z&OhL`9oT)zDI2`s5scwR{AuQgHuqt3FBAntq?sU4u8@((;3~F1j9H)Gah|_RdX|IC zxN05O9mwtfYBW%UoGF@T^SO^@)mlPv8WiHR)`NBudf&VkY=t$7g{zwS)9hXbN0AKk z{>sR+C%YcsOy(TUTvJh!@Q7G3L0mV4G`65Rw*BA?6TbN|js!D!i*h1j@ni>21$Hb$ zARE@S!7Ipb69K~^;0m2W*x4jh<78qDJTR5CRZkO{C8^lVJ-YHHjVpD7db{8FLLqd> z%!EJ0OhoF195ekM9jtM^Jk#%+TB$Qw2nGiXWD$(E-lcz+=SpVat;)f8P&A2pai3}a z4ODlr`|dKAP4K8HWP+oy`A`%OHP5~+@w+e9qlGtC&vN3Uv)JUxxgZxUV0#%jEVSeJbr5~tKr@JRHcl{# zHdphFD9J^tZsDN9+)VNLH~GCzDAMB?vxJQfit`_>UW5p{t@xW4D_tlFgiNc> zcUnv68AvQQU#8e@YtQ`o*@cQrGDF`I#sA7& zqZQzd@-6-Lu5i%d^b8)?xE7-4fxHfVV(Yv9G-CeDT&(q!g=QhYe${FDF=4tvaW`p`y{y#KJXNu{%byuRQ+* zahn;Il>7VjZP)L&$Jz5sXP_0Y2EPPlkDNL@;C0vlk0xU~&Wg31FI9*3Rm4lU`wcrD zo-?}GTxIYS*o(Zd7KilMHMrwSRs5m@_BSpe>YQ#hiEaT7Fc1d*61?C^+)4S+E&^9S zbdSIK0IPQn?%%96E+WEL_R^NPZt7MPbh}993SU>Hm)Qy0%MkD0*o8=`E-OfRU$kx2 zk8jTl00^(tP~R>P^RdX&b)g_T{d+H*A6MP=j1P#b#BT}3y-O`D(os;6B}xts6pXzR zaSP8Q=2&g4q$Hliu%(+b@P%J<4r~co{n7&}Q7|H6{X9kHATvb_@r`Qn#^yf<;J%NC z6pl_%OnADVNkw|z&V8mB<43vaS$7vbc1>XSCg7EdS}=g}a2UAxI`S;t^K6p!p4`~W zd;u58@yS=5l*rI>+8;Q?<4A$z(d6gK$8NMZ=zXVKGHB#m8+jp}$$vyy4tttM>2;=U zv~0_%krA1 z9D&Cg?cPkySxyXfC29w6Q}Cf|@@c0T)q?NJlVuCX%|@uXQ=y5Pbl{ME6fJKB5k>w@ zNvqJ&fOO@kJ%D^MED2z!itSztp?-%Je_(PGZC0}5st~*Ssz)Ai_Saa$K5d{ks+_Xf zbMpG&is^~{PaAQ48T$@Za|##S*?Hw<5m4~wInZ^X)<`B6Y)~OKV0YpjlFF4o-I##z z(i%d`>OY>%bt(x+FM*2;r;Xu=w2mB*C>&4LZIHcN;eYX`6iiryax(0t4u?2B$FN71 zeyCLb4n(YK41RSVjC&+4M{rT`f+YQRi*?}7##23@^-3`GhoQ%Mg%}2XqU{VEklVr9 z6FIUwYG6B>IWtT~gZ|<(yu1kbd=B)pMBnQ@z`q_z1^CySZ(751I{4(TnXnu*q5spH z=QC0()_?~oD`pzT0p07O35eEonqmm*r>d1&o}Y{-qm z=?w^{0(eomYXK^AFL?XyJ)^|VC5{QmpI^oslkk@<%9$&Yin}Y%wpEcwV}1TITLxH; zwLN+<)~4phe=fg59;LeXZxRxf0D24p!xe^$TMe$m24|UxXm5c0Icz)ewUpRXI<#|1 z!rWm3U2_XOc^&gMEfwRl7T7~S$U8ar4aGPQfOE#Exn|)d8io_Da0EHE{e!5~5{JtV z`1`Dicr7VkEe=0uIA6z@^L6rAX*rT=YE&LyWWg79zK)g7%lp|2PtwwKJbMt%s?Tvp z*|MO5CZ=|HTZRGy4}lzr8q^&3{;f};7Fg^;Xk^fj2k{1I_sYUGvWPs2WMY5U-8x@8 zyEc{ga_>mFtdfz9&U-Xr5SYT=KE1xkjV4EZLINtkPc=-rZ={~Mnq=R>Fo!%S-}lw8 zJqqTreaTA!W>Wdge#cGpl}W-{f&`Pg6;yQ+2Zqb%$wSble`4ogHH>9%o5Q9z8;Gne zelpqds6Q{DmW)SpxV7m*m_QcV^!AOtCLNC-8dKOE%{XSHf--nRp8sPL{Q}=Xr-( zq#bnEP2?~}j?=uL{vcfZc}}I{KFK*PjqobsICO9Mi~!gM9}{Wf*=vMz2pmnctK!f0 zuI3L%x#~UvN?{Rn{o#$i8kzbiUxvCbV)XiMIj=!EmhVJ5X9W>_0M#vUKrWGw;|%lc z(LJrFM%YgMA!Z)kVWTfJ2kbWV8Q<2vwvU38fsTT7ef$Z^eObr%tAmD6eF4;44vlU(t^S1xy>77#v@<3zx#P$I=IYu$4 z)O4U|VV8W_V!^>69BN@5pZU;EizYK6;KSBZGa?lB6#D5i@2`Kkwa0s(uca4JW+pq$ zCL8&60wF&$gE&%9@*h8DbyHoH4wnal4Ykx&Ag%j&Ly>5E_oV|+>ecfzVBtaxMxOIX zLqV%z9Fw>?K0dgVxoyhv{Wum$jW3nM!FuEgY9zkM3M>k}u*4Qa%twpD)|LT2@1|iz zGdM3x?#_j~FXs5>Xj$zz4LyCMsA%9BQg`6qk?rZtyCw#ic6PA?30xV9DI9lZ6#93G zT3j1m1kyg=Y=!lJ83SJR70jDD7^KL&`ip!OYSd8KIw7h=+S%3-Y~C<7x8|1fb?a~? z^C+xS6V>^(E<E{W^=Dz|UQswcp50DAEHA=39CcefY=}UAIj5SEd0}Ml zXC(P%fo{=6{fCI^Lzc<-9LZM1@jVA>QujjdU#t7Wy()cSJOvaoYbnbYni(8fi`O%; zT?eKH89j6b^J5`pQt$cRU)Qe8aGOcCJZ2lB*^K=XFO7LfJ#EL=01r4;(wD zhatQWtH1Hg;{nFa_uT(}UlCt=EQ7S&0unKqEZWvl&V!o9Xm{?vigSv0z$xWZ znv;DsbgDHBFHNf_t?MTJuOXtpc1EL%RR^S-;5*qon9{z0*MOG@vF0@NQ!YHznW*PE zRjKubYr)IWyQSamM#Z-i1VHw{589}(w#yeVOkMq|xq%;7tDJML6K|h!eO=Qjk1O|+ z`O3lZR zH>HSr$CS2FC14Z)*dBI)$Q>%N?uy5(m#LFUKX+w#ra(1GD3j9R3rvp-358@+#kAH+ z9i^|UMt(6jrI=1EtA0+iZCUO3DfIe^j_X}%GopMjr&=_&MLl;Go8V7vruJAy=fk{D zi~S?{BpstKV^HgC8Qq|m>TVeI*$r7Bp6l5BGE&FM&gR6-{!(Yjrw0FV-BY;r&1HZ6pYW~B5{5@OTC(3!D`A8-oTdKJFOgoKfsgH5 zjeElC7K4{7H`pL|nc@;}w?lI!-I~c?61pGg)&}cu-bZgL@%wzYK{YOZoPSpg=hR!T zbnBi9Npx5|Oex;>5bx2|TbtM#wjjsGu4>*>a%BoCGuu&fbLRpq*!t|5y#tl*#|X^) z9S?Ebj-4Abua4~S&ENg5K08xhUNh8CbKce%v#U3IKTL05HUn38AH6s_An<(yPkC&F z4aPVhDUkoXkEBi{c4FlY#?>ZhvfusM@?*a2>qEHU$*IraqSa0z zCKFWX3)%;uL>8q8#J>I%;>@Tby;`?RLwhcN2u_uhnkdD7g9q9DN8pdh66EkUH&!tq zd=c}jpl$WS9gl)Z+(=#k=v5$0bIqS_vU~Yy1#eBX;QC{y8b4UV=I61O>y{u-GMjsz z5(n_C;ZrjvO?lLs-Cz?B%0FT6inpjWsAHzLRwK$8@JZT*0?USzT)PM%j&~Yv{v&?> z!*A>lxVm$m?Eh~k)*+J37pYS3=ud1wJz>0P{DzRc`OnLL3|1`BxeVvbUbFaq*h3GL zfP)m7l^Ai&kSlAIvi}g(o`o*P3;%cy4H)Z9ntKy%;6zI~Q`FSL=}c8L^Eh~Ow3LDL zy23smUfz;I9iiXwf^>jkH(>ht!r?eYFj-`0Zl}uSxJgD4YmVu_KlipXJ_d(F`RvvZ zp-tU;?(VtE{r?6YbVfbSP4-(M{?$XrVhmyEIq1<|J-~}n&)>PO4Z7lH-z}mg$T^IYGuR1~WDa$7QvNSKY2<=8t6bA+=n4=?ep1gQ*2#;>&5(WrdNyyr3-@*-3$_G5<= zb|Ifz=6j@a_E6WQ=){gXtYCYICZuy8jIwv-P8_3kzb}oehYj3wbZ4BxKGp$UPJM+{M z|9RCq4hHDL2f1}O@-^|2cQ|>a>Q_jDFIF2s^KZa<(>Sh&)wUi7zC5p9`grjy2q}3g zKJRbSi+RS&D#pPfe)OG-(zhgCV-asCR9fINn!0tx^vsX6iFsiFu}o=1VhBV6cZkUV zwvBwM(>bc~A5y3eyxbs9zJHhT{W#JTNohX|SIgQmLv<-yL5SFC;B^kI65mZ+jd) z!U>!vS>Qy*@7tA{0yM<$Qh3N&(#bILnYv{$dYQwqV0oZ9N5E8S@ay>!lXviNR#u`t zbSAVbZA_S7z=uP!WdYNVinz{LC5`>@mO09oFyt*bB%QQ38b+eaJt-%iu;-5M{=#}k z)#F9bn3-Xrx7r0K*09{WRJ$RgZ=Ug2_{KMHi|dtw$~Z8S>Er3SkkPeP=)$RqN8xMz zAa!PK5~-42!QYdb!&n`X0gqSpI;#ecDjRRQkA)_Y$8cRNd?kn69DAx=UwzzG?rQV9 z%*2|EvLGs$XI0tj&AqtcsJWx`8>YSs5cZi9Db6HwjC45XbA6Q^BAGIcr9TPU$CU!E zcmy96XHB7{6X5!!@sO_RZ$pz&bCcI3B4@a_j>@BaY-$IAHpdp>gL#1ak-!$%6*!h- z^;gubG%zzcB@RmrQ(w+T0FDbUTT@+v*afP0BAD&lZhwjRdK}ka+c+QY9Coukevt;- z0#M>*#b$FhHd{9_qY1yAtZchPj|w$$o>Kv773uBh;rJA3hpd7(u883VBh{$r_N?ja zo+4NWD1c%c_SgeVE|My|j=a{dwipv$kA3RHV&F4n?WCn5O=O~d4$Ik#RNgw!#{gv<@#}Zo8?|>FY8>$ zcYJRn9THWkMv{fOVyo5ZDBcaEJz05tFfcIUb0k_QDPdSSQ#Bu95Wk3%!eY=c5*%CY zKPRY?mm|#Hb{T^q?yppN!NbX}RSXt*_4@nYuPW=S#rDfoZ!@G{z4XW2WmLRn@=3V9 z{BYM);l)R8me&VUQ3>KNVy0Ix-b3%z0!=$jl;XObW5jv&;v_z`Oa>jrcGkO`!yj4f z&GY>Jj&7hc{n@p^vykXwENV5VL(g;tm(c$_Xg11sEXnetm~zmU=P0TMb!*u9RC6u9 zWYKunP_$}Sz$B8E#io9dLZU>uSuHxa4)Ngoie)L(Hw(`)|G6nNbOaf;ud9uSJV;3? z{K=R6`K!K_Izj+?_o46BrR6%jA2Fccs>Zdhyy-)B}d{=TZKe}ro$=(q%GlWB~ zeE3_-y3ovg5AhwU$V`mBHBOzH?I+ua0AuA^RH~VeqaEh(m$U3+CuPianz836uw~n} zZ?^#9z=oMVV4TjQejc)X@i5rwP58MVGCsxjFs>H?jXH57I3J@t(`R_om!ALcG*gqE z`ALhutJ7uaey}p8wd*tcs=mc+s@Sc)>JbUF#Raz382BI zi{Y-ILKU26?8>cP0^lb z?VaC$4+Jyi?D@`=QU>E~u%WCsIgenSwHTLMq9!Ds`2RhjUaDB0)gBQ;uXJlFs?*fZ zNG(KNo#&$-@Opy6r;z(@50G`oQbI;7qLCBZHl>!g4Umc%pB4A zHVbSbt1s+_3~e(aP4wb^j?Ah%KtCfMKEE9C&@I=C zMg0?rWvp%h8?ZkB;mOKC*jvJtt^e}{v2krdC;9t3+aS(Rxz@gsVNY$K$AWb2hafew zKRm1Aap*zaD{jwtE7}gD-@?oB101B?(j6ln$3$xsK-mY>zhDgFmS7e552ArhAY%o`pr+>Fv2>T^y7HpnHcgLriCO}P|eB?||z?xmbKd#StrDb#u6=INGKaBQwoa~9S1~$qAC&{9^7TiLIrhw)(~hhA4CxBXyyz6BQjR#w!X04_r~Di= z(a^E9RzlyCwYyun6&Yv`Rm8Iv<~|Tg1bi*c)tMp}Xwu|}!5#Yj9TTE+_*ZJPUgr0( zaE&>Ni9UU4S>ANfR3+rCx{&^a$LZSuJ^S?s{qnWbx{moL70ll=vmLl{!s&#k>eu7| zTjl#bzwrI8M66+}3al@_7BT_`WKYG%2#^B)WxI4<-DFRD?2FCk-$Uqo-?&J=N?BSH zBZS{ODe=t-hlIaqGn}q{Odh85d#9g;A<8yy{ikW+z!m@j35}L!tu1PR?c1&a1WF$L z8(1ek=52kh?OoT^l~PBwjG{hW{Kc2-7C-PM9u;nSnah$#{}bpZlee~3Wm?g(^qoBC zJVGWpDu`$vVZ!?FE0Ey!u!0c&Au4j$5G}$&*Ck#IRU%_WND7^6ZDZ}^%+ggj5E>Tw zojb~g;ZiXQ*6whGWAPEcQ34&p&iA5MzCQmwt=SCzcZQA~c91i1y4v;)?I9yK^Y-N< z_4Y;Tj6;oPn9Ms#X_t)3Dz6$;tOc2`v&!d*>-vvd3*I+R8k)+iGG)7uOwzqhl~lE{{?2B{)?YJatvPBw>L$z(ZiAP? zY!!s=L^&VgmsM9_Xc>&QvFSlm+iVQd<>2wxqJO8xd}Ze5yPqmPWfi1rG1(hcTDlIf zTBoP~gjTt3s4n~bJLR63NkS>ZJJ=#hrw zKb+z5ArifQZH5d09pe%9#rDWlE%p3S-YIn=Td|zig&$%($-XWncQBKgTr|RZ6s&fd z3PUo=9G;r(?D^^tM?zGLzEzATt0+q5z5KS5{CvhdWxB?)O<_oK1Wi9!T8TpKSa2XB zX4GJ04%7l>FA~I8{@O-QoxKR_2YoNC_IB^7`_ORgSt>3)nj?T$<#O*>x`UYV;30C< z3^O!{mGVrax8q|>dd#y@chZ99yYAueQ4iW6%;pU3QB(Vm;9*~(`RD%#$cr#M$yaG! z^O~;r-eHm!%3{38+W37LM1-P{HZsgZ8`3OS*)|%lMp&n8jQ7?Nl4k8~Sf4e<_r)1q z*F%)*D~y6rvWtK%lkEV&ae=56#(bVtnH^nYuZtZ^KGhW_7q{64K;(S>EgC(boZAKfsPoEj5+{5k^pQB!X5-x ztQHU*nxq4yNp$@@`bH*nwIJu~$-KG6RIYRP_b*~&4Hc&s5x4PDa>o*&14q*oWDDn5 z^}!w!Yn|1lfei!6#izcB7NHNo5-7R;)&sl+whQe2__nk^(KC68pIAA6@3hT zAgZ2cJ9I+>VDcXHyvbUFn)dWm>hB^@!B=vwtkE6MHfbXT< zzfSkD(iqYN(ZMoSuwLY)SJy% z+wkEag|;Fea?Kw_ZU{rqGcy2ji0IH&pV8v6{4Eg#bl zJk(7)MdEfO3Ua8WtZYd4FEIXzcnXh{&ua+^D(N04Z3@9^8_L5if(I53AQbSlg@y)D z1&sSv#G*^dfA1K2dS1uQuJxsoB%~~{&|Dd^y!0iB+hzwcgK+C%;Hp{gKIfouM^*BF~rAO2Yq!yD*}vzu;L-<}L}+2ocGh%v?^>Irn~*ez?~Ypu%8Tr$9p&mZ$NusPjC?y?ro3Qb z?~=+lxuCw@b#V!$;GU0CbbdP8PafPaC>O;$?5sWDG;}&^=1ELByn|HdaB)K!&*NRd zji$Qer6J{t3*!!Z@SWR$hoW7k%)mm4S~zkTL7Z9l{Rzaas zao}7~XE~#&@`ysVxifIqs*iGiVuWAc_1Uk&hsgJd33$hAkyeS!Y5ruihA@4CW_fa( z36szom}!qmFq`i{8j!*oeb!RCXjMgTrOQ5kLFK0LPo@1JanEcPE{mN+Gn0Aqb*Iod ze`hLu9McJ^S1N8wy^-anot7nuSb6wpm*yeuy~3|F!smJ%gz92k>^?0KM7<$tu%ktAgM?1IGY#+hLI=y2p4&W83E*$$ZgO$Y}XmPRJ5N$P!97(i}tiJLkCpT^Z*WrznR* zq_%o%aAmyyQx?V^uLPNoN-=x$9APj!GJ32pjGQgINO&f_DN4(9fL<7pLH}r(&G>zM zr7`ta7S2Y>i_~zK?TD4iF>XG%FA{R+L1BT8`tz9+|LFVVAN{kJ17?luDm0AzR|ppS zhL@Regk{hV*c~+Zk+;LN3#7F46T{QDku>fpakybwX3om>3wU&wZDq2;J03S-_G|lV zE~b{_wj;^d*1{P1wXrV1#%|8ru``<=!&YA4w%F-0R9e%Z)Y#Y*offHD5;;zk3liug zsgyF5FG6__-dt#9KWgF1-<6@C403QO-96$SXvC>u#j<|utqQ!+sH`0%?>Qpg+;SeSjXOC=9VlAVRs<9no^EFFd0Ih z4HWjgJyjRU<)xx>C%LN>l|VLFxzSd%)QAX_a4zJF;=m|fDD)N=ZM&*_`2=`ew$@f9 z=f}wj_v^tH!#yj-I39K1Rqz$v&%LzKNGlqV81jN}tB?qiw+t|7!|!Fc-rV(f+=l(g zsjBZL3kjgW*hc5#WGg3~pmI+G@dCfnVumGbMeXnCXfH5H-rO@!9ATkLE}p7tO|7_W zM*i*tRVL*>Ry+cfb^W3TXgD?0ZIU!9m5F2WX#S-S_e_4k zyN0#y}npJ*;wr_n^gnjYi0&Xzk`RzvkWtOjPYYOHAaR z;P1H5lBMj!UbYXQeJiuaM^S$F_i0Q`cBdpDFmBz*%CuQ8L8Y0_Q@sOYE%mq($r_^+Zxq7ju zV3f*lZ}0OR_zBZiuO6pMSrd*Pt=)|YSaa9+ayhi7Nj@2MG z99*s_JyE^{&Fyu!J;8dd+&=4G;}MqGYwA;<{YhcSr-*odq)0Xd_@$Eiz&go700;UbBCM{8 zL1mDxL`tZOyjiMU^sYx2h4Kcl??{vvri9v{`=u1@elMxy z?#h}B8plz}mNAgHI1N7JcL(cRytQCia>>{z%&1=ia`(Ko+_cBJm|Smo`w9?|Eqdw5 zi1HR88&_+dSQJ~m(V^OcQt#YqvT@wKSJAnLa;Lci@VqjGiL0GV^}11%rBK?~ z8VG~_5$rLFI4IZ9$gdK}5S3CVUCMIBAawo-4-q%inm?RhGp|qna>xrFNr#-QewJ0R zj7Z4JXZbqnIu;f%J%4b~x~BO=4d%d|B_&=IhBno#4vy-i^&VJ6rX0HOm>2bc!z~D~ zX@%a+X0^u)17(Y*a=$;<`^nB?-X>@Y<%;RnDQhcku6Pmy~=7tYvVxHoduFdU*uzI$m>m+Qe?UD(sLktBTZm%yL+nFWt% zC!B`$>j-l&WPs;)l-hH^XgTpg{G(wU$<_wi3Y~uavLTf z;hxW-SY~EhV_&X&CIKh%UL_;lGqFhXM7^9=>to1Hcrb>{CS2``{V@gm>K4_xUVpxvvQXn&un&Vey-{Jo#&nj!F9&0v!1$3D(E zj2|=u?6M4gS>0$fdbw{j#7oUA*7hmVZu{?sBSNTUZG5OkfrYUcayt8kc#A?-ORxX|z@4cB*O`8>oo6nF=i zP0vfYR$C;T8{q@)c_SoE$u)Ak+^b(ZR|PUDS@0&W#aJ2$ki)i5qqt0@Q$2z z96_21)}}e)wv7#5ovK)R9f1WtH_1x4Kz5+bSk!z^PizlyGm3V-K1qRT?&->HJ142( z>QNM=oUV8D(xM@I=`nOWF8G1j$A|s2{q4P)l+-=uf`@y3E=~_>suzfjjQWUDzkIo$ zN#-yV+i`t1gG!X2%3?7e9A{MB7qbmpM|!JNcG88CW#l%pojgP?nSK zKZB>jRx*|e*D+(g#5vT9atPJqG8u;yX0FA4q8`AeJo;eY6`TiRz!U9&nFAPhnVwCv z`q?I@_?b4eojuDNtZ!Hklnhib;B3+V+zBIE*xCSz;_0D;x4AMB-e0^?N;9=Qnwo7X zvK$%RP9#-LA~ckIC#RX#PqMhm07nZDkm9vdkAEHnK>h}Vfp}Kvhuc6IezVWl`0UB; zYQbB$sv^jywVsezy42$dq5NL5Yj(~b1R3-bAnJ=~Bm0YS2|3zmn-Dho5&tY16)4Ze zcMPNr_(p7ZTXK#=$5lG^4*>9?Lc^c-DtHYxmv|9udL$(Ace^vM4HMh; zH>+R@H(vrmjzTx)2W>Psm)l&Hsf}aX^0H;rP9epnPwl|V_qO*-0w+iko@bI=oKv3H zi>OsLmfK>$iMtMRCb|zf_Gu%568@`cZipAo zl4aD@=0c7n-F=#K@yzm8ZziEnBZgK#Nq_xJe2tp3BFE}fcMa49k6^y*;YX~=9WZAu*ZEbY`~mB9q%?^Te^~Go~KV>+ecm3??q<>FtuKCR0zTv=y*7fr58O zFrW_f6NWtzIZZ@%@)-Y~Idf-aGmw>_=$hrwZ-++}+UTNfewlxHgH2rJDba`3I3Jf! zkqKjk)wF2pT0sY~>zsX&6{JPo%+Hi1qBZvZBT$m&2s%?~fvovczYm`fuT`6MdfwO> zeNfMFN;y=$l`_EBzUi?cfmEU_+1Y`S^YNu_l=82Muk9U}pS^FdPP_jI6B=)oOghx_(#tU1EGrAp~8bldqfo>rA|~XDXI+*Y`;<#!7uUfW})1UH7vo zx;IytOJ#b* zbuYq9OG4YCoBR&AFz0V-7cuxA^i^!nv(6{*Rr#&7N3=0>MrF!mc^&S14ZcLUN%+k2 z+$f$$^TO+x^`Di?#RqLh#FDHw0<$4}E0r6}*3z)?Lj$8>gXz4I!@qJ%RE^71Da3zUnsxZNMKk`Cb<_ z%NPXK((tie0cTcu7LX+n6TSZR?f?D(F(Ov}fKEJsee*2E&{Zn{8qh*H*1$pT-hz`F zElyra$NtwnUeZb0O3v}K4QW(zFKrh#mHHL>JqVN7>JTeMjydzbr-1(wXjJuT8BGAJ z=VK!Q^<|no@Bt^3;L}zi(O=qrEMX!X4`t+LTzjS>cK7}F(0ssni*^Zl>o-D!O)<^l zz0%PELQvjcO!$1RC=KS^JGmW3Y$UsGESYm+&qYIOZ#J%f{)xh@P(nRuVcdwu?x-` z>$>kaBl8G92qu#e##vxvi?P=#McIHS-29a1R~~eIv{XhJ=Wlfo% z;ex$gPdH@JCt0r?B2QdMAH7%TtJ#MjFb2}jY_kec^F5!S^S+w?b}pX0pCS|!WP|D5 z`N^I}sF$fc7-J>3aGFPa$QPUXU8reSd7}R;(!n%G4*Ge{ z{`V-u^{q~GmQ{8j`9!-OsOn+mZ#9YcypHmQC=cH)nhia-$um63`Q$+!+tU1(Pz+v% zSjjv#-np1(i(J-ZD)o1QJ+CA5?2I$3=5k^oa-I@d$DI4o6Pv0llz+LW5R&k8^vV9Z==*(6bK+H{uJ_YC zaB8KNRP8FyIX{<2`Y?2V7l9n*x&{A4-W1MtmBw;dSN+d0$sa*I7pc|Svm@e)$ifoR zG0rIKy2JA;6S(j%nSp=5&+QO=y#z64`_RU8J%5{;B8;31WDC1cK_}k`=3&or25XE4 zOaIQ$B_3S@3rFc@rQ^P?LS#*rd)Kn%I3Ud4w6ANe${$o++u(QrBU+k}dDT~nwF6Jp zM$Yn-omFp+vA&3lCs1*F=>B~N%gJGrNU+ z`Qu*%5Ds1(OZJrDKy}S2^geJYMbEMVGbsluMafmpcMrt~y~R+?G?aU=sxR>)H;`FW z;qQ2o6baVK*51V06icU7Hk0?A%39TYKTDdwZHwJIXUH2A_g60V4+nK)pC!HC4QaIhrKvvRX9ds^D8juNn4dl}-$7B=LBWvhup(T-} zg09j@vl|S)>kRxWF$$ib+O7S_T>Rt`#iLDW(H>9o`U}rLdMjQhg?;RT0fj28_xeEz z7Q$F#jMs$*2A1aPRE%{vK%UDM z)6udwHOH}PLnnGcE7ki#PbPaF8G0AdDwwg;e(K5Db*9#ml1hs14 zYOA02)R*aco&>%`=b|aaZ@m8f>}|ZE1a|tH#cLRW3&)#@)P;0#q|)T{YE%>XX6Ja# zasoJ_ahtg=_JD=34@N&f_c>;()Axn<0VC4BF}cB~a!!Ll%coDu?p{yL-+GDr@hm}{ z)i#pfWIM`qZN7pwmcTbFQ#0dB^Mh4NBqd5Wls6j0Jb5YTydPa$@8|={uj)%d!oA4i z=s$aU0jFL7rDds>sWtyI(>;9Wj0?oi++a_8@~}qTgiG9bBjUv_wErgw@mDz#i5!RJ zaVY`6V-qLQKDwhooPrN;tUu%KLbUVLJfR@fcecmR{yGPIYG9}oqlJTxkHRWir2p_1 z7dUN>=DW8z1LI)1CFfiDWh%?L}!|+_*`8`br#YKA(`3_nRlgy{E3!h@Iu0 z5S*OIE*KtpmD?6<*i@fOVOMoLZ9$#OQ4~1-`soQCCX`;vp;1M7K|{*>8=h|0F*=nW zEZ)TKe1oo|lkqW-0QP`?)Xd~iax3(wUkZggbrhzxf7BY;Ustm3$}L|;3U^hypMJf= zk>CxP_{8W26rLcdKrVw~ard`JJHSXaxyLW;G4|Bkl9_C7)*Q%SV(DQS?))dK)xSsA z_~5GV5E+XpcU%r*qK-t*6rmR-)ut+3;P96@2lGL_%`D(nCYHT~=RqjK3ddA@f3>uU zW(VSW3TAEWI{>HvVCSVEtB}ntm7>c4g)*D`!HoLhTWIV>IhOtpRP=Zs;OI}}Xie-p z{oFYcV((yZ_|4wGMcYTP9)aPD2GzuNj4_kibuckaNJ(0`L#+AoF>Hn)@?GL`M>O2vD4aE5xM&HJUY;9d6NRu7-m<*V%`-#M(hn(1)vz$HR zecVCW&biY(Xpc1lQh5LMRQBuIsq^gz&5jakoH@xzogabH(}jCxIh{PP&L!fesV9iv zn#EmQ^9$`(A#c*G10ktHuRahYJa|1UPH^U|;6=?Ogr&JSf%VijrQ222gx&?edYf!^ zo0m#aZIenuQ@QRmPt__R2oH`dRCH4V&|#s0?iLZj61c_VfiJ+WeR#7k@ZeYLWJSIc ztNIuBx9}2_(AXHQWUs(v9{dlGIPHXeosONrfmi+`c)}O97PZh*(f`TQa@mtTfxn|* zV6mnWw}*y5moIe8et~GKn*24sznN4cLY493D~E!1LnQ}+b%L9l-wgPIEvGC8FoQN} zxo$M)+-V$GJePiL8}nF!hdTb+c-3Wo5`Foj;?=}i^R1BHIQ*ajzs%~+Ip93;zVq$- zexCYoa%M=t^x{X`i#-IH%nVfe&uu*X)BCiRTBovtWXNKsM1p6-y7d~R<_*Qzj3!W| z%2nT*3M>MRHon#q&9C=Y%hk>KcHhR7sdR3@zkeIz60;U}CtDeKCP@vNxSy}8>S7+K{L0de&G2(c5V7ryT|Bc2 zlyS#*)#FbCa?r+IZ;H518~M`T;*klvZEFXxAOt0z$lDjc^$r`3CVR4boz-Cc32E0D zUSR!5S?<-n1l4a(|86%jAS;XlrVx)>*glo`G-YK?8QviN@o-##yrCPmHV z?oz@tG$P!{?5z|h(D2n4gUVxe3g`lnoooI;RC{K)tjb;pEt;7*l#}+qcFKb~k&rE3 z>G}}<-o=GX)DoAoXxFy|szv%Wdr@>qHzy^$xieVxcUzA3zPou_A?9*brq=et3on6D z-^kpyYN*fAPg_fV)S*+b6144ZG~MB+sv0elz{RF8Sro3r5*Moy{vMVzbN9|)T?&<;NGS|d@l(~ z>7^Ehm&YifE;z1@60?a|;fjpRA>N~_4?R32h_OGr`5jyk#_+?bp}(IneQc)orq$gj zLwky&b-IGh?Co{ZfmE5lny4^D5I98!6mFMR|6b2rXeZPzH2wTCyl)(C%fXtMpzh1p zeOliMB8t6L(;>tCSu!M)%690!PftWbk$+_9g;B#R@CCyzctr7;d|dOzrLpJ#B2SsT zGAFbZ9P|StUY8O8#=Qi;vMLcxFisKCOU(^g(o$-JUvr;cecm{ID)My8rSkHR=l_18 z*o)u6m5NjhG|az2(ccuE*@uMaBh4R{O9I1?k`jIcvrUeC zP-24p8C{n!Im2`yr-;evm^Qg(mIg{aSMLAm?ped3TH7X-QcT27Nh`a^p&XJZvQjV8 z35g=bR8k>{7m1l!8pY15W}~Ap2}z|PB*{z}hmw*UrY15@ISs~XteIJ}e2?1S{`R%6 z_s{p|{qg=-7t6J*`+Psox}W>7Z_Tc&Sx(pFb$uh8D`8;_*{NVu<#0_v$kTUfD}49b z88n>@j&IDYFayae75kZ5kB)|EHdy=`e{}sN-8)llbyL3SB~g5Xc)X}&^}}`0yY)hss54y(>CJ7_X6ouj?Bri;7$m0)YVc zoemmi)Rvpe8wuJ!yNY7-g_wzOr1G5K$sn6*FTL+47HEcVir6{y9DA3Zl|SG>HUHe+ z24B~jQ32*+tJ+h&9y^a3^`+-dI-cfE7B}?!ewLJ;(X)#8vh?D*QQP`FS$Q2=C8Z5H zJG!XHFI4*^3qh>nq#K&pSx$YQccPS5yF@d*m>!VWpX3B9VQFZX)Q9YdhWRRA^t{_r z)VI}RX!4@@H5bfKOrRfgGAeFi^D`J~7Fyv~YaAOk@L&l@S3p-XSv$i=0-RxP>tumS1VIqgQ z$R68}a|3_L?4%qBUtrP0f%Lv?>bW!QkeO~J(vYf3*Wk6A2?7p3(f5q&zEO*@NB%EL z_bl~LSw(+QT^_gZ{FZ2GYNkPE#dH6}-d?6__zUC9h$oxVRk-KFd6}e~^ zBH~xmK)-&ac+-cQ<(;#U^w3$h;fdbrrD%l-A*x6D&tVGPEVg0fm`q`S(S zo{iN61!sDS&DSq_8fdKL*LOA&ER*O-rk}Uks7j`B$s7UCJ0pwa=c;X`lcE#6z(ITa z?|DV3{6vPQ?5XT7E*}vkiWP472DNYn+~Dtyu-jz?M_)6D;^5F@Gk4or&c|rt>!-+T z0~-ovYb+dxf~~-LtF4nHw$3-fBG)2sLeW|flDt>COf9u(Pw!e=)?%Fbl9_2Kl1Z17#ow(txE$DCB~;S)o-U5M~GW|`T$JvYxV%T&MFFAE#ORG7nL>1!Ge+ zu-YlmJI3pNcGj2v1BK-&U`5?{IcV+1q}JQ3kM-%za%p6q& z$5C^?p@d4?B@6FyclajFMK%T`Z!p|Lum7fe!#4X0*=G%=mfW=%63;_jr{xsDPPj|M z2c#a;j$u*4$OF7Xq2 z5vxQgY0vn$Blog#wj(El_clS=VuD$(>gq3&50JVq z1|wRa$uZkL=V&f#x8V7KUTM3`|20E&ss-*Hf=8HmG1;FXbgbv;+V}=A)qz zAx&sxhjCz1+YyIU{npy}x{OF4t$((jOs)-JF_kt$WtlSr29Bj2EnX z=QVGC?;Xce6I^!2c!Q+ceCdb&v8oMiSXm@v`>}@uk&ZWtPwL*!@S8LAI3|D-tQmT= z&yL^x!l=uF_^GcRYC(=8F}$9dv@pK1?(xZI4kggF)AtJDj>{}1?AWlR;mm}YII%Aq%pa5@bKwmV8 zq{#%f85e=fT|kV`UAzKl!a{AKbqUQKSd1kJ3#X$;2{Z-#IM`~&XfbhX(pHxPkD6!j zBYi<(@i>IdK@!KOFjM+#fjs zmdsf60~iD&oOu}dJwqSiSAzik)dm24m2f+LG2>5Y4a641X*p{t_*yCylEynBR0;Gc z=p8|iLNsVXmw;)u0b<~ei`03@$7`_ACk)UU(6>xqQZ>VnB_b*TCvOMsR7u@r8F;;p z&;}@b68k4+MF?juS!D}Z?T`BzOex1eU*>Z9fTq(mA7I7IF0*wWj5^{rM;6-M-904ffv{3fUqY1x)#GG!lfCf1%M1&}f7J5-Ho~1DnqL z2^1_le+O|Fe+7IC0eg#xU4HUa`wwj6noJqv1MpAY#7O1I%JBFaQ;EMj2@6R<_#iHz zK*ws=6QsYjg8s9$61{lafT|@#Ie#GBImV*MZ2C_JJR@y`V957A$lgxzLOI zE=7dCK!>Wh4WYN*!;iU#-2PA1)X9AS0OQB||MCHhG4M?!`-a_v z7T?B!JpY$a+faa9{RP=e18`vW{0b;7Tml+&IWuW%axV2kQ>uXEe=##3WDgCnpWz~C zZv|5S0H9}t(NmF*cG7Gj_RbPQO~GUFK$vkO@6+j>h!FdNBJuUawrxn1-;E%`EqdXaP0LK}%`KhZm=kTT5JGe6WX}Jjk zu180G32~$e0O=!)ricvnMaA&#I1zO*P6iwUHWAS;OU9R*>P%Smxbk*%1xvD5%92=` z7eE%~`xOu!0MP3_!pS9jk#mz*FF@1wd-i`9H=%ada^=z{7(Ge=UsJ zM``~X$&>eb0j$%Aeuzyg03(@1;DbGlD> zmZ?kmhlAh77KXGn96c$z$qjSdEUB*e2FeeJQTN0r zjPzeA<=h3ye6hffcMr2R_!k2wY%Hj`M4UDu%+Jo&&yG4x?y;u;t66B) z6(k|_L8)M0WUnaF94!e%fOLM`!a>fZ4T3Csnm+TMv%st?9e|EwgA^AuUJ=}0#a9Za zdSOuUMl8u`J)9us#Y@&wIo{?Yoe%*Bb`55Eag-z8;j!x!#_xc@f9BW5VPgmKh&M;N z6a_g5xzb&y($!iLGaHJvc2ATgwGd+uxSZx3A*X8!iNPrYM1fuBgp?;%ttX9y_7(Wc{IxY>1tpGunDc>f9oZGTJJ%Xhip1$#1q3xU4X!vj`9ViBwB zyAIfC_oDiW*aaqAXzM(h4GEo?G!A~G1TX+vgK``15VJvElg4kz*eF=G_Ev1^Ck_+q z7{XyTt$kt+P`p=S7)(|>M|vG3nbi)w1ewuAas<$J4_eX1C~zM?m%37DJ;Hf`FF-#2 zA_X3`8(`Sbz&>I^TV~Vg)1gY{)8_QFeggg|dRPu$$!+jZKjJbOKQhEFzjDMhz~4oh zc)f!;zmG*|T-8{##jt)yK7IJm!L0=j@Eo}V8ADF@3IfXyeol&iI&+$DZwjIzi@?X! zFJQF0-2eN!_5DV?9C*!t>>6YL1}Ur@ZNIG7TwRW2zs$E^z&V{;Bru76yA-z-_g5Re zw$&joLK8dQ9}L9I@B6dX78)L8sxSjj$qO=|VA$J8ATdgJ(=pNWQ!1q27Mfs2%qxkG zn#mm>vR7`|g{A{5y!@oM!}&F&jXsme$i6xLta(K=3)3B8)=|~ZL!7p%(y!?+Pv)-D z9uzD)VPw_O6xsS|e@}ylFhgprFJ*0LR&24VpLm?+EIP%ebyo#+dO1Xd56`YhLq;-4 z_Iww&K359Z<+Y-Atfk~rOVsXRFx%`&crDrfl!9#TeCW#VB^>7~+nJm}W=-V{2Ifd< zPH0GQlg`2Fs9zX55itK8z4-ZkMAgF^^=*#6YBjR5+}Jv4?-Scp?gPvWUHl-zy6OP0 zNz%l + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "arduino_r3_connector.dtsi" +#include + +/ { + leds: leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&gpioj 2 GPIO_ACTIVE_HIGH>; + label = "User LD7"; + }; + red_led: led_2 { + gpios = <&gpioi 13 GPIO_ACTIVE_HIGH>; + label = "User LD6"; + }; + green_led_2: led_3 { + gpios = <&gpiod 3 GPIO_ACTIVE_HIGH>; + label = "User LD8"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button_0 { + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + label = "User SB1"; + zephyr,code = ; + }; + }; +}; + +&rcc { + d1cpre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; +}; + +&mailbox { + status = "okay"; +}; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts new file mode 100644 index 00000000000000..fe16637e5efc62 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "stm32h745i_disco.dtsi" + +/ { + model = "STMicroelectronics STM32H745I-DISCO board"; + compatible = "st,stm32h745i-disco"; + + /* HW resources belonging to CM4 */ + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram1; + zephyr,flash = &flash1; + }; + + aliases { + led0 = &green_led; + }; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&rcc { + clock-frequency = ; +}; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml new file mode 100644 index 00000000000000..c54a159929890c --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml @@ -0,0 +1,17 @@ +identifier: stm32h745i_disco/stm32h745xx/m4 +name: STM32H745XI Discovery (M4) +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 288 +flash: 1024 +supported: + - arduino_gpio + - gpio +testing: + ignore_tags: + - mpu + - nfc +vendor: st diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig new file mode 100644 index 00000000000000..03e689742d93ba --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena + +# Enable GPIO +CONFIG_GPIO=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# By default SERIAL peripherals are assigned to m7 + +# Enable uart driver +#CONFIG_SERIAL=y + +# Console +#CONFIG_CONSOLE=y +#CONFIG_UART_CONSOLE=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts new file mode 100644 index 00000000000000..2d46284294ea7e --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "stm32h745i_disco.dtsi" + +/ { + model = "STMicroelectronics STM32H745I-DISCO board"; + compatible = "st,stm32h745i-disco"; + + /* HW resources belonging to CM7 */ + chosen { + zephyr,console = &usart3; + zephyr,shell-uart = &usart3; + zephyr,dtcm = &dtcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,flash-controller = &mt25ql512ab1; + zephyr,canbus = &fdcan1; + }; + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm11 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "User LD8 - PWM11"; + }; + }; + + transceiver0: can-phy0 { + compatible = "microchip,mcp2562fd", "can-transceiver-gpio"; + max-bitrate = <5000000>; + #phy-cells = <0>; + }; + + transceiver1: can-phy1 { + compatible = "microchip,mcp2562fd", "can-transceiver-gpio"; + max-bitrate = <5000000>; + #phy-cells = <0>; + }; + + /* RM0455 - 23.6 External device address mapping */ + sdram2: sdram@d0000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + device_type = "memory"; + reg = <0xd0000000 DT_SIZE_M(16)>; /* 128Mbit */ + zephyr,memory-region = "SDRAM2"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; + + aliases { + led0 = &green_led; + pwm-led0 = &green_pwm_led; + sw0 = &user_button; + }; +}; + +&clk_lsi { + status = "okay"; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; /* X1: 25MHz */ + status = "okay"; +}; + +&pll { + div-m = <5>; + mul-n = <192>; + div-p = <2>; + div-q = <15>; + div-r = <4>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pb6 &usart1_rx_pb7>; + pinctrl-names = "default"; + current-speed = <57600>; + status = "okay"; +}; + +&usart3 { + pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>, + <&rcc STM32_SRC_LSI RTC_SEL(2)>; + status = "okay"; +}; + +&timers1 { + st,prescaler = <10000>; + status = "okay"; + + pwm11: pwm { + status = "okay"; + pinctrl-0 = <&tim1_ch1_pa8>; + pinctrl-names = "default"; + }; +}; + +&mac { + status = "okay"; + /* MII */ + pinctrl-0 = <ð_ref_clk_pa1 + ð_crs_dv_pa7 + ð_rxd2_pb0 + ð_rxd3_pb1 + ð_txd2_pc2 + ð_tx_clk_pc3 + ð_rxd0_pc4 + ð_rxd1_pc5 + ð_txd3_pe2 + ð_tx_en_pg11 + ð_txd1_pg12 + ð_txd0_pg13 + ð_rx_er_pi10>; + pinctrl-names = "default"; +}; + +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + +&rng { + status = "okay"; +}; + +&quadspi { + pinctrl-names = "default"; + pinctrl-0 = < + &quadspi_bk1_io0_pd11 + &quadspi_bk1_io3_pf6 + &quadspi_bk1_io2_pf7 + &quadspi_bk1_io1_pf9 + &quadspi_clk_pf10 + &quadspi_bk1_ncs_pg6 + &quadspi_bk2_io2_pg9 + &quadspi_bk2_io3_pg14 + &quadspi_bk2_io0_ph2 + &quadspi_bk2_io1_ph3 + >; + flash-id = <1>; + status = "okay"; + + mt25ql512ab1: qspi-nor-flash-1@90000000 { + compatible = "st,stm32-qspi-nor"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + qspi-max-frequency = <72000000>; + spi-bus-width = <4>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + reg = <0x0 DT_SIZE_M(64)>; + }; + }; + }; + + mt25ql512ab2: qspi-nor-flash-2@90000000 { + compatible = "st,stm32-qspi-nor"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + qspi-max-frequency = <72000000>; + status = "okay"; + }; +}; + +&i2c4 { + status = "okay"; + pinctrl-0 = <&i2c4_scl_pd12 &i2c4_sda_pd13>; + pinctrl-names = "default"; +}; + +&spi2 { + status = "okay"; + pinctrl-0 = <&spi2_nss_pb4 &spi2_mosi_pb15 &spi2_miso_pi2 &spi2_sck_pd3>; + pinctrl-names = "default"; +}; + +&fdcan1 { + status = "okay"; + pinctrl-0 = <&fdcan1_tx_ph13 &fdcan1_rx_ph14>; + pinctrl-names = "default"; + bus-speed = <125000>; + bus-speed-data = <1000000>; + sample-point = <875>; + sample-point-data = <875>; + phys = <&transceiver0>; +}; + +&fdcan2 { + status = "okay"; + pinctrl-0 = <&fdcan2_tx_pb13 &fdcan2_rx_pb5>; + pinctrl-names = "default"; + bus-speed = <125000>; + bus-speed-data = <1000000>; + sample-point = <875>; + sample-point-data = <875>; + phys = <&transceiver1>; +}; + +&fmc { + pinctrl-0 = <&fmc_nbl0_pe0 &fmc_nbl1_pe1 + &fmc_sdclk_pg8 &fmc_sdnwe_ph5 &fmc_sdcke1_ph7 + &fmc_sdne1_ph6 &fmc_sdnras_pf11 &fmc_sdncas_pg15 + &fmc_a0_pf0 &fmc_a1_pf1 &fmc_a2_pf2 &fmc_a3_pf3 &fmc_a4_pf4 + &fmc_a5_pf5 &fmc_a6_pf12 &fmc_a7_pf13 &fmc_a8_pf14 + &fmc_a9_pf15 &fmc_a10_pg0 &fmc_a11_pg1 + &fmc_a14_pg4 &fmc_a15_pg5 &fmc_d0_pd14 &fmc_d1_pd15 + &fmc_d2_pd0 &fmc_d3_pd1 &fmc_d4_pe7 &fmc_d5_pe8 &fmc_d6_pe9 + &fmc_d7_pe10 &fmc_d8_pe11 &fmc_d9_pe12 &fmc_d10_pe13 + &fmc_d11_pe14 &fmc_d12_pe15 &fmc_d13_pd8 &fmc_d14_pd9 + &fmc_d15_pd10>; + pinctrl-names = "default"; + status = "okay"; + + sdram { + status = "okay"; + power-up-delay = <100>; + num-auto-refresh = <8>; + mode-register = <0x220>; + refresh-rate = <0x603>; + bank@1 { + reg = <1>; + st,sdram-control = ; + st,sdram-timing = <2 7 4 7 2 2 2>; + }; + }; +}; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml new file mode 100644 index 00000000000000..4b261299fed1e9 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml @@ -0,0 +1,23 @@ +identifier: stm32h745i_disco/stm32h745xx/m7 +name: STM32H745XI Discovery (M7) +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 512 +flash: 1024 +supported: + - arduino_gpio + - arduino_i2c + - uart + - gpio + - counter + - i2c + - pwm + - netif:eth + - qspi + - memc + - spi + - rtc +vendor: st diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig new file mode 100644 index 00000000000000..f3ba3ad3b2a933 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena + +# Enable the internal SMPS regulator +CONFIG_POWER_SUPPLY_DIRECT_SMPS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable UART ( disable to assign to M4 core) +CONFIG_SERIAL=y + +# Console ( disable to assign to M4 core) +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable Clock +CONFIG_CLOCK_CONTROL=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/stm32h745i_disco/support/openocd.cfg b/boards/st/stm32h745i_disco/support/openocd.cfg new file mode 100644 index 00000000000000..cd2f2e5753b934 --- /dev/null +++ b/boards/st/stm32h745i_disco/support/openocd.cfg @@ -0,0 +1,30 @@ +# STM32H745XI DISCOVERY board OpenOCD ST-LINK V3 configuration +# +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena +# SPDX-License-Identifier: Apache-2.0 +# + +source [find board/stm32h745i-disco.cfg] + +# Use connect_assert_srst here to be able to program +# even when core is in sleep mode +reset_config srst_only srst_nogate connect_assert_srst + +$_CHIPNAME.cpu0 configure -event gdb-attach { + echo "Debugger attaching: halting execution" + gdb_breakpoint_override hard +} + +$_CHIPNAME.cpu0 configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} + +# Due to the use of connect_assert_srst, running gdb requires +# to reset halt just after openocd init. +rename init old_init +proc init {} { + old_init + reset halt +} From 1b4b7130fe61210119fb22259485155aab8e088f Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0628/1389] tests: drivers: Add more test cases for the i2c driver in controller mode Extend coverage for the i2c master mode driver This test suite uses external sensor BME688 Signed-off-by: Bartosz Miller --- tests/drivers/i2c/i2c_bme688/CMakeLists.txt | 9 + tests/drivers/i2c/i2c_bme688/README.txt | 6 + tests/drivers/i2c/i2c_bme688/prj.conf | 2 + tests/drivers/i2c/i2c_bme688/src/main.c | 286 ++++++++++++++++++++ tests/drivers/i2c/i2c_bme688/src/sensor.c | 105 +++++++ tests/drivers/i2c/i2c_bme688/src/sensor.h | 163 +++++++++++ tests/drivers/i2c/i2c_bme688/testcase.yaml | 6 + 7 files changed, 577 insertions(+) create mode 100644 tests/drivers/i2c/i2c_bme688/CMakeLists.txt create mode 100644 tests/drivers/i2c/i2c_bme688/README.txt create mode 100644 tests/drivers/i2c/i2c_bme688/prj.conf create mode 100644 tests/drivers/i2c/i2c_bme688/src/main.c create mode 100644 tests/drivers/i2c/i2c_bme688/src/sensor.c create mode 100644 tests/drivers/i2c/i2c_bme688/src/sensor.h create mode 100644 tests/drivers/i2c/i2c_bme688/testcase.yaml diff --git a/tests/drivers/i2c/i2c_bme688/CMakeLists.txt b/tests/drivers/i2c/i2c_bme688/CMakeLists.txt new file mode 100644 index 00000000000000..0e4b8e8a8b6a72 --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(i2c_bme688) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/i2c/i2c_bme688/README.txt b/tests/drivers/i2c/i2c_bme688/README.txt new file mode 100644 index 00000000000000..b0ac29c8a97137 --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/README.txt @@ -0,0 +1,6 @@ +I2C bus controller to BME688 sensor test +######################################## + +This test verifies I2C target driver API methods +with external sensors device - Bosch BME688. +I2C speed is set to standard. diff --git a/tests/drivers/i2c/i2c_bme688/prj.conf b/tests/drivers/i2c/i2c_bme688/prj.conf new file mode 100644 index 00000000000000..4b19609ecfbd14 --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/prj.conf @@ -0,0 +1,2 @@ +CONFIG_I2C=y +CONFIG_ZTEST=y diff --git a/tests/drivers/i2c/i2c_bme688/src/main.c b/tests/drivers/i2c/i2c_bme688/src/main.c new file mode 100644 index 00000000000000..7041e579c1304b --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/src/main.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sensor.h" + +#define SENSOR_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(bosch_bme680) +#define I2C_TEST_NODE DT_PARENT(SENSOR_NODE) +#define DEVICE_ADDRESS (uint8_t)DT_REG_ADDR(SENSOR_NODE) + +static const struct device *const i2c_device = DEVICE_DT_GET(I2C_TEST_NODE); +static struct calibration_coeffs cal_coeffs; +static int32_t t_fine; + +/* Read data from the senors register */ +static uint8_t read_sensor_register(uint8_t register_address) +{ + int err; + uint8_t response = 0; + + err = i2c_reg_read_byte(i2c_device, DEVICE_ADDRESS, register_address, &response); + zassert_equal(err, 0, "i2c_read(%x)' failed with error: %d\n", register_address, err); + TC_PRINT("I2C read reg, addr: 0x%x, val: 0x%x\n", register_address, response); + return response; +} + +/* Burst read data from the sensor registers */ +static void burst_read_sensor_registers(uint8_t starting_register_address, uint8_t number_of_bytes, + uint8_t *data_buffer) +{ + int err; + + zassert_true(number_of_bytes <= MAX_BURST_READ_SIZE, + "Too many bytes to read %d, max burst read size is set to: %d", + number_of_bytes, MAX_BURST_READ_SIZE); + err = i2c_burst_read(i2c_device, DEVICE_ADDRESS, starting_register_address, data_buffer, + number_of_bytes); + zassert_equal(err, 0, "i2c_burst_read(%x, %x)' failed with error: %d\n", + starting_register_address, number_of_bytes, err); + TC_PRINT("I2C burst read, start addr: 0x%x, number of bytes: %d\n", + starting_register_address, number_of_bytes); +} + +/* Write sensor register */ +static void write_sensor_register(uint8_t register_address, int8_t value) +{ + int err; + + err = i2c_reg_write_byte(i2c_device, DEVICE_ADDRESS, register_address, value); + zassert_equal(err, 0, "i2c_reg_write_byte(%x, %x)' failed with error: %d\n", + register_address, value, err); + TC_PRINT("I2C reg write, addr: 0x%x, val: 0x%x\n", register_address, value); +} + +/* Set IIR filter for the temperature and pressure measurements */ +static void set_sensor_iir_filter(void) +{ + uint8_t response = 0; + + TC_PRINT("Set IIR filter\n"); + response = read_sensor_register(CONF_REGISTER_ADDRESS); + response &= ~IIR_FILER_ORDER_BIT_MASK; + response |= IIR_FILER_COEFF_3 << IIR_FILER_ORDER_BIT_SHIFT; + write_sensor_register(CONF_REGISTER_ADDRESS, response); + read_sensor_register(CONF_REGISTER_ADDRESS); +} + +/* Read calibration coefficients for temperature, humifity and pressure */ +static void read_calibration_coeffs(struct calibration_coeffs *coeffs) +{ + uint8_t register_data[MAX_BURST_READ_SIZE] = { 0 }; + + /* Humidity */ + TC_PRINT("Reading humidity calibration coefficients\n"); + burst_read_sensor_registers(HUMI_PAR_REGISTERS_START_ADDRESS, HUMI_PAR_REGISTERS_COUNT, + register_data); + coeffs->par_h1 = (uint16_t)(((uint16_t)register_data[HUMI_PAR_H1_MSB_BUF_POSITION] << 4) | + (register_data[HUMI_PAR_H1_LSB_BUF_POSITION] & + HUMI_PAR_H1_LSB_BIT_MASK)); + coeffs->par_h2 = (uint16_t)(((uint16_t)register_data[HUMI_PAR_H2_MSB_BUF_POSITION] << 4) | + ((register_data[HUMI_PAR_H2_LSB_BUF_POSITION]) >> 4)); + + coeffs->par_h3 = (uint8_t)register_data[HUMI_PAR_H3_BUF_POSITION]; + coeffs->par_h4 = (uint8_t)register_data[HUMI_PAR_H4_BUF_POSITION]; + coeffs->par_h5 = (uint8_t)register_data[HUMI_PAR_H5_BUF_POSITION]; + coeffs->par_h6 = (uint8_t)register_data[HUMI_PAR_H6_BUF_POSITION]; + coeffs->par_h7 = (uint8_t)register_data[HUMI_PAR_H7_BUF_POSITION]; + + /* Temperature */ + TC_PRINT("Reading temperature calibration coefficients\n"); + burst_read_sensor_registers(TEMP_PAR_T1_REGISTER_ADDRESS_LSB, 2, register_data); + coeffs->par_t1 = (uint16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]); + burst_read_sensor_registers(TEMP_PAR_T2_REGISTER_ADDRESS_LSB, 2, register_data); + coeffs->par_t2 = (uint16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]); + coeffs->par_t3 = (uint8_t)read_sensor_register(TEMP_PAR_T3_REGISTER_ADDRESS); + + /* Pressure */ + TC_PRINT("Reading pressure calibration coefficients\n"); + burst_read_sensor_registers(PRES_PAR_P1_REGISTER_ADDRESS_LSB, 4, register_data); + coeffs->par_p1 = (uint16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]); + coeffs->par_p2 = (int16_t)(((uint16_t)register_data[3] << 8) | (uint16_t)register_data[2]); + coeffs->par_p3 = (int8_t)read_sensor_register(PRES_PAR_P3_REGISTER_ADDRESS); + burst_read_sensor_registers(PRES_PAR_P4_REGISTER_ADDRESS_LSB, 4, register_data); + coeffs->par_p4 = (int16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]); + coeffs->par_p5 = (int16_t)(((uint16_t)register_data[3] << 8) | (uint16_t)register_data[2]); + coeffs->par_p6 = (int8_t)read_sensor_register(PRES_PAR_P6_REGISTER_ADDRESS); + coeffs->par_p7 = (int8_t)read_sensor_register(PRES_PAR_P7_REGISTER_ADDRESS); + burst_read_sensor_registers(PRES_PAR_P8_REGISTER_ADDRESS_LSB, 4, register_data); + coeffs->par_p8 = (int16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]); + coeffs->par_p9 = (int16_t)(((uint16_t)register_data[3] << 8) | (uint16_t)register_data[2]); + coeffs->par_p10 = read_sensor_register(PRES_PAR_P10_REGISTER_ADDRESS); +} + +/* Configure temperature, pressure and humidity measurements */ +static void configure_measurements(void) +{ + unsigned char response = 0; + + TC_PRINT("Configure measurements\n"); + + /* Humidity */ + response = read_sensor_register(CTRL_HUM_REGISTER_ADDRESS); + response &= ~HUMIDITY_OVERSAMPLING_BIT_MSK; + response |= HUMIDITY_OVERSAMPLING_1X << HUMIDITY_OVERSAMPLING_BIT_SHIFT; + write_sensor_register(CTRL_HUM_REGISTER_ADDRESS, response); + + /* Temperature*/ + response = read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS); + response &= ~TEMP_OVERSAMPLING_BIT_MSK; + response |= TEMPERATURE_OVERSAMPLING_2X << TEMP_OVERSAMPLING_BIT_SHIFT; + + write_sensor_register(CTRL_MEAS_REGISTER_ADDRESS, response); + + /* Pressure */ + response = read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS); + response &= ~PRES_OVERSAMPLING_BIT_MSK; + response |= PRESSURE_OVERSAMPLING_16X << PRES_OVERSAMPLING_BIT_SHIFT; + + write_sensor_register(CTRL_MEAS_REGISTER_ADDRESS, response); + read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS); + set_sensor_iir_filter(); +} + +/* Set the sensor operation mode */ +static void set_sensor_mode(uint8_t sensor_mode) +{ + unsigned char response = 0; + + TC_PRINT("Set sensor mode to: 0x%x\n", sensor_mode); + + response = read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS); + response &= ~CTRL_MEAS_MODE_BIT_MSK; + response |= sensor_mode << CTRL_MEAS_MODE_BIT_SHIFT; + write_sensor_register(CTRL_MEAS_REGISTER_ADDRESS, response); + read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS); +} + +/* Read the raw ADC temperature measurement result */ +static uint32_t read_adc_temperature(void) +{ + uint32_t adc_temperature = 0; + + TC_PRINT("Reading ADC temperature\n"); + adc_temperature = (uint32_t)(((uint32_t)read_sensor_register(TEMP_ADC_DATA_MSB_0) << 12) | + ((uint32_t)read_sensor_register(TEMP_ADC_DATA_LSB_0) << 4) | + ((uint32_t)read_sensor_register(TEMP_ADC_DATA_XLSB_0) >> 4)); + + return adc_temperature; +} + +/* Read the raw ADC pressure measurement result */ +static uint32_t read_adc_pressure(void) +{ + uint32_t pres_adc = 0; + + TC_PRINT("Reading ADC pressure\n"); + pres_adc = (uint32_t)(((uint32_t)read_sensor_register(PRES_ADC_DATA_MSB_0) << 12) | + ((uint32_t)read_sensor_register(PRES_ADC_DATA_LSB_0) << 4) | + ((uint32_t)read_sensor_register(PRES_ADC_DATA_XLSB_0) >> 4)); + + return pres_adc; +} + +/* Read the raw ADC humidity measurement result */ +static uint16_t read_adc_humidity(void) +{ + uint16_t hum_adc = 0; + + TC_PRINT("Reading ADC humidity\n"); + hum_adc = (uint16_t)(((uint16_t)read_sensor_register(HUM_ADC_DATA_MSB_0) << 8) | + (uint16_t)read_sensor_register(HUM_ADC_DATA_LSB_0)); + + return hum_adc; +} + +ZTEST(i2c_controller_to_sensor, test_i2c_basic_memory_read) +{ + int err; + uint8_t entire_sensor_memory[SENSOR_MEMORY_SIZE_IN_BYTES] = { 0 }; + + TC_PRINT("Device address 0x%x\n", DEVICE_ADDRESS); + + err = i2c_read(i2c_device, entire_sensor_memory, SENSOR_MEMORY_SIZE_IN_BYTES, + DEVICE_ADDRESS); + zassert_equal(err, 0, "i2c_read' failed with error: %d\n", err); +} + +ZTEST(i2c_controller_to_sensor, test_i2c_controlled_sensor_operation) +{ + int err; + uint8_t response = 0; + int16_t temperature = 0; + uint32_t pressure = 0; + uint32_t humidity = 0; + uint32_t i2c_config = I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_CONTROLLER; + uint8_t measurements_left = MEASUREMENT_CYCLES + 1; + + TC_PRINT("Device address 0x%x\n", DEVICE_ADDRESS); + + err = i2c_configure(i2c_device, i2c_config); + zassert_equal(err, 0, "i2c_configure' failed with error: %d\n", err); + + response = read_sensor_register(CHIP_ID_REGISTER_ADDRESS); + TC_PRINT("Chip_Id: %d\n", response); + + response = read_sensor_register(VARIANT_ID_REGISTER_ADDRESS); + TC_PRINT("Variant_Id: %d\n", response); + + write_sensor_register(RESET_REGISTER_ADDRESS, RESET_DEVICE); + k_sleep(K_MSEC(SLEEP_TIME_MS)); + + read_calibration_coeffs(&cal_coeffs); + + configure_measurements(); + set_sensor_mode(FORCED_MODE); + + while (measurements_left) { + response = read_sensor_register(MEAS_STATUS_0_REG_ADDRESS); + TC_PRINT("Meas status 0, meas in progress: %d, new data: %d\n", + response & MEASUREMENT_IN_PROGRESS_BIT_MASK, + response & MEASUREMENT_NEW_DATA_BIT_MASK); + if (response & MEASUREMENT_NEW_DATA_BIT_MASK) { + temperature = + calculate_temperature(read_adc_temperature(), &t_fine, &cal_coeffs); + pressure = calculate_pressure(read_adc_pressure(), t_fine, &cal_coeffs); + humidity = calculate_humidity(read_adc_humidity(), t_fine, &cal_coeffs); + TC_PRINT("Temperature: %d.%d C deg\n", temperature / 100, + temperature % 100); + TC_PRINT("Pressure: %d hPa\n", pressure / 100); + TC_PRINT("Humidity: %d %%\n", humidity / 1000); + set_sensor_mode(FORCED_MODE); + + /* Check if the results are within reasonable ranges + * for laboratory room usage + * This is asserted to catch values + * that may be results of an erroneous + * bus operation (corrupted read or write) + */ + zassert_true( + (temperature / 100 >= 5) && (temperature / 100 <= 55), + "Temperature is outside of the allowed range for labroatory use"); + zassert_true((pressure / 100 >= 700) && (pressure / 100 <= 1300), + "Pressure is outside of the allowed range for labroatory use"); + zassert_true((humidity / 1000 >= 10) && (humidity / 1000 <= 90), + "Humidity is outside of the allowed range for labroatory use"); + measurements_left--; + } + k_sleep(K_MSEC(SLEEP_TIME_MS)); + } +} + +/* + * Test setup + */ +void *test_setup(void) +{ + zassert_true(device_is_ready(i2c_device), "i2c device is not ready"); + return NULL; +} + +ZTEST_SUITE(i2c_controller_to_sensor, NULL, test_setup, NULL, NULL, NULL); diff --git a/tests/drivers/i2c/i2c_bme688/src/sensor.c b/tests/drivers/i2c/i2c_bme688/src/sensor.c new file mode 100644 index 00000000000000..d351b31e7074be --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/src/sensor.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sensor.h" + +/* Calculate the compensated temperature */ +int32_t calculate_temperature(uint32_t adc_temp, int32_t *t_fine, + struct calibration_coeffs *cal_coeffs) +{ + int16_t temperature_compensated = 0; + int64_t var1, var2, var3; + + var1 = ((int32_t)adc_temp >> 3) - ((int32_t)cal_coeffs->par_t1 << 1); + var2 = (var1 * (int32_t)cal_coeffs->par_t2) >> 11; + var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; + var3 = ((var3) * ((int32_t)cal_coeffs->par_t3 << 4)) >> 14; + *t_fine = var2 + var3; + temperature_compensated = (int16_t)(((*t_fine * 5) + 128) >> 8); + return temperature_compensated; +} + +/* Calculate the compensated pressure + * Note: temperature must be calculated first + * to obtain the 't_fine' + */ +uint32_t calculate_pressure(uint32_t pres_adc, int32_t t_fine, + struct calibration_coeffs *cal_coeffs) +{ + int32_t var1; + int32_t var2; + int32_t var3; + int32_t pressure_comp; + const int32_t pres_ovf_check = INT32_C(0x40000000); + + var1 = (((int32_t)t_fine) >> 1) - 64000; + var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t)cal_coeffs->par_p6) >> 2; + var2 = var2 + ((var1 * (int32_t)cal_coeffs->par_p5) << 1); + var2 = (var2 >> 2) + ((int32_t)cal_coeffs->par_p4 << 16); + var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * ((int32_t)cal_coeffs->par_p3 << 5)) >> 3) + + (((int32_t)cal_coeffs->par_p2 * var1) >> 1); + var1 = var1 >> 18; + var1 = ((32768 + var1) * (int32_t)cal_coeffs->par_p1) >> 15; + pressure_comp = 1048576 - pres_adc; + pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125)); + if (pressure_comp >= pres_ovf_check) { + pressure_comp = ((pressure_comp / var1) << 1); + } else { + pressure_comp = ((pressure_comp << 1) / var1); + } + + var1 = ((int32_t)cal_coeffs->par_p9 * + (int32_t)(((pressure_comp >> 3) * (pressure_comp >> 3)) >> 13)) >> + 12; + var2 = ((int32_t)(pressure_comp >> 2) * (int32_t)cal_coeffs->par_p8) >> 13; + var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) * + (int32_t)(pressure_comp >> 8) * (int32_t)cal_coeffs->par_p10) >> + 17; + pressure_comp = (int32_t)(pressure_comp) + + ((var1 + var2 + var3 + ((int32_t)cal_coeffs->par_p7 << 7)) >> 4); + + return (uint32_t)pressure_comp; +} + +/* Calculate the relative humidity + * Note: temperature must be calculated first + * to obtain the 't_fine' + */ +uint32_t calculate_humidity(uint16_t hum_adc, int32_t t_fine, struct calibration_coeffs *cal_coeffs) +{ + int32_t var1; + int32_t var2; + int32_t var3; + int32_t var4; + int32_t var5; + int32_t var6; + int32_t temp_scaled; + int32_t calc_hum; + + temp_scaled = (((int32_t)t_fine * 5) + 128) >> 8; + var1 = (int32_t)(hum_adc - ((int32_t)((int32_t)cal_coeffs->par_h1 * 16))) - + (((temp_scaled * (int32_t)cal_coeffs->par_h3) / ((int32_t)100)) >> 1); + var2 = ((int32_t)cal_coeffs->par_h2 * + (((temp_scaled * (int32_t)cal_coeffs->par_h4) / ((int32_t)100)) + + (((temp_scaled * ((temp_scaled * (int32_t)cal_coeffs->par_h5) / ((int32_t)100))) >> + 6) / + ((int32_t)100)) + + (int32_t)(1 << 14))) >> + 10; + var3 = var1 * var2; + var4 = (int32_t)cal_coeffs->par_h6 << 7; + var4 = ((var4) + ((temp_scaled * (int32_t)cal_coeffs->par_h7) / ((int32_t)100))) >> 4; + var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; + var6 = (var4 * var5) >> 1; + calc_hum = (((var3 + var6) >> 10) * ((int32_t)1000)) >> 12; + if (calc_hum > 100000) { + calc_hum = 100000; + } else if (calc_hum < 0) { + calc_hum = 0; + } + + return (uint32_t)calc_hum; +} diff --git a/tests/drivers/i2c/i2c_bme688/src/sensor.h b/tests/drivers/i2c/i2c_bme688/src/sensor.h new file mode 100644 index 00000000000000..cac5addb33e723 --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/src/sensor.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SENSOR_H +#define SENSOR_H + +#include + +#define SLEEP_TIME_MS 250 +#define MEASUREMENT_CYCLES 3 +#define MAX_BURST_READ_SIZE 10 + +/* General */ +#define CHIP_ID_REGISTER_ADDRESS 0xD0 +#define VARIANT_ID_REGISTER_ADDRESS 0xF0 +#define CONF_REGISTER_ADDRESS 0x75 +#define CTRL_MEAS_REGISTER_ADDRESS 0x74 +#define CTRL_HUM_REGISTER_ADDRESS 0x72 +#define RESET_REGISTER_ADDRESS 0xE0 +#define SLEEP_MODE 0x0 +#define FORCED_MODE 0x1 +#define CTRL_MEAS_MODE_BIT_MSK 1 << 1 | 1 +#define CTRL_MEAS_MODE_BIT_SHIFT 0 +#define RESET_DEVICE 0xB6 +#define SENSOR_MEMORY_SIZE_IN_BYTES 255 + +/* Calibration coeffcients */ +#define TEMP_PAR_T1_REGISTER_ADDRESS_LSB 0xE9 +#define TEMP_PAR_T1_REGISTER_ADDRESS_MSB 0xEA +#define TEMP_PAR_T2_REGISTER_ADDRESS_LSB 0x8A +#define TEMP_PAR_T2_REGISTER_ADDRESS_MSB 0x8B +#define TEMP_PAR_T3_REGISTER_ADDRESS 0x8C + +#define HUMI_PAR_REGISTERS_START_ADDRESS 0xE1 +#define HUMI_PAR_REGISTERS_COUNT 8 +#define HUMI_PAR_H1_LSB_BUF_POSITION 1 +#define HUMI_PAR_H1_MSB_BUF_POSITION 2 +#define HUMI_PAR_H2_LSB_BUF_POSITION 1 +#define HUMI_PAR_H2_MSB_BUF_POSITION 0 +#define HUMI_PAR_H3_BUF_POSITION 3 +#define HUMI_PAR_H4_BUF_POSITION 4 +#define HUMI_PAR_H5_BUF_POSITION 5 +#define HUMI_PAR_H6_BUF_POSITION 6 +#define HUMI_PAR_H7_BUF_POSITION 7 + +#define HUMI_PAR_H1_REGISTER_ADDRESS_LSB 0xE2 +#define HUMI_PAR_H1_LSB_BIT_MASK 0xFF +#define HUMI_PAR_H1_REGISTER_ADDRESS_MSB 0xE3 +#define HUMI_PAR_H2_REGISTER_ADDRESS_LSB 0xE2 +#define HUMI_PAR_H2_REGISTER_ADDRESS_MSB 0xE1 +#define HUMI_PAR_H3_REGISTER_ADDRESS 0xE4 +#define HUMI_PAR_H4_REGISTER_ADDRESS 0xE5 +#define HUMI_PAR_H5_REGISTER_ADDRESS 0xE6 +#define HUMI_PAR_H6_REGISTER_ADDRESS 0xE7 +#define HUMI_PAR_H7_REGISTER_ADDRESS 0xE8 + +#define PRES_PAR_P1_REGISTER_ADDRESS_LSB 0x8E +#define PRES_PAR_P1_REGISTER_ADDRESS_MSB 0x8F +#define PRES_PAR_P2_REGISTER_ADDRESS_LSB 0x90 +#define PRES_PAR_P2_REGISTER_ADDRESS_MSB 0x91 +#define PRES_PAR_P3_REGISTER_ADDRESS 0x92 +#define PRES_PAR_P4_REGISTER_ADDRESS_LSB 0x94 +#define PRES_PAR_P4_REGISTER_ADDRESS_MSB 0x95 +#define PRES_PAR_P5_REGISTER_ADDRESS_LSB 0x96 +#define PRES_PAR_P5_REGISTER_ADDRESS_MSB 0x97 +#define PRES_PAR_P6_REGISTER_ADDRESS 0x99 +#define PRES_PAR_P7_REGISTER_ADDRESS 0x98 +#define PRES_PAR_P8_REGISTER_ADDRESS_LSB 0x9C +#define PRES_PAR_P8_REGISTER_ADDRESS_MSB 0x9D +#define PRES_PAR_P9_REGISTER_ADDRESS_LSB 0x9E +#define PRES_PAR_P9_REGISTER_ADDRESS_MSB 0x9F +#define PRES_PAR_P10_REGISTER_ADDRESS 0xA0 + +/* IIR filter */ +#define IIR_FILER_ORDER_BIT_MASK 1 << 4 | 1 << 3 | 1 << 2 +#define IIR_FILER_ORDER_BIT_SHIFT 2 +#define IIR_FILER_COEFF_3 0x2 + +/* Temperature measurement */ +#define TEMPERATURE_OVERSAMPLING_2X 0x2 +#define TEMP_OVERSAMPLING_BIT_MSK 1 << 7 | 1 << 6 | 1 << 5 +#define TEMP_OVERSAMPLING_BIT_SHIFT 5 + +#define TEMP_ADC_DATA_MSB_0 0x22 +#define TEMP_ADC_DATA_LSB_0 0x23 +#define TEMP_ADC_DATA_XLSB_0 0x24 + +/* Pressure measurement */ +#define PRESSURE_OVERSAMPLING_16X 0x5 +#define PRES_OVERSAMPLING_BIT_MSK 1 << 4 | 1 << 3 | 1 << 2 +#define PRES_OVERSAMPLING_BIT_SHIFT 2 + +#define PRES_ADC_DATA_MSB_0 0x1F +#define PRES_ADC_DATA_LSB_0 0x20 +#define PRES_ADC_DATA_XLSB_0 0x21 + +/* Humidity measurement */ +#define HUMIDITY_OVERSAMPLING_1X 0x1 +#define HUMIDITY_OVERSAMPLING_BIT_MSK 1 << 2 | 1 << 1 | 1 +#define HUMIDITY_OVERSAMPLING_BIT_SHIFT 0 + +#define HUM_ADC_DATA_MSB_0 0x25 +#define HUM_ADC_DATA_LSB_0 0x26 + +/* Measurement status */ +#define MEAS_STATUS_0_REG_ADDRESS 0x1D +#define MEAS_STATUS_1_REG_ADDRESS 0x2E +#define MEAS_STATUS_2_REG_ADDRESS 0x3F +#define MEASUREMENT_IN_PROGRESS_BIT_MASK 1 << 5 +#define MEASUREMENT_NEW_DATA_BIT_MASK 1 << 7 + +struct calibration_coeffs { + /* Temperature */ + uint16_t par_t1; + uint16_t par_t2; + uint8_t par_t3; + + /* Humidity */ + uint16_t par_h1; + uint16_t par_h2; + uint8_t par_h3; + uint8_t par_h4; + uint8_t par_h5; + uint8_t par_h6; + uint8_t par_h7; + + /* Pressure */ + uint16_t par_p1; + int16_t par_p2; + int8_t par_p3; + int16_t par_p4; + int16_t par_p5; + int8_t par_p6; + int8_t par_p7; + int16_t par_p8; + int16_t par_p9; + uint8_t par_p10; +}; + +/* Calculate the compensated temperature + * Note: 't_fine' is required for other measurements + */ +int32_t calculate_temperature(uint32_t adc_temp, int32_t *t_fine, + struct calibration_coeffs *cal_coeffs); + +/* Calculate the compensated pressure + * Note: temperature must be calculated first + * to obtain the 't_fine' + */ +uint32_t calculate_pressure(uint32_t pres_adc, int32_t t_fine, + struct calibration_coeffs *cal_coeffs); + +/* Calculate the relative humidity + * Note: temperature must be calculated first + * to obtain the 't_fine' + */ +uint32_t calculate_humidity(uint16_t hum_adc, int32_t t_fine, + struct calibration_coeffs *cal_coeffs); + +#endif diff --git a/tests/drivers/i2c/i2c_bme688/testcase.yaml b/tests/drivers/i2c/i2c_bme688/testcase.yaml new file mode 100644 index 00000000000000..e36d79089f9a0d --- /dev/null +++ b/tests/drivers/i2c/i2c_bme688/testcase.yaml @@ -0,0 +1,6 @@ +common: + tags: drivers i2c + depends_on: i2c +tests: + drivers.i2c.bme688: + filter: dt_compat_enabled("bosch,bme680") From 2a571090f9121c4ee76462a096b03e2eff832d6f Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0629/1389] drivers: usb: stm32: fix logic for USB clock configuration - If the peripheral is OTG_HS with ULPI, enable the OTG_HS ULPI clock - The constant has a slightly different name on stm32h7 - Otherwise, if the peripheral is OTG_HS: - Disable the OTG_HS ULPI clock in sleep/low power mode, - If the peripheral is OTG_HS with PHYC[1], enable the PHYC clock. - Otherwise, if the peripheral is OTG_FS[2] on stm32h7, also disable the OTG_FS ULPI clock in sleep mode (in the device/ driver, this is done in usb_dc_stm32_init()), [1]: Internal HS PHY in stm32f7x2xx and (some) stm32f730xx [2]: "OTG_FS" on stm32h7 is really just another OTG_HS peripheral, but without any way to actually connect a HS PHY Signed-off-by: Armin Brauns --- drivers/usb/device/usb_dc_stm32.c | 31 ++++++++++++++-------------- drivers/usb/udc/udc_stm32.c | 34 +++++++++++++++---------------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/drivers/usb/device/usb_dc_stm32.c b/drivers/usb/device/usb_dc_stm32.c index ad9c6ac520cab1..fbc7ff07e71cf0 100644 --- a/drivers/usb/device/usb_dc_stm32.c +++ b/drivers/usb/device/usb_dc_stm32.c @@ -265,27 +265,26 @@ static int usb_dc_stm32_clock_enable(void) #endif /* RCC_CFGR_OTGFSPRE / RCC_CFGR_USBPRE */ -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) +#if USB_OTG_HS_ULPI_PHY +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI); - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); -#elif defined(CONFIG_SOC_SERIES_STM32H7X) -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in sleep - * mode. - */ - LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); #endif -#else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in low - * power mode. It is disabled by default in run power mode, no need to - * disable it. +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) /* USB_OTG_HS_ULPI_PHY */ + /* Disable ULPI interface (for external high-speed PHY) clock in sleep/low-power mode. It is + * disabled by default in run power mode, no need to disable it. */ +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); +#endif + +#if USB_OTG_HS_EMB_PHY + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); +#endif #endif /* USB_OTG_HS_ULPI_PHY */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */ return 0; } diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c index 1e75fe49d70971..e86893b1b18f89 100644 --- a/drivers/usb/udc/udc_stm32.c +++ b/drivers/usb/udc/udc_stm32.c @@ -974,33 +974,31 @@ static int priv_clock_enable(void) #endif /* RCC_CFGR_OTGFSPRE / RCC_CFGR_USBPRE */ -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) +#if USB_OTG_HS_ULPI_PHY +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI); - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); -#elif defined(CONFIG_SOC_SERIES_STM32H7X) -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in sleep - * mode. +#endif +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) /* USB_OTG_HS_ULPI_PHY */ + /* Disable ULPI interface (for external high-speed PHY) clock in sleep/low-power mode. It is + * disabled by default in run power mode, no need to disable it. */ +#if defined(CONFIG_SOC_SERIES_STM32H7X) LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else + LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); +#endif /* defined(CONFIG_SOC_SERIES_STM32H7X) */ + +#if USB_OTG_HS_EMB_PHY + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); #endif -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) && DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) /* The USB2 controller only works in FS mode, but the ULPI clock needs * to be disabled in sleep mode for it to work. */ LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB2OTGHSULPI); -#endif -#else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in low - * power mode. It is disabled by default in run power mode, no need to - * disable it. - */ - LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); #endif /* USB_OTG_HS_ULPI_PHY */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */ return 0; } From e8cf5c0ad4bfc24c4a414d39d8d2b1379046b23d Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0630/1389] dts: stm32f7: add clock definition for OTG_HS peripheral This peripheral is also run off the 48MHz clock, just like OTG_FS. Signed-off-by: Armin Brauns --- dts/arm/st/f7/stm32f7.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index a20419f001d36d..ea80dbe86afc5d 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -714,7 +714,8 @@ num-bidir-endpoints = <9>; ram-size = <4096>; maximum-speed = "full-speed"; - clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x20000000>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x20000000>, + <&rcc STM32_SRC_PLL_Q CK48M_SEL(0)>; phys = <&otghs_fs_phy>; status = "disabled"; }; From e20b76da22f5ed374c0d395176d55d30bec49ecf Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0631/1389] boards: stm32f769i_disco: enable USB This board uses a ULPI PHY to provide HS (USB 2.0) connectivitiy instead of the internal PHY, which only supports FW (USB 1.x). Signed-off-by: Armin Brauns --- .../st/stm32f769i_disco/stm32f769i_disco.dts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/boards/st/stm32f769i_disco/stm32f769i_disco.dts b/boards/st/stm32f769i_disco/stm32f769i_disco.dts index feb0f2f11a2852..22b981b50225a1 100644 --- a/boards/st/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/st/stm32f769i_disco/stm32f769i_disco.dts @@ -32,6 +32,11 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + otghs_ulpi_phy: otghs_ulpis_phy { + compatible = "usb-ulpi-phy"; + #phy-cells = <0>; + }; + leds { compatible = "gpio-leds"; red_led_1:led_1 { @@ -238,3 +243,22 @@ arduino_serial: &usart6 {}; }; }; }; + +zephyr_udc0: &usbotg_hs { + pinctrl-0 = <&usb_otg_hs_ulpi_ck_pa5 + &usb_otg_hs_ulpi_d0_pa3 + &usb_otg_hs_ulpi_d1_pb0 + &usb_otg_hs_ulpi_d2_pb1 + &usb_otg_hs_ulpi_d3_pb10 + &usb_otg_hs_ulpi_d4_pb11 + &usb_otg_hs_ulpi_d5_pb12 + &usb_otg_hs_ulpi_d6_pb13 + &usb_otg_hs_ulpi_d7_pb5 + &usb_otg_hs_ulpi_stp_pc0 + &usb_otg_hs_ulpi_dir_pi11 + &usb_otg_hs_ulpi_nxt_ph4>; + pinctrl-names = "default"; + maximum-speed = "high-speed"; + phys = <&otghs_ulpi_phy>; + status = "okay"; +}; From 7be0164c19ca78792918b92992f7e558ceccb13c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0632/1389] soc: smartbond: Move PM_DEVICE dependency to soc For DA1469x if PM config is selected PM_DEVICE must also be selected for GPIO to work when device enters/exists deep sleep. Previously GPIO and regulator drivers selected PM_DEVICE when PM was enabled. Now it is moved to SOC instead. PM_DEVICE selection in GPIO could result in circular dependency for mcux if MEMC_MCUX_FLEXSPI (which is already dependent on PM_DEVICE) was to be additionally dependent on GPIO. Signed-off-by: Jerzy Kasenberg --- drivers/gpio/Kconfig.smartbond | 1 - drivers/regulator/Kconfig.da1469x | 1 - soc/renesas/smartbond/da1469x/Kconfig | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/Kconfig.smartbond b/drivers/gpio/Kconfig.smartbond index 59c8b2f109f155..5e624cd30119a2 100644 --- a/drivers/gpio/Kconfig.smartbond +++ b/drivers/gpio/Kconfig.smartbond @@ -5,6 +5,5 @@ config GPIO_SMARTBOND bool "Renesas SmartBond(tm) GPIO driver" default y depends on DT_HAS_RENESAS_SMARTBOND_GPIO_ENABLED - select PM_DEVICE if PM help Enable GPIO driver for Renesas SmartBond(tm) MCU family. diff --git a/drivers/regulator/Kconfig.da1469x b/drivers/regulator/Kconfig.da1469x index 142634ae5e81ff..d8205ed4925dff 100644 --- a/drivers/regulator/Kconfig.da1469x +++ b/drivers/regulator/Kconfig.da1469x @@ -4,7 +4,6 @@ config REGULATOR_DA1469X bool "DA1469X regulators driver" default y - select PM_DEVICE if PM depends on DT_HAS_RENESAS_SMARTBOND_REGULATOR_ENABLED help Enable support for the Smartbond DA1469x regulators. diff --git a/soc/renesas/smartbond/da1469x/Kconfig b/soc/renesas/smartbond/da1469x/Kconfig index 0dcaed68f02843..c987b579c10329 100644 --- a/soc/renesas/smartbond/da1469x/Kconfig +++ b/soc/renesas/smartbond/da1469x/Kconfig @@ -13,3 +13,4 @@ config SOC_SERIES_DA1469X select CLOCK_CONTROL select CLOCK_CONTROL_SMARTBOND select PLATFORM_SPECIFIC_INIT + select PM_DEVICE if PM From 47cc9f4af5df26ae909fad46abf04e620f73c152 Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0633/1389] boards: waveshare: esp32s3_touch: update appcpu supported peripherals esp32s3 contains 2 cpus: procpu and appcpu. appcpu has very limited peripherals support for now. This updated esp32s3_touch board to list only support peripherals. Signed-off-by: Sylvio Alves --- ...esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml index bd677cef701c15..c42258133ae272 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml @@ -5,18 +5,23 @@ arch: xtensa toolchain: - zephyr supported: - - gpio - - i2c - - spi - - watchdog - - regulator - uart - - pwm - - pinmux - - nvs - - display testing: ignore_tags: - net - bluetooth + - flash + - cpp + - posix + - watchdog + - logging + - kernel + - pm + - gpio + - crypto + - eeprom + - heap + - cmsis_rtos + - jwt + - zdsp vendor: waveshare From c2737b3d5313a2391ade063e52629fdcfdebd66c Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0634/1389] Bluetooth: Audio: Shell Remove BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE Do not enable BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE as it depends on EATT which isn't enabled. Signed-off-by: Emil Gydesen --- tests/bluetooth/shell/audio.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/bluetooth/shell/audio.conf b/tests/bluetooth/shell/audio.conf index bfc9e3f452aebb..e783677ad0fc50 100644 --- a/tests/bluetooth/shell/audio.conf +++ b/tests/bluetooth/shell/audio.conf @@ -153,7 +153,6 @@ CONFIG_BT_HAS_PRESET_NAME_DYNAMIC=y CONFIG_BT_HAS_PRESET_COUNT=4 CONFIG_BT_HAS_CLIENT=y CONFIG_BT_HAS_FEATURES_NOTIFIABLE=y -CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE=y # Common Audio Profile CONFIG_BT_CAP_ACCEPTOR=y From 696d9d7d49d43340188e3b09c3d6586d86adb5a9 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0635/1389] driver: uart: native: fix stop_bits/databits mix Correct a trivial bug and doxygen documentation error in which data_bits was missused instead of stop_bits. Signed-off-by: Alberto Escolar Piedras Signed-off-by: Mateusz Grzywacz --- drivers/serial/uart_native_tty.c | 2 +- drivers/serial/uart_native_tty_bottom.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/serial/uart_native_tty.c b/drivers/serial/uart_native_tty.c index 8eb51bff5b873f..4f2acc50b340b1 100644 --- a/drivers/serial/uart_native_tty.c +++ b/drivers/serial/uart_native_tty.c @@ -90,7 +90,7 @@ static int native_tty_conv_to_bottom_cfg(struct native_tty_bottom_cfg *bottom_cf return -ENOTSUP; } - switch (cfg->data_bits) { + switch (cfg->stop_bits) { case UART_CFG_STOP_BITS_1: bottom_cfg->stop_bits = NTB_STOP_BITS_1; break; diff --git a/drivers/serial/uart_native_tty_bottom.c b/drivers/serial/uart_native_tty_bottom.c index cb8e4162a662c2..279ebca410005e 100644 --- a/drivers/serial/uart_native_tty_bottom.c +++ b/drivers/serial/uart_native_tty_bottom.c @@ -144,7 +144,7 @@ static inline void native_tty_stop_bits_set(struct termios *ter, * @brief Set the number of data bits in the termios structure * * @param ter - * @param stop_bits + * @param data_bits * */ static inline void native_tty_data_bits_set(struct termios *ter, From f6778224400765da56b46156fb6a26e7f92e31a1 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0636/1389] boards: nxp: mixmxrt1170_evk: Separate i2c6 from csi pin muxing Pin muxing for i2c6 and csi should be separated as i2c is initialized before csi. Otherwise, i2c6 bus device will not be ready when the camera sensor on this bus initializes. Signed-off-by: Phi Bang Nguyen --- boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi | 5 ++++- boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi index 26c910b55c52ba..43b1642da96f91 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi @@ -23,7 +23,10 @@ bias-pull-up; slew-rate = "fast"; }; - group2 { + }; + + pinmux_lpi2c6: pinmux_lpi2c6 { + group0 { pinmux = <&iomuxc_lpsr_gpio_lpsr_07_lpi2c6_scl>, <&iomuxc_lpsr_gpio_lpsr_06_lpi2c6_sda>; drive-strength = "high"; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi index a1d680a1e746d7..e70890f911d4f2 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi @@ -130,6 +130,11 @@ pinctrl-names = "default"; }; +&lpi2c6 { + pinctrl-0 = <&pinmux_lpi2c6>; + pinctrl-names = "default"; +}; + &flexcan3 { pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; From ae0f177725ca70c69c8b0d39f4776fc5b467c653 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:38:59 +0200 Subject: [PATCH 0637/1389] net: context: Do not check our own ports There is no need to check our own context when going through the used ports in the system. This prevents error when binding in some corner cases. Fixes #72035 Signed-off-by: Jukka Rissanen --- subsys/net/ip/net_context.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 77d829a570fd6f..20b85237aea27f 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -156,7 +156,8 @@ static inline bool is_in_tcp_time_wait_state(struct net_context *context) #endif } -static int check_used_port(struct net_if *iface, +static int check_used_port(struct net_context *context, + struct net_if *iface, enum net_ip_protocol proto, uint16_t local_port, const struct sockaddr *local_addr, @@ -170,6 +171,10 @@ static int check_used_port(struct net_if *iface, continue; } + if (context != NULL && context == &contexts[i]) { + continue; + } + if (!(net_context_get_proto(&contexts[i]) == proto && net_sin((struct sockaddr *)& contexts[i].local)->sin_port == local_port)) { @@ -313,7 +318,7 @@ static uint16_t find_available_port(struct net_context *context, do { local_port = sys_rand16_get() | 0x8000; - } while (check_used_port(NULL, net_context_get_proto(context), + } while (check_used_port(context, NULL, net_context_get_proto(context), htons(local_port), addr, false, false) == -EEXIST); return htons(local_port); @@ -327,7 +332,8 @@ bool net_context_port_in_use(enum net_ip_protocol proto, uint16_t local_port, const struct sockaddr *local_addr) { - return check_used_port(NULL, proto, htons(local_port), local_addr, false, false) != 0; + return check_used_port(NULL, NULL, proto, htons(local_port), + local_addr, false, false) != 0; } #if defined(CONFIG_NET_CONTEXT_CHECK) @@ -794,7 +800,7 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr, ret = 0; if (addr6->sin6_port) { - ret = check_used_port(iface, + ret = check_used_port(context, iface, context->proto, addr6->sin6_port, addr, @@ -894,7 +900,7 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr, ret = 0; if (addr4->sin_port) { - ret = check_used_port(iface, + ret = check_used_port(context, iface, context->proto, addr4->sin_port, addr, From c824d5c2058cd607c5f5aef0454ff0cf4b2c76ae Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0638/1389] twister: Refactor 'recording' feature Refactor Twister 'recording' feature moving it from Handler class to TestInstance class and enable it also for other Harness child classes other than Console. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/handlers.py | 19 +-------- scripts/pylib/twister/twisterlib/harness.py | 15 ++++--- .../pylib/twister/twisterlib/testinstance.py | 17 ++++++++ scripts/tests/twister/test_handlers.py | 39 ++----------------- scripts/tests/twister/test_harness.py | 28 +++++++++++++ scripts/tests/twister/test_testinstance.py | 31 +++++++++++++++ 6 files changed, 90 insertions(+), 59 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index eaef473af71d74..c3fe7da2f56a07 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -5,7 +5,6 @@ # Copyright 2022 NXP # SPDX-License-Identifier: Apache-2.0 -import csv import logging import math import os @@ -97,22 +96,6 @@ def get_test_timeout(self): self.instance.platform.timeout_multiplier * self.options.timeout_multiplier) - def record(self, harness): - if harness.recording: - if self.instance.recording is None: - self.instance.recording = harness.recording.copy() - else: - self.instance.recording.extend(harness.recording) - - filename = os.path.join(self.build_dir, "recording.csv") - with open(filename, "at") as csvfile: - cw = csv.DictWriter(csvfile, - fieldnames = harness.recording[0].keys(), - lineterminator = os.linesep, - quoting = csv.QUOTE_NONNUMERIC) - cw.writeheader() - cw.writerows(harness.recording) - def terminate(self, proc): terminate_process(proc) self.terminated = True @@ -165,7 +148,7 @@ def _final_handle_actions(self, harness, handler_time): for tc in self.instance.testcases: tc.status = "failed" - self.record(harness) + self.instance.record(harness.recording) class BinaryHandler(Handler): diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index c8aa437930049c..061e19ec9b2b76 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -91,9 +91,19 @@ def get_testcase_name(self): """ return self.id + def parse_record(self, line) -> re.Match: + match = None + if self.record_pattern: + match = self.record_pattern.search(line) + if match: + self.recording.append({ k:v.strip() for k,v in match.groupdict(default="").items() }) + return match + # def process_test(self, line): + self.parse_record(line) + runid_match = re.search(self.run_id_pattern, line) if runid_match: run_id = runid_match.group("run_id") @@ -251,11 +261,6 @@ def handle(self, line): elif self.GCOV_END in line: self.capture_coverage = False - if self.record_pattern: - match = self.record_pattern.search(line) - if match: - self.recording.append({ k:v.strip() for k,v in match.groupdict(default="").items() }) - self.process_test(line) # Reset the resulting test state to 'failed' when not all of the patterns were # found in the output, but just ztest's 'PROJECT EXECUTION SUCCESSFUL'. diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index 5be57e1deb69fc..fb0fc1d909b483 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -10,6 +10,7 @@ import logging import shutil import glob +import csv from twisterlib.testsuite import TestCase, TestSuite from twisterlib.platform import Platform @@ -73,6 +74,22 @@ def __init__(self, testsuite, platform, outdir): self.filters = [] self.filter_type = None + def record(self, recording, fname_csv="recording.csv"): + if recording: + if self.recording is None: + self.recording = recording.copy() + else: + self.recording.extend(recording) + + filename = os.path.join(self.build_dir, fname_csv) + with open(filename, "wt") as csvfile: + cw = csv.DictWriter(csvfile, + fieldnames = self.recording[0].keys(), + lineterminator = os.linesep, + quoting = csv.QUOTE_NONNUMERIC) + cw.writeheader() + cw.writerows(self.recording) + def add_filter(self, reason, filter_type): self.filters.append({'type': filter_type, 'reason': reason }) self.status = "filtered" diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 7eddd016ca9afd..7a3b56a130f513 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -129,6 +129,7 @@ def test_handler_final_handle_actions(mocked_instance): harness.detected_suite_names = mock.Mock() harness.matched_run_id = False harness.run_id_exists = True + harness.recording = mock.Mock() handler_time = mock.Mock() @@ -143,6 +144,8 @@ def test_handler_final_handle_actions(mocked_instance): handler.instance.reason = 'This reason shan\'t be changed.' handler._final_handle_actions(harness, handler_time) + instance.assert_has_calls([mock.call.record(harness.recording)]) + assert handler.instance.reason == 'This reason shan\'t be changed.' @@ -204,42 +207,6 @@ def test_handler_missing_suite_name(mocked_instance): ) -def test_handler_record(mocked_instance): - instance = mocked_instance - instance.testcases = [mock.Mock()] - - handler = Handler(instance) - - harness = twisterlib.harness.Harness() - harness.recording = [ {'field_1': 'recording_1_1', 'field_2': 'recording_1_2'}, - {'field_1': 'recording_2_1', 'field_2': 'recording_2_2'} - ] - - with mock.patch( - 'builtins.open', - mock.mock_open(read_data='') - ) as mock_file, \ - mock.patch( - 'csv.DictWriter.writerow', - mock.Mock() - ) as mock_writeheader, \ - mock.patch( - 'csv.DictWriter.writerows', - mock.Mock() - ) as mock_writerows: - handler.record(harness) - - print(mock_file.mock_calls) - - mock_file.assert_called_with( - os.path.join(instance.build_dir, 'recording.csv'), - 'at' - ) - - mock_writeheader.assert_has_calls([mock.call({ k:k for k in harness.recording[0].keys()})]) - mock_writerows.assert_has_calls([mock.call(harness.recording)]) - - def test_handler_terminate(mocked_instance): def mock_kill_function(pid, sig): if pid < 0: diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index 3657163a7ba45b..a01d313cb28ee6 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -44,6 +44,32 @@ def process_logs(harness, logs): harness.handle(line) +TEST_DATA_RECORDING = [ + ([''], "^START:(?P.*):END", []), + (['START:bar:STOP'], "^START:(?P.*):END", []), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}]), + (['START:bar:baz:END'], "^START:(?P.*):(?P.*):END", [{'foo':'bar', 'boo':'baz'}]), + (['START:bar:baz:END','START:may:jun:END'], "^START:(?P.*):(?P.*):END", + [{'foo':'bar', 'boo':'baz'}, {'foo':'may', 'boo':'jun'}]), + ] +@pytest.mark.parametrize( + "lines, pattern, expected_records", + TEST_DATA_RECORDING, + ids=["empty", "no match", "match 1 field", "match 2 fields", "match 2 records"] +) +def test_harness_parse_record(lines, pattern, expected_records): + harness = Harness() + harness.record = { 'regex': pattern } + harness.record_pattern = re.compile(pattern) + + assert not harness.recording + + for line in lines: + harness.parse_record(line) + + assert harness.recording == expected_records + + TEST_DATA_1 = [('RunID: 12345', False, False, False, None, True), ('PROJECT EXECUTION SUCCESSFUL', False, False, False, 'passed', False), ('PROJECT EXECUTION SUCCESSFUL', True, False, False, 'failed', False), @@ -63,6 +89,7 @@ def test_harness_process_test(line, fault, fail_on_fault, cap_cov, exp_stat, exp harness.state = None harness.fault = fault harness.fail_on_fault = fail_on_fault + mock.patch.object(Harness, 'parse_record', return_value=None) #Act harness.process_test(line) @@ -71,6 +98,7 @@ def test_harness_process_test(line, fault, fail_on_fault, cap_cov, exp_stat, exp assert harness.matched_run_id == exp_id assert harness.state == exp_stat assert harness.capture_coverage == cap_cov + assert harness.recording == [] def test_robot_configure(tmp_path): diff --git a/scripts/tests/twister/test_testinstance.py b/scripts/tests/twister/test_testinstance.py index 1b1c99a2143583..4f820532aeaf70 100644 --- a/scripts/tests/twister/test_testinstance.py +++ b/scripts/tests/twister/test_testinstance.py @@ -226,6 +226,37 @@ def test_testinstance_init(all_testsuites_dict, class_testplan, platforms_list, assert testinstance.build_dir == os.path.join(class_testplan.env.outdir, platform.name, testsuite.source_dir_rel, testsuite.name) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'sample'}], indirect=True) +def test_testinstance_record(testinstance): + testinstance.testcases = [mock.Mock()] + recording = [ {'field_1': 'recording_1_1', 'field_2': 'recording_1_2'}, + {'field_1': 'recording_2_1', 'field_2': 'recording_2_2'} + ] + with mock.patch( + 'builtins.open', + mock.mock_open(read_data='') + ) as mock_file, \ + mock.patch( + 'csv.DictWriter.writerow', + mock.Mock() + ) as mock_writeheader, \ + mock.patch( + 'csv.DictWriter.writerows', + mock.Mock() + ) as mock_writerows: + testinstance.record(recording) + + print(mock_file.mock_calls) + + mock_file.assert_called_with( + os.path.join(testinstance.build_dir, 'recording.csv'), + 'wt' + ) + + mock_writeheader.assert_has_calls([mock.call({ k:k for k in recording[0]})]) + mock_writerows.assert_has_calls([mock.call(recording)]) + + @pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'sample'}], indirect=True) def test_testinstance_add_filter(testinstance): reason = 'dummy reason' From 32bc27685c14fa877f8c33f7f882973e5a302940 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0639/1389] twister: pytest: Enable recording for Pytest Harness Extend Pytest Harness to support 'recording' feature to parse test log by a regular expression and collect as records the same way as Console Harness do. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/harness.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 061e19ec9b2b76..6fd6dae73a899d 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -312,6 +312,7 @@ def pytest_run(self, timeout): finally: if self.reserved_serial: self.instance.handler.make_device_available(self.reserved_serial) + self.instance.record(self.recording) self._update_test_status() def generate_command(self): @@ -418,7 +419,7 @@ def run_command(self, cmd, timeout): env=env ) as proc: try: - reader_t = threading.Thread(target=self._output_reader, args=(proc,), daemon=True) + reader_t = threading.Thread(target=self._output_reader, args=(proc, self), daemon=True) reader_t.start() reader_t.join(timeout) if reader_t.is_alive(): @@ -455,12 +456,13 @@ def _update_command_with_env_dependencies(cmd): return cmd, env @staticmethod - def _output_reader(proc): + def _output_reader(proc, harness): while proc.stdout.readable() and proc.poll() is None: line = proc.stdout.readline().decode().strip() if not line: continue logger.debug('PYTEST: %s', line) + harness.parse_record(line) proc.communicate() def _update_test_status(self): From 9466e7f2684f4e08c4024556c96b5d6cf5e494a8 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0640/1389] scripts: compliance: handle multi-line output from pylint Switch from plain text to JSON output in the pylint compliance check in order to handle multi-line messages, which were so far being dropped by the regex. Fixes #68037. Signed-off-by: Carles Cufi --- scripts/ci/check_compliance.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 1bd39950ddefea..e82e7f95ac14bf 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -7,6 +7,7 @@ import argparse import collections from email.utils import parseaddr +import json import logging import os from pathlib import Path @@ -178,7 +179,6 @@ def fmtd_failure(self, severity, title, file, line=None, col=None, desc=""): self._result(fail, fail.text) self.fmtd_failures.append(fail) - class EndTest(Exception): """ Raised by ComplianceTest.error()/skip() to end the test. @@ -1169,7 +1169,7 @@ def run(self): else: python_environment["PYTHONPATH"] = check_script_dir - pylintcmd = ["pylint", "--rcfile=" + pylintrc, + pylintcmd = ["pylint", "--output-format=json2", "--rcfile=" + pylintrc, "--load-plugins=argparse-checker"] + py_files logger.info(cmd2str(pylintcmd)) try: @@ -1181,21 +1181,19 @@ def run(self): env=python_environment) except subprocess.CalledProcessError as ex: output = ex.output.decode("utf-8") - regex = r'^\s*(\S+):(\d+):(\d+):\s*([A-Z]\d{4}):\s*(.*)$' - - matches = re.findall(regex, output, re.MULTILINE) - for m in matches: - # https://pylint.pycqa.org/en/latest/user_guide/messages/messages_overview.html# + messages = json.loads(output)['messages'] + for m in messages: severity = 'unknown' - if m[3][0] in ('F', 'E'): + if m['messageId'][0] in ('F', 'E'): severity = 'error' - elif m[3][0] in ('W','C', 'R', 'I'): + elif m['messageId'][0] in ('W','C', 'R', 'I'): severity = 'warning' - self.fmtd_failure(severity, m[3], m[0], m[1], col=m[2], - desc=m[4]) + self.fmtd_failure(severity, m['messageId'], m['path'], + m['line'], col=str(m['column']), desc=m['message'] + + f" ({m['symbol']})") - # If the regex has not matched add the whole output as a failure - if len(matches) == 0: + if len(messages) == 0: + # If there are no specific messages add the whole output as a failure self.failure(output) From 376a87954821696de4eefa92a72cc656bc9a9c5e Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0641/1389] net: ipv6: Fix missing DAD for link-local address In case a network interface is brought down and back up, DAD was not performed for link-local unicast address. This happens because the logic in the network interface code assumed that DAD for link-local address is triggered when the address is added, and it's explicitly omited when looping over IPv6 address. This wasn't the case however when interface was brought back up, as the address was already present on the interface, hence DAD skipped. In Linux, the link-local address is removed from the interface when the interface is brought down. Such approach solves the issue described, hence implement it in a similar way in Zephyr. Signed-off-by: Robert Lubos --- subsys/net/ip/net_if.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 7106c38e735a46..c59d3031f63b24 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -3171,6 +3171,20 @@ static void iface_ipv6_start(struct net_if *iface) net_if_start_rs(iface); } +static void iface_ipv6_stop(struct net_if *iface) +{ + struct in6_addr addr = { }; + + if (!net_if_flag_is_set(iface, NET_IF_IPV6) || + net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { + return; + } + + net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface)); + + (void)net_if_ipv6_addr_rm(iface, &addr); +} + static void iface_ipv6_init(int if_count) { iface_ipv6_dad_init(); @@ -3203,6 +3217,7 @@ static void iface_ipv6_init(int if_count) #define leave_mcast_all(...) #define join_mcast_nodes(...) #define iface_ipv6_start(...) +#define iface_ipv6_stop(...) #define iface_ipv6_init(...) struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *addr, @@ -5034,6 +5049,7 @@ static void notify_iface_down(struct net_if *iface) if (!net_if_is_offloaded(iface) && !(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) { + iface_ipv6_stop(iface); net_ipv4_autoconf_reset(iface); } } From 1b46aac180a795fb8d222029050ce2961489aa3d Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0642/1389] net: ipv6: Rejoin all solicited node mcast addresses When bringing interface down, all IPv6 multicast addresses are removed from the interface. However, when the interface was brought back up, rejoin_ipv6_mcast_groups() would look only for solicited node mcast addresses already present on the interface. In result, after going back up, the interface was missing solicited-node mcast addresses for those unicast addresses, that were already present on the interface when bringing up. As net_ipv6_mld_join() does similar checks to skip MLD when not needed, we can just skip the lookup when rejoining, and use already defined join_mcast_nodes(). Additionally, check for IPV6 and NO_ND flags on the interface before attempting to add the address back, those multicast addresses are not needed if ND is disabled on the interface. Signed-off-by: Robert Lubos --- subsys/net/ip/net_if.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index c59d3031f63b24..2ff4a1017a602e 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1658,37 +1658,21 @@ static void rejoin_ipv6_mcast_groups(struct net_if *iface) net_if_lock(iface); + if (!net_if_flag_is_set(iface, NET_IF_IPV6) || + net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { + goto out; + } + if (net_if_config_ipv6_get(iface, &ipv6) < 0) { goto out; } ARRAY_FOR_EACH(ipv6->unicast, i) { - struct net_if_mcast_addr *maddr; - struct in6_addr addr; - int ret; - if (!ipv6->unicast[i].is_used) { continue; } - net_ipv6_addr_create_solicited_node( - &ipv6->unicast[i].address.in6_addr, - &addr); - - maddr = net_if_ipv6_maddr_lookup(&addr, &iface); - if (!maddr) { - continue; - } - - if (net_if_ipv4_maddr_is_joined(maddr)) { - continue; - } - - ret = net_ipv6_mld_join(iface, &addr); - if (ret < 0 && ret != EALREADY) { - NET_DBG("Cannot rejoin multicast group %s (%d)", - net_sprint_ipv6_addr(&addr), ret); - } + join_mcast_nodes(iface, &ipv6->unicast[i].address.in6_addr); } out: From e7d82885e7968e85990828fe26f465ead821f6eb Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0643/1389] net: ipv6: Clear joined flag on all mcast address when operational down When the network inteface goes operational DOWN (for example cable unplugged), clear "joined" flag on all registered multicast addresses, so that MLD report is sent for them when the interface goes back up. Signed-off-by: Robert Lubos --- subsys/net/ip/net_if.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 2ff4a1017a602e..1dbc0fb46a6b83 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1667,6 +1667,7 @@ static void rejoin_ipv6_mcast_groups(struct net_if *iface) goto out; } + /* Rejoin solicited node multicasts. */ ARRAY_FOR_EACH(ipv6->unicast, i) { if (!ipv6->unicast[i].is_used) { continue; @@ -1675,6 +1676,52 @@ static void rejoin_ipv6_mcast_groups(struct net_if *iface) join_mcast_nodes(iface, &ipv6->unicast[i].address.in6_addr); } + /* Rejoin any mcast address present on the interface, but marked as not joined. */ + ARRAY_FOR_EACH(ipv6->mcast, i) { + int ret; + + if (!ipv6->mcast[i].is_used || + net_if_ipv4_maddr_is_joined(&ipv6->mcast[i])) { + continue; + } + + ret = net_ipv6_mld_join(iface, &ipv6->mcast[i].address.in6_addr); + if (ret < 0) { + NET_ERR("Cannot join mcast address %s for %d (%d)", + net_sprint_ipv6_addr(&ipv6->mcast[i].address.in6_addr), + net_if_get_by_iface(iface), ret); + } + } + +out: + net_if_unlock(iface); +} + +/* To be called when interface comes operational down so that multicast + * groups are rejoined when back up. + */ +static void clear_joined_ipv6_mcast_groups(struct net_if *iface) +{ + struct net_if_ipv6 *ipv6; + + net_if_lock(iface); + + if (!net_if_flag_is_set(iface, NET_IF_IPV6)) { + goto out; + } + + if (net_if_config_ipv6_get(iface, &ipv6) < 0) { + goto out; + } + + ARRAY_FOR_EACH(ipv6->mcast, i) { + if (!ipv6->mcast[i].is_used) { + continue; + } + + net_if_ipv6_maddr_leave(iface, &ipv6->mcast[i]); + } + out: net_if_unlock(iface); } @@ -3199,6 +3246,7 @@ static void iface_ipv6_init(int if_count) #define join_mcast_allnodes(...) #define join_mcast_solicit_node(...) #define leave_mcast_all(...) +#define clear_joined_ipv6_mcast_groups(...) #define join_mcast_nodes(...) #define iface_ipv6_start(...) #define iface_ipv6_stop(...) @@ -5034,6 +5082,7 @@ static void notify_iface_down(struct net_if *iface) if (!net_if_is_offloaded(iface) && !(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) { iface_ipv6_stop(iface); + clear_joined_ipv6_mcast_groups(iface); net_ipv4_autoconf_reset(iface); } } From 57c52ff8401609206b1761b30f467fe6113df968 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0644/1389] tests: net: dhcpv6: Reapply LL address on iface up The test suite assigns LL address to the interface manually, hence need to reapply it whenever interface goes up. Signed-off-by: Robert Lubos --- tests/net/dhcpv6/src/main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/net/dhcpv6/src/main.c b/tests/net/dhcpv6/src/main.c index ace0a0128c2ff5..c5046a2746a215 100644 --- a/tests/net/dhcpv6/src/main.c +++ b/tests/net/dhcpv6/src/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "../../../subsys/net/lib/dhcpv6/dhcpv6.c" @@ -18,6 +19,7 @@ static struct in6_addr test_prefix = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, static uint8_t test_prefix_len = 64; static uint8_t test_preference; static struct net_dhcpv6_duid_storage test_serverid; +static struct net_mgmt_event_callback net_mgmt_cb; typedef void (*test_dhcpv6_pkt_fn_t)(struct net_if *iface, struct net_pkt *pkt); @@ -176,6 +178,19 @@ static struct net_pkt *test_dhcpv6_create_message( return NULL; } +static void evt_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, + struct net_if *iface) +{ + ARG_UNUSED(cb); + + if (mgmt_event == NET_EVENT_IF_UP) { + struct in6_addr lladdr; + + net_ipv6_addr_create_iid(&lladdr, net_if_get_link_addr(test_ctx.iface)); + (void)net_if_ipv6_addr_add(test_ctx.iface, &lladdr, NET_ADDR_AUTOCONF, 0); + } +} + static void *dhcpv6_tests_setup(void) { struct in6_addr lladdr; @@ -190,6 +205,9 @@ static void *dhcpv6_tests_setup(void) generate_fake_server_duid(); + net_mgmt_init_event_callback(&net_mgmt_cb, evt_handler, NET_EVENT_IF_UP); + net_mgmt_add_event_callback(&net_mgmt_cb); + return NULL; } From a1bc58a61164e2c185fde1df19e755634d447127 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0645/1389] Bluetooth: Kconfig: Merge BT_HCI_VS_EXT into BT_HCI_VS The naming of these two options was problematic, since it's both of them are about vendor extensions, even though one has _EXT in the name and the other doesn't. Just merge one option into the other. This has a slight overhead on the controller side of enabling some more vendor features if BT_HCI_VS is enabled, but that should hopefully be acceptable. Signed-off-by: Johan Hedberg --- boards/shields/x_nucleo_idb05a1/Kconfig.defconfig | 2 +- boards/st/b_l4s5i_iot01a/Kconfig.defconfig | 2 +- boards/st/disco_l475_iot1/Kconfig.defconfig | 2 +- boards/st/sensortile_box/Kconfig.defconfig | 2 +- boards/st/stm32l562e_dk/Kconfig.defconfig | 2 +- samples/bluetooth/peripheral_hr/prj_minimal.conf | 2 +- samples/boards/nrf/mesh/onoff-app/prj.conf | 2 -- subsys/bluetooth/common/Kconfig | 15 +++------------ subsys/bluetooth/controller/Kconfig | 6 +++--- subsys/bluetooth/controller/Kconfig.df | 4 ++-- subsys/bluetooth/controller/hci/hci.c | 11 ++--------- subsys/bluetooth/host/Kconfig | 4 ++-- subsys/bluetooth/host/hci_core.c | 6 +++--- subsys/bluetooth/host/hci_core.h | 2 +- subsys/bluetooth/host/id.c | 12 ++++++------ tests/bluetooth/init/prj_ctlr_4_0.conf | 2 +- tests/bluetooth/init/prj_ctlr_4_0_dbg.conf | 2 +- tests/bluetooth/init/prj_ctlr_5_x_dbg.conf | 2 +- tests/bluetooth/init/prj_ctlr_dbg.conf | 2 +- tests/bluetooth/init/prj_ctlr_ticker.conf | 2 +- tests/bluetooth/init/prj_ctlr_tiny.conf | 2 +- 21 files changed, 34 insertions(+), 52 deletions(-) diff --git a/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig b/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig index 430b8a860f7df8..a5fe2515b50341 100644 --- a/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig +++ b/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig @@ -17,7 +17,7 @@ config BT_BLUENRG_ACI # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/b_l4s5i_iot01a/Kconfig.defconfig b/boards/st/b_l4s5i_iot01a/Kconfig.defconfig index 36b722dbf38199..0000fc670f3ce7 100644 --- a/boards/st/b_l4s5i_iot01a/Kconfig.defconfig +++ b/boards/st/b_l4s5i_iot01a/Kconfig.defconfig @@ -36,7 +36,7 @@ config BT_BLUENRG_ACI # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/disco_l475_iot1/Kconfig.defconfig b/boards/st/disco_l475_iot1/Kconfig.defconfig index 5679d2caff840d..b99f7c57511eb7 100644 --- a/boards/st/disco_l475_iot1/Kconfig.defconfig +++ b/boards/st/disco_l475_iot1/Kconfig.defconfig @@ -36,7 +36,7 @@ config BT_BLUENRG_ACI # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/sensortile_box/Kconfig.defconfig b/boards/st/sensortile_box/Kconfig.defconfig index 29aa7598ef81b0..8e3f0bb167041f 100644 --- a/boards/st/sensortile_box/Kconfig.defconfig +++ b/boards/st/sensortile_box/Kconfig.defconfig @@ -19,7 +19,7 @@ config BT_BLUENRG_ACI # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/stm32l562e_dk/Kconfig.defconfig b/boards/st/stm32l562e_dk/Kconfig.defconfig index 3f15027bb35d63..5dea5bc3a74180 100644 --- a/boards/st/stm32l562e_dk/Kconfig.defconfig +++ b/boards/st/stm32l562e_dk/Kconfig.defconfig @@ -21,7 +21,7 @@ config BT_BLUENRG_ACI config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/samples/bluetooth/peripheral_hr/prj_minimal.conf b/samples/bluetooth/peripheral_hr/prj_minimal.conf index a9feeb48cb00bc..bb759ccfdf872d 100644 --- a/samples/bluetooth/peripheral_hr/prj_minimal.conf +++ b/samples/bluetooth/peripheral_hr/prj_minimal.conf @@ -91,7 +91,7 @@ CONFIG_BT_GATT_CACHING=n CONFIG_BT_GATT_SERVICE_CHANGED=n CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n CONFIG_BT_SETTINGS_CCC_LAZY_LOADING=y -CONFIG_BT_HCI_VS_EXT=n +CONFIG_BT_HCI_VS=n # Disable Bluetooth controller features not needed CONFIG_BT_CTLR_PRIVACY=n diff --git a/samples/boards/nrf/mesh/onoff-app/prj.conf b/samples/boards/nrf/mesh/onoff-app/prj.conf index 0fdf19b8cfce0d..8c74fc50e39056 100644 --- a/samples/boards/nrf/mesh/onoff-app/prj.conf +++ b/samples/boards/nrf/mesh/onoff-app/prj.conf @@ -79,8 +79,6 @@ CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_ADV_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_SELF_TEST=y -#CONFIG_BT_HCI_VS_EXT=n - #CONFIG_STACK_USAGE=y CONFIG_BT_RX_STACK_SIZE=4096 diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index ec1228981f37a9..2bfc0bd055c4d4 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -190,32 +190,23 @@ config BT_HCI_VS Host and/or Controller. This enables Set Version Information, Supported Commands, Supported Features vendor commands. -config BT_HCI_VS_EXT - bool "Zephyr HCI Vendor-Specific Extensions" - depends on BT_HCI_VS - default y - help - Enable support for the Zephyr HCI Vendor-Specific Extensions in the - Host and/or Controller. This enables Write BD_ADDR, Read Build Info, - Read Static Addresses and Read Key Hierarchy Roots vendor commands. - config BT_HCI_VS_EVT bool "Zephyr HCI Vendor-Specific Events" - depends on BT_HCI_VS_EXT + depends on BT_HCI_VS help Enable support for the Zephyr HCI Vendor-Specific Events in the Host and/or Controller. config BT_HCI_VS_FATAL_ERROR bool "Allow vendor specific HCI event Zephyr Fatal Error" - depends on BT_HCI_VS_EXT + depends on BT_HCI_VS help Enable emiting HCI Vendor-Specific events for system and Controller errors that are unrecoverable. config BT_HCI_VS_EXT_DETECT bool "Use heuristics to guess HCI vendor extensions support in advance" - depends on BT_HCI_VS_EXT && !BT_CTLR + depends on BT_HCI_VS && !BT_CTLR default y if BOARD_QEMU_X86 || BOARD_QEMU_CORTEX_M3 || BOARD_NATIVE_POSIX help Use some heuristics to try to guess in advance whether the controller diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 6d031c446224ab..962ce3b146c2e2 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -137,7 +137,7 @@ config BT_CTLR_CRYPTO config BT_CTLR_HCI_VS_BUILD_INFO string "Zephyr HCI VS Build Info string" default "" - depends on BT_HCI_VS_EXT + depends on BT_HCI_VS help User-defined string that will be returned by the Zephyr VS Read Build Information command after the Zephyr version and build time. When @@ -428,7 +428,7 @@ config BT_CTLR_TX_PWR_ANTENNA config BT_CTLR_TX_PWR_DYNAMIC_CONTROL bool "Tx Power Dynamic Control" - depends on BT_HCI_VS_EXT + depends on BT_HCI_VS help Enable dynamic control of Tx power per role/connection. Provides HCI VS commands to set and get the current Tx @@ -1007,7 +1007,7 @@ config BT_CTLR_ASSERT_HANDLER config BT_CTLR_VS_SCAN_REQ_RX bool "Use scan request reporting" - depends on BT_HCI_VS_EXT && !BT_CTLR_ADV_EXT + depends on BT_HCI_VS && !BT_CTLR_ADV_EXT select BT_HCI_VS_EVT select BT_CTLR_SCAN_REQ_NOTIFY help diff --git a/subsys/bluetooth/controller/Kconfig.df b/subsys/bluetooth/controller/Kconfig.df index 981d1b8f1fc33e..0613b66edbf7e0 100644 --- a/subsys/bluetooth/controller/Kconfig.df +++ b/subsys/bluetooth/controller/Kconfig.df @@ -312,7 +312,7 @@ endchoice config BT_CTLR_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connectionless IQ reports" - depends on BT_CTLR_DF_SCAN_CTE_RX && BT_HCI_VS_EXT + depends on BT_CTLR_DF_SCAN_CTE_RX && BT_HCI_VS select BT_HCI_VS_EVT help Direction Finging connectionless IQ reports provide a set of IQ samples collected during @@ -323,7 +323,7 @@ config BT_CTLR_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES config BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connection IQ reports" - depends on BT_CTLR_DF_CONN_CTE_RX && BT_HCI_VS_EXT + depends on BT_CTLR_DF_CONN_CTE_RX && BT_HCI_VS select BT_HCI_VS_EVT help Direction Finging connection IQ reports provide a set of IQ samples collected during diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index d051150a26b648..54417bdffd9977 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -4790,12 +4790,12 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, /* If Zephyr VS HCI commands are not enabled provide this functionality directly */ -#if !defined(CONFIG_BT_HCI_VS_EXT) +#if !defined(CONFIG_BT_HCI_VS) uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) { return hci_vendor_read_static_addr(addrs, size); } -#endif /* !defined(CONFIG_BT_HCI_VS_EXT) */ +#endif /* !defined(CONFIG_BT_HCI_VS) */ #if defined(CONFIG_BT_HCI_VS) @@ -4827,7 +4827,6 @@ static void vs_read_supported_commands(struct net_buf *buf, /* Set Version Information, Supported Commands, Supported Features. */ rp->commands[0] |= BIT(0) | BIT(1) | BIT(2); -#if defined(CONFIG_BT_HCI_VS_EXT) /* Write BD_ADDR, Read Build Info */ rp->commands[0] |= BIT(5) | BIT(7); /* Read Static Addresses, Read Key Hierarchy Roots */ @@ -4846,7 +4845,6 @@ static void vs_read_supported_commands(struct net_buf *buf, /* Set USB Transport Mode */ rp->commands[2] |= BIT(0); #endif /* USB_DEVICE_BLUETOOTH_VS_H4 */ -#endif /* CONFIG_BT_HCI_VS_EXT */ } static void vs_read_supported_features(struct net_buf *buf, @@ -4869,7 +4867,6 @@ uint8_t __weak hci_vendor_read_static_addr(struct bt_hci_vs_static_addr addrs[], return 0; } -#if defined(CONFIG_BT_HCI_VS_EXT) static void vs_write_bd_addr(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_vs_write_bd_addr *cmd = (void *)buf->data; @@ -5323,8 +5320,6 @@ static void vs_le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct ne } #endif /* CONFIG_BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES */ -#endif /* CONFIG_BT_HCI_VS_EXT */ - #if defined(CONFIG_BT_HCI_MESH_EXT) static void mesh_get_opts(struct net_buf *buf, struct net_buf **evt) { @@ -5501,7 +5496,6 @@ int hci_vendor_cmd_handle_common(uint16_t ocf, struct net_buf *cmd, break; #endif /* CONFIG_USB_DEVICE_BLUETOOTH_VS_H4 */ -#if defined(CONFIG_BT_HCI_VS_EXT) case BT_OCF(BT_HCI_OP_VS_READ_BUILD_INFO): vs_read_build_info(cmd, evt); break; @@ -5539,7 +5533,6 @@ int hci_vendor_cmd_handle_common(uint16_t ocf, struct net_buf *cmd, vs_set_min_used_chans(cmd, evt); break; #endif /* CONFIG_BT_CTLR_MIN_USED_CHAN && CONFIG_BT_PERIPHERAL */ -#endif /* CONFIG_BT_HCI_VS_EXT */ #if defined(CONFIG_BT_HCI_MESH_EXT) case BT_OCF(BT_HCI_OP_VS_MESH): diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 91e17c11fcbcad..175b3725255d82 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -881,7 +881,7 @@ config BT_DF_CTE_TX_AOD config BT_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connectionless IQ reports" - depends on BT_DF_CONNECTIONLESS_CTE_RX && BT_HCI_VS_EXT + depends on BT_DF_CONNECTIONLESS_CTE_RX && BT_HCI_VS select BT_HCI_VS_EVT help Direction Finging connectionless IQ reports provide a set of IQ samples collected during @@ -892,7 +892,7 @@ config BT_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES config BT_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connection IQ reports" - depends on BT_DF_CONNECTION_CTE_RX && BT_HCI_VS_EXT + depends on BT_DF_CONNECTION_CTE_RX && BT_HCI_VS select BT_HCI_VS_EVT help Direction Finging connection IQ reports provide a set of IQ samples collected during diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index b0429fe3b6d649..9fb3903d0e4e22 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -3665,7 +3665,7 @@ static void bt_dev_show_info(void) bt_dev.lmp_version, bt_dev.lmp_subversion); } -#if defined(CONFIG_BT_HCI_VS_EXT) +#if defined(CONFIG_BT_HCI_VS) static const char *vs_hw_platform(uint16_t platform) { static const char * const plat_str[] = { @@ -3803,7 +3803,7 @@ static void hci_vs_init(void) net_buf_unref(rsp); } } -#endif /* CONFIG_BT_HCI_VS_EXT */ +#endif /* CONFIG_BT_HCI_VS */ static int hci_init(void) { @@ -3858,7 +3858,7 @@ static int hci_init(void) return err; } -#if defined(CONFIG_BT_HCI_VS_EXT) +#if defined(CONFIG_BT_HCI_VS) hci_vs_init(); #endif err = bt_id_init(); diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index eb6c58e5a34c5f..8c5dcb6d31f4c8 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -373,7 +373,7 @@ struct bt_dev { /* Supported commands */ uint8_t supported_commands[64]; -#if defined(CONFIG_BT_HCI_VS_EXT) +#if defined(CONFIG_BT_HCI_VS) /* Vendor HCI support */ uint8_t vs_features[BT_DEV_VS_FEAT_MAX]; uint8_t vs_commands[BT_DEV_VS_CMDS_MAX]; diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index 618dc6b758606b..a72bc010384933 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -1487,7 +1487,7 @@ static void bt_read_identity_root(uint8_t *ir) /* Invalid IR */ memset(ir, 0, 16); -#if defined(CONFIG_BT_HCI_VS_EXT) +#if defined(CONFIG_BT_HCI_VS) struct bt_hci_rp_vs_read_key_hierarchy_roots *rp; struct net_buf *rsp; int err; @@ -1514,7 +1514,7 @@ static void bt_read_identity_root(uint8_t *ir) memcpy(ir, rp->ir, 16); net_buf_unref(rsp); -#endif /* defined(CONFIG_BT_HCI_VS_EXT) */ +#endif /* defined(CONFIG_BT_HCI_VS) */ } #endif /* defined(CONFIG_BT_PRIVACY) */ @@ -1589,7 +1589,7 @@ int bt_setup_public_id_addr(void) return id_create(BT_ID_DEFAULT, &addr, irk); } -#if defined(CONFIG_BT_HCI_VS_EXT) +#if defined(CONFIG_BT_HCI_VS) uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) { struct bt_hci_rp_vs_read_static_addrs *rp; @@ -1638,11 +1638,11 @@ uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) return cnt; } -#endif /* CONFIG_BT_HCI_VS_EXT */ +#endif /* CONFIG_BT_HCI_VS */ int bt_setup_random_id_addr(void) { -#if defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) +#if defined(CONFIG_BT_HCI_VS) || defined(CONFIG_BT_CTLR) /* Only read the addresses if the user has not already configured one or * more identities (!bt_dev.id_count). */ @@ -1689,7 +1689,7 @@ int bt_setup_random_id_addr(void) return 0; } } -#endif /* defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) */ +#endif /* defined(CONFIG_BT_HCI_VS) || defined(CONFIG_BT_CTLR) */ if (IS_ENABLED(CONFIG_BT_PRIVACY) && IS_ENABLED(CONFIG_BT_SETTINGS)) { atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); diff --git a/tests/bluetooth/init/prj_ctlr_4_0.conf b/tests/bluetooth/init/prj_ctlr_4_0.conf index a92a542f6d7f05..ba2013915d1798 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0.conf @@ -25,7 +25,7 @@ CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n CONFIG_BT_CTLR_SCAN_REQ_RSSI=n CONFIG_BT_CTLR_PROFILE_ISR=n CONFIG_BT_CTLR_DEBUG_PINS=n -CONFIG_BT_HCI_VS_EXT=n +CONFIG_BT_HCI_VS=n CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y diff --git a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf index 53559510ac4dde..59314c494d7ea0 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf @@ -27,7 +27,7 @@ CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n CONFIG_BT_CTLR_SCAN_REQ_RSSI=n CONFIG_BT_CTLR_PROFILE_ISR=n CONFIG_BT_CTLR_DEBUG_PINS=n -CONFIG_BT_HCI_VS_EXT=y +CONFIG_BT_HCI_VS=y CONFIG_BT_CTLR_VS_SCAN_REQ_RX=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf index f37e9c6f309c2a..b65082eb70f6f4 100644 --- a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf @@ -44,7 +44,7 @@ CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX=n CONFIG_BT_CTLR_PROFILE_ISR=y CONFIG_BT_CTLR_DEBUG_PINS=y CONFIG_BT_CTLR_TEST=y -CONFIG_BT_HCI_VS_EXT=y +CONFIG_BT_HCI_VS=y CONFIG_BT_HCI_MESH_EXT=n CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/tests/bluetooth/init/prj_ctlr_dbg.conf b/tests/bluetooth/init/prj_ctlr_dbg.conf index f2bf1f7ffd4559..1b32cbf6dc99e0 100644 --- a/tests/bluetooth/init/prj_ctlr_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_dbg.conf @@ -34,7 +34,7 @@ CONFIG_BT_CTLR_SCAN_INDICATION=y CONFIG_BT_CTLR_PROFILE_ISR=y CONFIG_BT_CTLR_DEBUG_PINS=y CONFIG_BT_CTLR_TEST=y -CONFIG_BT_HCI_VS_EXT=y +CONFIG_BT_HCI_VS=y CONFIG_BT_HCI_MESH_EXT=n CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/tests/bluetooth/init/prj_ctlr_ticker.conf b/tests/bluetooth/init/prj_ctlr_ticker.conf index ba983f09a734e3..47c4f3f70629d9 100644 --- a/tests/bluetooth/init/prj_ctlr_ticker.conf +++ b/tests/bluetooth/init/prj_ctlr_ticker.conf @@ -35,7 +35,7 @@ CONFIG_BT_CTLR_TEST=y CONFIG_BT_TICKER_EXT=n CONFIG_BT_TICKER_SLOT_AGNOSTIC=y CONFIG_BT_TICKER_PREFER_START_BEFORE_STOP=y -CONFIG_BT_HCI_VS_EXT=y +CONFIG_BT_HCI_VS=y CONFIG_BT_HCI_MESH_EXT=n CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/tests/bluetooth/init/prj_ctlr_tiny.conf b/tests/bluetooth/init/prj_ctlr_tiny.conf index 19de37a5a84d75..a9dcf2327e05a7 100644 --- a/tests/bluetooth/init/prj_ctlr_tiny.conf +++ b/tests/bluetooth/init/prj_ctlr_tiny.conf @@ -29,7 +29,7 @@ CONFIG_BT_CTLR_SCAN_REQ_RSSI=n CONFIG_BT_CTLR_PROFILE_ISR=n CONFIG_BT_CTLR_PROFILE_ISR=n CONFIG_BT_CTLR_DEBUG_PINS=n -CONFIG_BT_HCI_VS_EXT=n +CONFIG_BT_HCI_VS=n CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y From 51cf4dcd5d6c5a2102276dc4a6cf853e7f17dc61 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0646/1389] Bluetooth: Kconfig: Get rid of BT_HCI_VS_EVT Enabling vendor-specific extensions also implies support for vendor events, so a separate Kconfig option for that is unnecessary. One small additional thing this requires is the use of the __maybe_unused annotation, since there's no-longer a single Kconfig option that the controller hci.c can use to know that the vendor event helper symbols are needed. Signed-off-by: Johan Hedberg --- subsys/bluetooth/common/Kconfig | 7 ------- subsys/bluetooth/controller/Kconfig | 1 - subsys/bluetooth/controller/Kconfig.df | 2 -- subsys/bluetooth/controller/hci/hci.c | 12 ++++++------ subsys/bluetooth/host/Kconfig | 2 -- subsys/bluetooth/host/hci_core.c | 2 +- 6 files changed, 7 insertions(+), 19 deletions(-) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index 2bfc0bd055c4d4..d7d0d579609634 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -190,13 +190,6 @@ config BT_HCI_VS Host and/or Controller. This enables Set Version Information, Supported Commands, Supported Features vendor commands. -config BT_HCI_VS_EVT - bool "Zephyr HCI Vendor-Specific Events" - depends on BT_HCI_VS - help - Enable support for the Zephyr HCI Vendor-Specific Events in the - Host and/or Controller. - config BT_HCI_VS_FATAL_ERROR bool "Allow vendor specific HCI event Zephyr Fatal Error" depends on BT_HCI_VS diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 962ce3b146c2e2..11dc46dcc838f4 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -1008,7 +1008,6 @@ config BT_CTLR_ASSERT_HANDLER config BT_CTLR_VS_SCAN_REQ_RX bool "Use scan request reporting" depends on BT_HCI_VS && !BT_CTLR_ADV_EXT - select BT_HCI_VS_EVT select BT_CTLR_SCAN_REQ_NOTIFY help Enables usage of VS Scan Request Reports Command and Scan Request Received Event diff --git a/subsys/bluetooth/controller/Kconfig.df b/subsys/bluetooth/controller/Kconfig.df index 0613b66edbf7e0..3f62ed8b4f1e8d 100644 --- a/subsys/bluetooth/controller/Kconfig.df +++ b/subsys/bluetooth/controller/Kconfig.df @@ -313,7 +313,6 @@ endchoice config BT_CTLR_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connectionless IQ reports" depends on BT_CTLR_DF_SCAN_CTE_RX && BT_HCI_VS - select BT_HCI_VS_EVT help Direction Finging connectionless IQ reports provide a set of IQ samples collected during sampling of CTE. Bluetooth 5.3 Core Specification defines IQ samples to be 8 bits signed @@ -324,7 +323,6 @@ config BT_CTLR_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES config BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connection IQ reports" depends on BT_CTLR_DF_CONN_CTE_RX && BT_HCI_VS - select BT_HCI_VS_EVT help Direction Finging connection IQ reports provide a set of IQ samples collected during sampling of CTE. Bluetooth 5.3 Core Specification defines IQ samples to be 8 bits signed diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 54417bdffd9977..5d1f051461cc12 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -211,9 +211,9 @@ static uint32_t cis_pending_count; static uint64_t event_mask = DEFAULT_EVENT_MASK; static uint64_t event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2; static uint64_t le_event_mask = DEFAULT_LE_EVENT_MASK; -#if defined(CONFIG_BT_HCI_VS_EVT) -static uint64_t vs_events_mask = DEFAULT_VS_EVT_MASK; -#endif /* CONFIG_BT_HCI_VS_EVT */ +#if defined(CONFIG_BT_HCI_VS) +__maybe_unused static uint64_t vs_events_mask = DEFAULT_VS_EVT_MASK; +#endif /* CONFIG_BT_HCI_VS */ static struct net_buf *cmd_complete_status(uint8_t status); @@ -339,8 +339,8 @@ static void *meta_evt(struct net_buf *buf, uint8_t subevt, uint8_t melen) return net_buf_add(buf, melen); } -#if defined(CONFIG_BT_HCI_VS_EVT) -static void *vs_event(struct net_buf *buf, uint8_t subevt, uint8_t evt_len) +#if defined(CONFIG_BT_HCI_VS) +__maybe_unused static void *vs_event(struct net_buf *buf, uint8_t subevt, uint8_t evt_len) { struct bt_hci_evt_vs *evt; @@ -350,7 +350,7 @@ static void *vs_event(struct net_buf *buf, uint8_t subevt, uint8_t evt_len) return net_buf_add(buf, evt_len); } -#endif /* CONFIG_BT_HCI_VS_EVT */ +#endif /* CONFIG_BT_HCI_VS */ #if defined(CONFIG_BT_HCI_MESH_EXT) static void *mesh_evt(struct net_buf *buf, uint8_t subevt, uint8_t melen) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 175b3725255d82..328a4905976af9 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -882,7 +882,6 @@ config BT_DF_CTE_TX_AOD config BT_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connectionless IQ reports" depends on BT_DF_CONNECTIONLESS_CTE_RX && BT_HCI_VS - select BT_HCI_VS_EVT help Direction Finging connectionless IQ reports provide a set of IQ samples collected during sampling of CTE. Bluetooth 5.3 Core Specification defines IQ samples to be 8 bits signed @@ -893,7 +892,6 @@ config BT_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES config BT_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES bool "Use 16 bits signed integer IQ samples in connection IQ reports" depends on BT_DF_CONNECTION_CTE_RX && BT_HCI_VS - select BT_HCI_VS_EVT help Direction Finging connection IQ reports provide a set of IQ samples collected during sampling of CTE. Bluetooth 5.3 Core Specification defines IQ samples to be 8 bits signed diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 9fb3903d0e4e22..f02acf526513f5 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -2526,7 +2526,7 @@ static void hci_vendor_event(struct net_buf *buf) } #endif /* CONFIG_BT_HCI_VS_EVT_USER */ - if (IS_ENABLED(CONFIG_BT_HCI_VS_EVT) && !handled) { + if (IS_ENABLED(CONFIG_BT_HCI_VS) && !handled) { struct bt_hci_evt_vs *evt; evt = net_buf_pull_mem(buf, sizeof(*evt)); From 0c93f01b1aebf32735f54a877094d7e3b40c50a3 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0647/1389] Bluetooth: Remove bt_read_static_addr() "hack" This function was used to shortcut HCI for combined host + controller builds. It doesn't provide much value and adds complexity to the HCI driver interface, so just remove it. This means vendor-specific HCI commands is now the only way for the host to access the same information. Signed-off-by: Johan Hedberg --- include/zephyr/drivers/bluetooth/hci_driver.h | 9 --- subsys/bluetooth/controller/hci/hci.c | 10 --- subsys/bluetooth/host/id.c | 69 +++++++++---------- .../src/test_suite_bt_settings_enabled.c | 4 +- 4 files changed, 36 insertions(+), 56 deletions(-) diff --git a/include/zephyr/drivers/bluetooth/hci_driver.h b/include/zephyr/drivers/bluetooth/hci_driver.h index 8611765c706995..08aacc853f36cd 100644 --- a/include/zephyr/drivers/bluetooth/hci_driver.h +++ b/include/zephyr/drivers/bluetooth/hci_driver.h @@ -52,15 +52,6 @@ enum { */ int bt_recv(struct net_buf *buf); -/** @brief Read static addresses from the controller. - * - * @param addrs Random static address and Identity Root (IR) array. - * @param size Size of array. - * - * @return Number of addresses read. - */ -uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size); - /** Possible values for the 'bus' member of the bt_hci_driver struct */ enum bt_hci_driver_bus { BT_HCI_DRIVER_BUS_VIRTUAL = 0, diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 5d1f051461cc12..247a50959da9da 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -4788,16 +4788,6 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, return 0; } -/* If Zephyr VS HCI commands are not enabled provide this functionality directly - */ -#if !defined(CONFIG_BT_HCI_VS) -uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) -{ - return hci_vendor_read_static_addr(addrs, size); -} -#endif /* !defined(CONFIG_BT_HCI_VS) */ - - #if defined(CONFIG_BT_HCI_VS) static void vs_read_version_info(struct net_buf *buf, struct net_buf **evt) { diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index a72bc010384933..d6f23f2db64152 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -1589,9 +1589,9 @@ int bt_setup_public_id_addr(void) return id_create(BT_ID_DEFAULT, &addr, irk); } -#if defined(CONFIG_BT_HCI_VS) -uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) +static uint8_t vs_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) { +#if defined(CONFIG_BT_HCI_VS) struct bt_hci_rp_vs_read_static_addrs *rp; struct net_buf *rsp; int err, i; @@ -1637,59 +1637,58 @@ uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size) } return cnt; +#else + return 0; +#endif } -#endif /* CONFIG_BT_HCI_VS */ int bt_setup_random_id_addr(void) { -#if defined(CONFIG_BT_HCI_VS) || defined(CONFIG_BT_CTLR) /* Only read the addresses if the user has not already configured one or * more identities (!bt_dev.id_count). */ - if (!bt_dev.id_count) { + if (IS_ENABLED(CONFIG_BT_HCI_VS) && !bt_dev.id_count) { struct bt_hci_vs_static_addr addrs[CONFIG_BT_ID_MAX]; - bt_dev.id_count = bt_read_static_addr(addrs, CONFIG_BT_ID_MAX); - - if (bt_dev.id_count) { - for (uint8_t i = 0; i < bt_dev.id_count; i++) { - int err; - bt_addr_le_t addr; - uint8_t *irk = NULL; -#if defined(CONFIG_BT_PRIVACY) - uint8_t ir_irk[16]; + bt_dev.id_count = vs_read_static_addr(addrs, CONFIG_BT_ID_MAX); - if (!IS_ENABLED(CONFIG_BT_PRIVACY_RANDOMIZE_IR)) { - if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) { - irk = ir_irk; - } + for (uint8_t i = 0; i < bt_dev.id_count; i++) { + int err; + bt_addr_le_t addr; + uint8_t *irk = NULL; + uint8_t ir_irk[16]; + + if (IS_ENABLED(CONFIG_BT_PRIVACY) && + !IS_ENABLED(CONFIG_BT_PRIVACY_RANDOMIZE_IR)) { + if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) { + irk = ir_irk; } -#endif /* CONFIG_BT_PRIVACY */ + } - /* If true, `id_create` will randomize the IRK. */ - if (!irk && IS_ENABLED(CONFIG_BT_PRIVACY)) { - /* `id_create` will not store the id when called before - * BT_DEV_READY. But since part of the id will be - * randomized, it needs to be stored. - */ - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); - } + /* If true, `id_create` will randomize the IRK. */ + if (!irk && IS_ENABLED(CONFIG_BT_PRIVACY)) { + /* `id_create` will not store the id when called before + * BT_DEV_READY. But since part of the id will be + * randomized, it needs to be stored. + */ + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); } + } - bt_addr_copy(&addr.a, &addrs[i].bdaddr); - addr.type = BT_ADDR_LE_RANDOM; + bt_addr_copy(&addr.a, &addrs[i].bdaddr); + addr.type = BT_ADDR_LE_RANDOM; - err = id_create(i, &addr, irk); - if (err) { - return err; - } + err = id_create(i, &addr, irk); + if (err) { + return err; } + } + if (bt_dev.id_count > 0) { return 0; } } -#endif /* defined(CONFIG_BT_HCI_VS) || defined(CONFIG_BT_CTLR) */ if (IS_ENABLED(CONFIG_BT_PRIVACY) && IS_ENABLED(CONFIG_BT_SETTINGS)) { atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); diff --git a/tests/bluetooth/host/id/bt_setup_random_id_addr/src/test_suite_bt_settings_enabled.c b/tests/bluetooth/host/id/bt_setup_random_id_addr/src/test_suite_bt_settings_enabled.c index e2b63adfefedf8..bc843b5d9cabdc 100644 --- a/tests/bluetooth/host/id/bt_setup_random_id_addr/src/test_suite_bt_settings_enabled.c +++ b/tests/bluetooth/host/id/bt_setup_random_id_addr/src/test_suite_bt_settings_enabled.c @@ -50,7 +50,7 @@ ZTEST_SUITE(bt_setup_random_id_addr_bt_settings_enabled, NULL, NULL, tc_setup, N * Test reading controller static random address fails and no attempt to store settings. * * Constraints: - * - bt_read_static_addr() returns zero + * - vs_read_static_addr() returns zero * * Expected behaviour: * - ID count is set to 0 and bt_setup_random_id_addr() returns a negative error code @@ -60,7 +60,7 @@ ZTEST(bt_setup_random_id_addr_bt_settings_enabled, test_bt_read_static_addr_retu { int err; - /* This will force bt_read_static_addr() to fail */ + /* This will force vs_read_static_addr() to fail */ bt_hci_cmd_send_sync_fake.return_val = 1; err = bt_setup_random_id_addr(); From eed8059a71211e23c05f6c813524c7b61737b4c9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0648/1389] doc: migration-guide-3.7: Mention Bluetooth HCI related changes Mention the changes to Bluetooth HCI Kconfig options and one semi-private API (bt_read_static_addr). Signed-off-by: Johan Hedberg --- doc/releases/migration-guide-3.7.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 19de22a992e8ff..762e581dece586 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -156,6 +156,15 @@ Analog-to-Digital Converter (ADC) Bluetooth HCI ============= + * The ``BT_HCI_VS_EXT`` Kconfig option was deleted and the feature is now included in the + :kconfig:option:`BT_HCI_VS` Kconfig option. + * The ``BT_HCI_VS_EVT`` Kconfig option was removed, since vendor event support is implicit if + the :kconfig:option:`BT_HCI_VS` option is enabled. + * The bt_read_static_addr() API was removed. This wasn't really a completely public API, but + since it was exposed by the public hci_driver.h header file the removal is mentioned here. + Enable the :kconfig:option:`BT_HCI_VS` Kconfig option instead, and use vendor specific HCI + commands API to get the Controller's Bluetooth static address when available. + Charger ======= From c83f02532352afed9b7056f063d8da00c62b9a3a Mon Sep 17 00:00:00 2001 From: Ayush Kothari Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0649/1389] Driver: Add pin inversion to Esp32 Uart Additional properties are added to esp32 uart to allow for signal inversion. Signed-off-by: Ayush Kothari --- drivers/serial/uart_esp32.c | 11 +++++++++++ dts/bindings/serial/espressif,esp32-uart.yaml | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index cb07de20adcb1d..48f213c7394c97 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -67,6 +67,8 @@ struct uart_esp32_config { const clock_control_subsys_t clock_subsys; int irq_source; int irq_priority; + bool tx_invert; + bool rx_invert; #if CONFIG_UART_ASYNC_API const struct device *dma_dev; uint8_t tx_dma_channel; @@ -328,6 +330,13 @@ static int uart_esp32_configure(const struct device *dev, const struct uart_conf uart_hal_set_rx_timeout(&data->hal, 0x16); + if (config->tx_invert) { + uart_hal_inverse_signal(&data->hal, UART_SIGNAL_TXD_INV); + } + + if (config->rx_invert) { + uart_hal_inverse_signal(&data->hal, UART_SIGNAL_RXD_INV); + } return 0; } @@ -1004,6 +1013,8 @@ static const DRAM_ATTR struct uart_driver_api uart_esp32_api = { .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \ .irq_source = DT_INST_IRQN(idx), \ .irq_priority = UART_IRQ_PRIORITY, \ + .tx_invert = DT_INST_PROP_OR(idx, tx_invert, false), \ + .rx_invert = DT_INST_PROP_OR(idx, rx_invert, false), \ ESP_UART_DMA_INIT(idx)}; \ \ static struct uart_esp32_data uart_esp32_data_##idx = { \ diff --git a/dts/bindings/serial/espressif,esp32-uart.yaml b/dts/bindings/serial/espressif,esp32-uart.yaml index 313d9039a5b542..ab3b88df83f583 100644 --- a/dts/bindings/serial/espressif,esp32-uart.yaml +++ b/dts/bindings/serial/espressif,esp32-uart.yaml @@ -21,3 +21,15 @@ properties: Overrides hw-flow-control if both are set. Using this mode, the pin assigned to DTR is asserted during transmission. + + tx-invert: + type: boolean + description: | + Invert the binary logic of tx pin. When enabled, physical logic levels are inverted and + we use 1=Low, 0=High instead of 1=High, 0=Low. + + rx-invert: + type: boolean + description: | + Invert the binary logic of rx pin. When enabled, physical logic levels are inverted and + we use 1=Low, 0=High instead of 1=High, 0=Low. From bfb4b1f285d4426339ef9b22dfe186c7f57b9428 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0650/1389] soc: nxp: rw: use correct mask for FLEXSPI clock setup divider Mask for FLEXSPI clock divider was being used when setting the FLEXSPI clock selector value. Correct this to use the mask for the selector instead of the divider. Signed-off-by: Daniel DeGrasse --- soc/nxp/rw/flexspi_clock_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/nxp/rw/flexspi_clock_setup.c b/soc/nxp/rw/flexspi_clock_setup.c index 3876e1adbf4279..3eb5640d82de2d 100644 --- a/soc/nxp/rw/flexspi_clock_setup.c +++ b/soc/nxp/rw/flexspi_clock_setup.c @@ -43,7 +43,7 @@ int __ramfunc flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate) FLEXSPI_Enable(FLEXSPI, false); set_flexspi_clock(FLEXSPI, (CLKCTL0->FLEXSPIFCLKSEL & - CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK), (divider + 1)); + CLKCTL0_FLEXSPIFCLKSEL_SEL_MASK), (divider + 1)); FLEXSPI_Enable(FLEXSPI, true); From e05e25f6fde7fb0a0c8e3edafcf49300057b29d4 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0651/1389] drivers: memc: memc_mcux_flexspi: update documentation for flash_config Update documentation for flash_config memc function, to correctly reflect usage of the "lut_count" parameter Signed-off-by: Daniel DeGrasse --- drivers/memc/memc_mcux_flexspi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memc/memc_mcux_flexspi.h b/drivers/memc/memc_mcux_flexspi.h index 707d9f088cc370..6863649bc94a53 100644 --- a/drivers/memc/memc_mcux_flexspi.h +++ b/drivers/memc/memc_mcux_flexspi.h @@ -57,7 +57,7 @@ int memc_flexspi_update_clock(const struct device *dev, * @param dev: FlexSPI device * @param device_config: External device configuration. * @param lut_array: Lookup table of FlexSPI flash commands for device - * @param lut_count: number of command entries (16 bytes each) in LUT + * @param lut_count: number of LUT entries (4 bytes each) in lut array * @param port: FlexSPI port to use for this external device * @return 0 on success, negative value on failure */ From a4090eaf77a946934b057367094a77844e5dc554 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0652/1389] drivers: memc: memc_mcux_flexspi: correctly handle multi-device usage When multiple devices are used, the FLEXSPI will place their address spaces sequentially (based on the chip select port used). Additionally, each device must use different sections of the FLEXSPI LUT table. Fix the following calculation issues with multi-device usage: - correct calculation of LUT sequence indices for AHB commands - correctly add address and sequence offset when submitting FLEXSPI IP transfer Signed-off-by: Daniel DeGrasse --- drivers/memc/memc_mcux_flexspi.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index 951d3f99a1e940..99c524a29b21c4 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -188,9 +188,12 @@ int memc_flexspi_set_device_config(const struct device *dev, /* Update lut offset with new value */ data->port_luts[port].lut_offset = lut_used; } - data->port_luts[port].lut_used = lut_count; - tmp_config.ARDSeqIndex += data->port_luts[port].lut_offset; - tmp_config.AWRSeqIndex += data->port_luts[port].lut_offset; + /* LUTs should only be installed on sequence boundaries, every + * 4 entries. Round LUT usage up to nearest sequence + */ + data->port_luts[port].lut_used = ROUND_UP(lut_count, 4); + tmp_config.ARDSeqIndex += data->port_luts[port].lut_offset / MEMC_FLEXSPI_CMD_PER_SEQ; + tmp_config.AWRSeqIndex += data->port_luts[port].lut_offset / MEMC_FLEXSPI_CMD_PER_SEQ; /* Lock IRQs before reconfiguring FlexSPI, to prevent XIP */ key = irq_lock(); @@ -215,12 +218,29 @@ int memc_flexspi_reset(const struct device *dev) int memc_flexspi_transfer(const struct device *dev, flexspi_transfer_t *transfer) { + flexspi_transfer_t tmp; struct memc_flexspi_data *data = dev->data; status_t status; + uint32_t seq_off, addr_offset = 0U; + int i; - /* Adjust transfer LUT index based on port */ - transfer->seqIndex += data->port_luts[transfer->port].lut_offset; - status = FLEXSPI_TransferBlocking(data->base, transfer); + /* Calculate sequence offset and address offset based on port */ + seq_off = data->port_luts[transfer->port].lut_offset / + MEMC_FLEXSPI_CMD_PER_SEQ; + for (i = 0; i < transfer->port; i++) { + addr_offset += data->size[i]; + } + + if ((seq_off != 0) || (addr_offset != 0)) { + /* Adjust device address and sequence index for transfer */ + memcpy(&tmp, transfer, sizeof(tmp)); + tmp.seqIndex += seq_off; + tmp.deviceAddress += addr_offset; + status = FLEXSPI_TransferBlocking(data->base, &tmp); + } else { + /* Transfer does not need adjustment */ + status = FLEXSPI_TransferBlocking(data->base, transfer); + } if (status != kStatus_Success) { LOG_ERR("Transfer error: %d", status); From e39d595bcb01fe567a4967f3e511b90cbca7778f Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0653/1389] drivers: memc: use custom initialization priority for FLEXSPI Use custom initialization priority for FLEXSPI MEMC driver. This may be needed when the MEMC driver must initialize before a flash driver, and before another MEMC driver (for an attached device, like PSRAM) Signed-off-by: Daniel DeGrasse --- drivers/memc/Kconfig.mcux | 10 ++++++++++ drivers/memc/memc_mcux_flexspi.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/memc/Kconfig.mcux b/drivers/memc/Kconfig.mcux index 6d2f30933e96cc..b0bfa04ac486f4 100644 --- a/drivers/memc/Kconfig.mcux +++ b/drivers/memc/Kconfig.mcux @@ -30,6 +30,16 @@ config MEMC_MCUX_FLEXSPI_IS66WVQ8M4 depends on DT_HAS_NXP_IMX_FLEXSPI_IS66WVQ8M4_ENABLED select MEMC_MCUX_FLEXSPI +config MEMC_MCUX_FLEXSPI_INIT_PRIORITY + int "MCUX FLEXSPI MEMC driver initialization priority" + default MEMC_INIT_PRIORITY + help + Initialization priority for FlexSPI MEMC driver. In cases where the + flash driver must initialize before the MEMC RAM driver, + initialization priorities can be set such that + MEMC_MCUX_FLEXSPI_INIT_PRIORITY < FLASH_INIT_PRIORITY < + MEMC_INIT_PRIORITY + config MEMC_MCUX_FLEXSPI bool select PINCTRL diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index 99c524a29b21c4..39faadcd534af4 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -424,7 +424,7 @@ static int memc_flexspi_pm_action(const struct device *dev, enum pm_device_actio &memc_flexspi_data_##n, \ NULL, \ POST_KERNEL, \ - CONFIG_MEMC_INIT_PRIORITY, \ + CONFIG_MEMC_MCUX_FLEXSPI_INIT_PRIORITY, \ NULL); DT_INST_FOREACH_STATUS_OKAY(MEMC_FLEXSPI) From 12c8bd25b4a8d0e47887509a9c866e3424f4e2a4 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0654/1389] drivers: memc: memc_mcux_flexspi: support initializing FLEXSPI when XIP Add support for initializing the FLEXSPI when using a flash attached to the FLEXSPI for XIP. This option is guarded behind a Kconfig, as enabling it is dangerous and requires special care be taken by the user to ensure that the configuration of pins and FLEXSPI settings will not break support for reading the attached flash, as this will break XIP support. Signed-off-by: Daniel DeGrasse --- drivers/memc/Kconfig.mcux | 10 ++++++++++ drivers/memc/memc_mcux_flexspi.c | 31 +++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/memc/Kconfig.mcux b/drivers/memc/Kconfig.mcux index b0bfa04ac486f4..dd6c2da48f4431 100644 --- a/drivers/memc/Kconfig.mcux +++ b/drivers/memc/Kconfig.mcux @@ -40,6 +40,16 @@ config MEMC_MCUX_FLEXSPI_INIT_PRIORITY MEMC_MCUX_FLEXSPI_INIT_PRIORITY < FLASH_INIT_PRIORITY < MEMC_INIT_PRIORITY +config MEMC_MCUX_FLEXSPI_INIT_XIP + bool "Initialize FLEXSPI when using device for XIP" + help + Initialize the FLEXSPI device even when using it for XIP. If this + Kconfig is enabled, the user must ensure that the pin control + state used does not reconfigure the pins used to interface with + the flash device used for XIP, and that the configuration settings + used for the FLEXSPI are compatible with those needed for XIP from + the flash device. + config MEMC_MCUX_FLEXSPI bool select PINCTRL diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index 39faadcd534af4..c3ad20aab4b2d1 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -280,19 +280,21 @@ static int memc_flexspi_init(const struct device *dev) { struct memc_flexspi_data *data = dev->data; flexspi_config_t flexspi_config; + uint32_t flash_sizes[kFLEXSPI_PortCount]; + int ret; + uint8_t i; /* we should not configure the device we are running on */ if (memc_flexspi_is_running_xip(dev)) { - LOG_DBG("XIP active on %s, skipping init", dev->name); - return 0; + if (!IS_ENABLED(CONFIG_MEMC_MCUX_FLEXSPI_INIT_XIP)) { + LOG_DBG("XIP active on %s, skipping init", dev->name); + return 0; + } } - /* * SOCs such as the RT1064 and RT1024 have internal flash, and no pinmux * settings, continue if no pinctrl state found. */ - int ret; - ret = pinctrl_apply_state(data->pincfg, PINCTRL_STATE_DEFAULT); if (ret < 0 && ret != -ENOENT) { return ret; @@ -328,7 +330,7 @@ FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB /* Configure AHB RX buffers, if any configuration settings are present */ __ASSERT(data->buf_cfg_cnt < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT, "Maximum RX buffer configuration count exceeded"); - for (uint8_t i = 0; i < data->buf_cfg_cnt; i++) { + for (i = 0; i < data->buf_cfg_cnt; i++) { /* Should AHB prefetch up to buffer size? */ flexspi_config.ahbConfig.buffer[i].enablePrefetch = data->buf_cfg[i].prefetch; /* AHB access priority (used for suspending control of AHB prefetching )*/ @@ -339,8 +341,25 @@ FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB flexspi_config.ahbConfig.buffer[i].bufferSize = data->buf_cfg[i].buf_size; } + if (memc_flexspi_is_running_xip(dev)) { + /* Save flash sizes- FlexSPI init will reset them */ + for (i = 0; i < kFLEXSPI_PortCount; i++) { + flash_sizes[i] = data->base->FLSHCR0[i]; + } + } + FLEXSPI_Init(data->base, &flexspi_config); + if (memc_flexspi_is_running_xip(dev)) { + /* Restore flash sizes */ + for (i = 0; i < kFLEXSPI_PortCount; i++) { + data->base->FLSHCR0[i] = flash_sizes[i]; + } + + /* Reenable FLEXSPI module */ + data->base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + } + return 0; } From 19fd8d6e8932106777fa290773c0d59d0f96fb86 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:00 +0200 Subject: [PATCH 0655/1389] drivers: memc: memc_mcux_flexspi_is66wvq8m4: do not reset FLEXSPI Do not reset the FLEXSPI during init, as this will crash the chip if we are running the MEMC driver in XIP mode. Signed-off-by: Daniel DeGrasse --- drivers/memc/memc_mcux_flexspi_is66wvq8m4.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c b/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c index e3ba54f2a5d68d..7ce698b3dd6506 100644 --- a/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c +++ b/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c @@ -169,8 +169,6 @@ static int memc_flexspi_is66wvq8m4_init(const struct device *dev) return -EINVAL; } - memc_flexspi_reset(data->controller); - if (memc_flexspi_is66wvq8m4_get_vendor_id(dev, &vendor_id)) { LOG_ERR("Could not read vendor id"); return -EIO; From 4e503a28495728300e9e4e450bd1c4792bf5eafb Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0656/1389] drivers: flash: flash_mcux_flexspi_nor: reduce LUT usage FLEXSPI nor driver uses several LUTs for "scratch" commands during the SFDP probe phase that are not needed once the flash is configured. Set a second "end" marker we can use to configure the FLEXSPI MEMC driver, so that we can indicate the true number of LUTs needed by this driver when init is completed. Signed-off-by: Daniel DeGrasse --- drivers/flash/flash_mcux_flexspi_nor.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/flash/flash_mcux_flexspi_nor.c b/drivers/flash/flash_mcux_flexspi_nor.c index bfcef6daebd744..d072f25f9246c4 100644 --- a/drivers/flash/flash_mcux_flexspi_nor.c +++ b/drivers/flash/flash_mcux_flexspi_nor.c @@ -52,8 +52,10 @@ enum { READ_STATUS_REG, ERASE_CHIP, READ_JESD216, + /* Entries after this should be for scratch commands */ + FLEXSPI_INSTR_PROG_END, /* Used for temporary commands during initialization */ - SCRATCH_CMD, + SCRATCH_CMD = FLEXSPI_INSTR_PROG_END, SCRATCH_CMD2, /* Must be last entry */ FLEXSPI_INSTR_END, @@ -1014,7 +1016,7 @@ static int flash_flexspi_nor_probe(struct flash_flexspi_nor_data *data) */ ret = memc_flexspi_set_device_config(&data->controller, &data->config, (uint32_t *)flexspi_lut, - FLEXSPI_INSTR_END * MEMC_FLEXSPI_CMD_PER_SEQ, + FLEXSPI_INSTR_PROG_END * MEMC_FLEXSPI_CMD_PER_SEQ, data->port); if (ret < 0) { return ret; From c58b78bdd10ccbec7d040a05216b359133ed2ad4 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0657/1389] samples: drivers: memc: support PSRAM on RW612 while using XIP mode RW612 has one FLEXSPI controller, which is capable of supporting multiple external devices on one board. However, care must be taken when configuring the FLEXSPI to use multiple devices, as if the FLEXSPI is configured incorrectly in XIP mode it will fail to read from the external flash, and the chip will crash. Make the following changes to the RW configuration for the MEMC sample, in order to support executing from flash while accessing PSRAM: - initialize the FLEXSPI MEMC driver first, before the flash or PSRAM drivers are initialized - force the FLEXSPI MEMC driver to reconfigure the FLEXSPI at boot, so we can configure the DQS sampling mode for the PSRAM on port B - only configure the PSRAM pins during FLEXSPI init, so XIP is not disrupted - configure the flash device at boot. This is required so that the MEMC driver will not replace the LUTs programmed in the FLEXSPI by the bootrom, as it would otherwise not be aware of their existence. Signed-off-by: Daniel DeGrasse --- samples/drivers/memc/boards/rd_rw612_bga.conf | 21 +++++++++++-- .../drivers/memc/boards/rd_rw612_bga.overlay | 31 ++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/samples/drivers/memc/boards/rd_rw612_bga.conf b/samples/drivers/memc/boards/rd_rw612_bga.conf index 60bfc1c6262497..f76b8554671c64 100644 --- a/samples/drivers/memc/boards/rd_rw612_bga.conf +++ b/samples/drivers/memc/boards/rd_rw612_bga.conf @@ -1,5 +1,22 @@ # Copyright 2023 NXP # SPDX-License-Identifier: Apache-2.0 -# RW is configured to execute from code ram, so use rom loader to load image -CONFIG_NXP_RW_ROM_RAMLOADER=y +# In order to safely access the PSRAM on port B of the RW FlexSPI peripheral, +# the QSPI flash on port A must be configured by the application. Otherwise, +# the PSRAM configuration will overwrite the LUT entries for the QSPI flash, +# and the application will no longer be able to XIP from the flash. +# To make sure the QSPI flash is configured, enable flash drivers. +CONFIG_FLASH=y + +# Initialization priorities are critical here. The FlexSPI MEMC driver must +# initialize first. Then, the QSPI flash driver must initialize to program +# the LUT table for port A. Finally, the PSRAM driver can initialize and +# program the LUT table for port B +CONFIG_MEMC_MCUX_FLEXSPI_INIT_PRIORITY=0 +CONFIG_FLASH_INIT_PRIORITY=50 +CONFIG_MEMC_INIT_PRIORITY=60 + +# This board has the PSRAM attached to the same FLEXSPI device as the flash +# chip used for XIP, so we must explicitly enable the FLEXSPI MEMC driver +# to reconfigure the flash device it is executing from +CONFIG_MEMC_MCUX_FLEXSPI_INIT_XIP=y diff --git a/samples/drivers/memc/boards/rd_rw612_bga.overlay b/samples/drivers/memc/boards/rd_rw612_bga.overlay index d02a07662da1ab..e32be713e3b88b 100644 --- a/samples/drivers/memc/boards/rd_rw612_bga.overlay +++ b/samples/drivers/memc/boards/rd_rw612_bga.overlay @@ -5,10 +5,6 @@ */ / { - chosen { - zephyr,flash = &sram_code; - }; - aliases { sram-ext = &is66wvq8m4; }; @@ -17,3 +13,30 @@ &is66wvq8m4 { status = "okay"; }; + +&pinctrl { + pinmux_flexspi_safe: pinmux-flexspi-safe { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + + group1 { + pinmux = ; + slew-rate = "normal"; + bias-pull-down; + }; + }; +}; + +/* Override pin control state to use one that only changes the PSRAM pin + * configuration + */ +&flexspi { + pinctrl-0 = <&pinmux_flexspi_safe>; +}; From 8995436bd11f62f7dc5607b231bed14efb7c7176 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0658/1389] drivers: display: mcux_elcdif: add additional documentation around PXP Add additional documentation and warnings around PXP usage. PXP rotation is only intended to be used when framebuffers passed to the eLCDIF display driver are equal in size to the screen. Moreover, PXP rotation is flipped versus LVGL rotation. So a LVGL rotation of 90 degrees requires the PXP to be set to rotate 270 degrees to function as expected. Signed-off-by: Daniel DeGrasse --- drivers/display/Kconfig.mcux_elcdif | 17 ++++++++++++----- drivers/display/display_mcux_elcdif.c | 3 +++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/display/Kconfig.mcux_elcdif b/drivers/display/Kconfig.mcux_elcdif index 43f90374380a70..48c4857a8eb559 100644 --- a/drivers/display/Kconfig.mcux_elcdif +++ b/drivers/display/Kconfig.mcux_elcdif @@ -60,8 +60,13 @@ choice MCUX_ELCDIF_PXP_ROTATE_DIRECTION prompt "Rotation angle of PXP" help Set rotation angle of PXP. The ELCDIF cannot detect the correct - rotation angle based on the call to display_write, so the user - should configure it here. + rotation angle based on the call to display_write, so the user should + configure it here. In order for PXP rotation to work, calls to + display_write MUST supply a framebuffer equal in size to screen width + and height (without rotation applied). Note that the width and + height settings of the screen in devicetree should not be modified + from their values in the default screen orientation when using this + functionality. config MCUX_ELCDIF_PXP_ROTATE_0 bool "Rotate display by 0 degrees" @@ -72,17 +77,19 @@ config MCUX_ELCDIF_PXP_ROTATE_0 config MCUX_ELCDIF_PXP_ROTATE_90 bool "Rotate display by 90 degrees" help - Rotate display clockwise by 90 degrees + Rotate display counter-clockwise by 90 degrees. + For LVGL, this corresponds to a rotation of 270 degrees config MCUX_ELCDIF_PXP_ROTATE_180 bool "Rotate display by 180 degrees" help - Rotate display clockwise by 180 degrees + Rotate display counter-clockwise by 180 degrees config MCUX_ELCDIF_PXP_ROTATE_270 bool "Rotate display by 270 degrees" help - Rotate display clockwise by 270 degrees + Rotate display counter-clockwise by 270 degrees + For LVGL, this corresponds to a rotation of 90 degrees endchoice diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index e4b45f89d40dd9..4252a98e859c19 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -190,6 +190,9 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u return ret; } k_sem_take(&dev_data->pxp_done, K_FOREVER); + } else { + LOG_WRN("PXP rotation will not work correctly unless a full sized " + "framebuffer is provided"); } #endif /* CONFIG_MCUX_ELCDIF_PXP */ From 6bf1563eaad951ff13dc91abc51012c0027183bb Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0659/1389] boards: nxp: mimxrt1050: enable PXP and apply optimized LVGL settings Enable PXP on RT1050 EVK, and apply LVGL settings optimized for PXP support. These settings will enable PXP rotation to function as expected when using LVGL with the RT1050. Signed-off-by: Daniel DeGrasse --- boards/nxp/mimxrt1050_evk/Kconfig.defconfig | 23 +++++++++++++++++++- boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts | 4 ++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/boards/nxp/mimxrt1050_evk/Kconfig.defconfig b/boards/nxp/mimxrt1050_evk/Kconfig.defconfig index bfb4a84e341b0f..1db4e04d7770b9 100644 --- a/boards/nxp/mimxrt1050_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1050_evk/Kconfig.defconfig @@ -37,12 +37,33 @@ endif # NETWORKING if LVGL +# LVGL should allocate buffers equal to size of display config LV_Z_VDB_SIZE - default 16 + default 100 + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +# Force full refresh. This prevents memory copy associated with partial +# display refreshes, which is not necessary for the eLCDIF driver +config LV_Z_FULL_REFRESH + default y config LV_DPI_DEF default 128 +config LV_Z_BITS_PER_PIXEL + default 16 + +# Force display buffers to be aligned to cache line size (32 bytes) +config LV_Z_VDB_ALIGN + default 32 + +# Use offloaded render thread +config LV_Z_FLUSH_THREAD + default y + choice LV_COLOR_DEPTH default LV_COLOR_DEPTH_16 endchoice diff --git a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts index 9c441f051d10df..4bd6b5bb441161 100644 --- a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts +++ b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts @@ -249,6 +249,10 @@ zephyr_udc0: &usb1 { status = "okay"; }; +&pxp { + status = "okay"; +}; + /* GPT and Systick are enabled. If power management is enabled, the GPT * timer will be used instead of systick, as allows the core clock to * be gated. From 83c5be6681479ee88b390aa9df73f01e5e51408d Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0660/1389] drivers: display: smartbond: Add support for PM This commit should add all the functionality needed for the DISPLAY driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios --- .../da1469x_dk_pro-pinctrl.dtsi | 15 ++ .../dts/da1469x_dk_pro_lcdc.overlay | 11 +- drivers/display/display_renesas_lcdc.c | 175 +++++++++++++----- 3 files changed, 152 insertions(+), 49 deletions(-) diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi index 39daff3ff162da..60d7fb98c56b88 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi @@ -47,6 +47,21 @@ }; }; + /omit-if-no-ref/ display_controller_sleep: display_controller_sleep { + group1 { + pinmux = , + , + , + , + , + , + , + , + , + ; + }; + }; + spi_controller: spi_controller { group1 { pinmux = , diff --git a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay index c147201adc483b..197882b5536f63 100644 --- a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay +++ b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay @@ -31,6 +31,14 @@ bias-pull-up; }; }; + + i2c2_sleep: i2c2_sleep { + group1 { + pinmux = , + ; + bias-pull-down; + }; + }; }; &i2c2 { @@ -47,7 +55,8 @@ &lcdc { status = "okay"; pinctrl-0 = <&display_controller_default>; - pinctrl-names = "default"; + pinctrl-1 = <&display_controller_sleep>; + pinctrl-names = "default", "sleep"; width = <480>; height = <272>; disp-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; diff --git a/drivers/display/display_renesas_lcdc.c b/drivers/display/display_renesas_lcdc.c index c09b48ac003a3f..ab12cc23a0083a 100644 --- a/drivers/display/display_renesas_lcdc.c +++ b/drivers/display/display_renesas_lcdc.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include LOG_MODULE_REGISTER(smartbond_display, CONFIG_DISPLAY_LOG_LEVEL); @@ -72,6 +74,10 @@ struct display_smartbond_data { struct k_sem dma_sync_sem; /* Granted DMA channel used for memory transfers */ int dma_channel; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + /* Flag to determine if device suspension is allowed */ + bool is_sleep_allowed; +#endif }; struct display_smartbond_config { @@ -180,6 +186,44 @@ static void smartbond_display_isr(const void *arg) k_sem_give(&data->sync_sem); } +static void display_smartbond_dma_cb(const struct device *dma, void *arg, + uint32_t id, int status) +{ + struct display_smartbond_data *data = arg; + + if (status < 0) { + LOG_WRN("DMA transfer did not complete"); + } + + k_sem_give(&data->dma_sync_sem); +} + +static int display_smartbond_dma_config(const struct device *dev) +{ + struct display_smartbond_data *data = dev->data; + + data->dma = DEVICE_DT_GET(DT_NODELABEL(dma)); + if (!device_is_ready(data->dma)) { + LOG_ERR("DMA device is not ready"); + return -ENODEV; + } + + data->dma_cfg.channel_direction = MEMORY_TO_MEMORY; + data->dma_cfg.user_data = data; + data->dma_cfg.dma_callback = display_smartbond_dma_cb; + data->dma_cfg.block_count = 1; + data->dma_cfg.head_block = &data->dma_block_cfg; + + /* Request an arbitrary DMA channel */ + data->dma_channel = dma_request_channel(data->dma, NULL); + if (data->dma_channel < 0) { + LOG_ERR("Could not acquire a DMA channel"); + return -EIO; + } + + return 0; +} + static int display_smartbond_resume(const struct device *dev) { const struct display_smartbond_config *config = dev->config; @@ -207,47 +251,43 @@ static int display_smartbond_resume(const struct device *dev) } #endif + ret = display_smartbond_dma_config(dev); + if (ret < 0) { + return ret; + } + return display_smartbond_configure(dev); } -static void display_smartbond_dma_cb(const struct device *dma, void *arg, - uint32_t id, int status) +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static void display_smartbond_dma_deconfig(const struct device *dev) { - struct display_smartbond_data *data = arg; + struct display_smartbond_data *data = dev->data; - if (status < 0) { - LOG_WRN("DMA transfer did not complete"); - } + __ASSERT(data->dma, "DMA should be already initialized"); - k_sem_give(&data->dma_sync_sem); + dma_release_channel(data->dma, data->dma_channel); } -static int display_smartbond_dma_config(const struct device *dev) +static int display_smartbond_suspend(const struct device *dev) { - struct display_smartbond_data *data = dev->data; + const struct display_smartbond_config *config = dev->config; + int ret; - data->dma = DEVICE_DT_GET(DT_NODELABEL(dma)); - if (!device_is_ready(data->dma)) { - LOG_ERR("DMA device is not ready"); - return -ENODEV; + /* Select sleep state; it's OK if settings fails for any reason */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_WRN("Could not apply DISPLAY pins' sleep state"); } - data->dma_cfg.channel_direction = MEMORY_TO_MEMORY; - data->dma_cfg.user_data = data; - data->dma_cfg.dma_callback = display_smartbond_dma_cb; - data->dma_cfg.block_count = 1; - data->dma_cfg.head_block = &data->dma_block_cfg; + /* Disable host controller to minimize power consumption */ + da1469x_lcdc_set_status(false, false, 0); - /* Request an arbitrary DMA channel */ - data->dma_channel = dma_request_channel(data->dma, NULL); - if (data->dma_channel < 0) { - LOG_ERR("Could not acquire a DMA channel"); - return -EIO; - } + display_smartbond_dma_deconfig(dev); return 0; } - +#endif static int display_smartbond_init(const struct device *dev) { @@ -271,33 +311,25 @@ static int display_smartbond_init(const struct device *dev) } } - ret = display_smartbond_resume(dev); - if (ret < 0) { - return ret; - } - - ret = display_smartbond_dma_config(dev); - if (ret < 0) { - return ret; - } - IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_display_isr, DEVICE_DT_INST_GET(0), 0); -#if CONFIG_PM - /* - * When in continues mode, the display device should always be refreshed - * and so the controller is not allowed to be turned off. The latter, is - * powered by PD_SYS which is turned off when the SoC enters the extended - * sleep state. By acquiring PD_SYS, the deep sleep state is prevented - * and the system enters the low-power state (i.e. ARM WFI) when possible. - * - * XXX CONFIG_PM_DEVICE_RUNTIME is no supported yet! - */ - da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + + /* Sleep is allowed until the device is explicitly resumed on application level. */ + if (ret == 0) { + data->is_sleep_allowed = true; + } +#else + /* Resume if either PM is not used at all or if PM without runtime is used. */ + ret = display_smartbond_resume(dev); #endif - return 0; + return ret; } static int display_smartbond_blanking_on(const struct device *dev) @@ -323,6 +355,14 @@ static int display_smartbond_blanking_on(const struct device *dev) } } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + /* + * At this moment the display panel should be turned off and so the device + * can enter the suspend state. + */ + data->is_sleep_allowed = true; +#endif + k_sem_give(&data->device_sem); return ret; @@ -351,6 +391,14 @@ static int display_smartbond_blanking_off(const struct device *dev) */ LCDC->LCDC_MODE_REG &= ~LCDC_LCDC_MODE_REG_LCDC_FORCE_BLANK_Msk; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + /* + * At this moment the display should be turned on and so the device + * cannot enter the suspend state. + */ + data->is_sleep_allowed = false; +#endif + k_sem_give(&data->device_sem); return ret; @@ -515,6 +563,36 @@ static int display_smartbond_write(const struct device *dev, return 0; } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int display_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + /* Initialize with an error code that should abort sleeping */ + int ret = -EBUSY; + struct display_smartbond_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* Sleep is only allowed whne display blanking is activated */ + if (data->is_sleep_allowed) { + (void)display_smartbond_suspend(dev); + ret = 0; + } + break; + case PM_DEVICE_ACTION_RESUME: + __ASSERT_NO_MSG(data->is_sleep_allowed); + /* + * The resume error code should not be taken into consideration + * by the PM subsystem + */ + ret = display_smartbond_resume(dev); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif static struct display_driver_api display_smartbond_driver_api = { .write = display_smartbond_write, @@ -527,6 +605,7 @@ static struct display_driver_api display_smartbond_driver_api = { #define SMARTBOND_DISPLAY_INIT(inst) \ PINCTRL_DT_INST_DEFINE(inst); \ + PM_DEVICE_DT_INST_DEFINE(inst, display_smartbond_pm_action); \ \ __aligned(4) static uint8_t buffer_ ## inst[(((DT_INST_PROP(inst, width) * \ DISPLAY_SMARTBOND_PIXEL_SIZE(inst)) + 0x3) & ~0x3) * \ @@ -572,7 +651,7 @@ static struct display_driver_api display_smartbond_driver_api = { }; \ \ \ - DEVICE_DT_INST_DEFINE(inst, display_smartbond_init, NULL, \ + DEVICE_DT_INST_DEFINE(inst, display_smartbond_init, PM_DEVICE_DT_INST_GET(inst), \ &display_smartbond_data_## inst, \ &display_smartbond_config_## inst, \ POST_KERNEL, \ From 1b621b35c22ecc083fe81f2af9b70765e91c6ffe Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0661/1389] dts: bindings: dac: Add NXP GAU DAC binding Add binding for NXP GAU DAC Signed-off-by: Declan Snyder --- dts/bindings/dac/nxp,gau-dac.yaml | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 dts/bindings/dac/nxp,gau-dac.yaml diff --git a/dts/bindings/dac/nxp,gau-dac.yaml b/dts/bindings/dac/nxp,gau-dac.yaml new file mode 100644 index 00000000000000..e151d2fdbe3d51 --- /dev/null +++ b/dts/bindings/dac/nxp,gau-dac.yaml @@ -0,0 +1,45 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP GAU DAC + +compatible: "nxp,gau-dac" + +include: dac-controller.yaml + +properties: + nxp,dac-reference: + type: string + enum: + - "internal" + - "external" + default: "internal" + description: | + DAC reference select. + Default is "internal" because that is the reset value. + + nxp,output-voltage-range: + type: string + enum: + - "small" + - "medium" + - "large" + default: "large" + description: | + See specific platform Reference Manual for equations describing the options. + Default is large because that is the reset value. + + nxp,conversion-rate: + type: string + enum: + - "62.5K" + - "125K" + - "250K" + - "500K" + default: "62.5K" + description: | + DAC conversion rate. + Default is "62.5K" because that is the reset value. + + "#io-channel-cells": + const: 0 From 5b79dacb668507e2bf0b8a16832588900ea1c813 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0662/1389] dts: bindings: adc: Add NXP GAU ADC binding Add binding for NXP GAU ADC Signed-off-by: Declan Snyder --- dts/bindings/adc/nxp,gau-adc.yaml | 55 ++++++++++++++++++++ include/zephyr/dt-bindings/adc/nxp,gau-adc.h | 27 ++++++++++ 2 files changed, 82 insertions(+) create mode 100644 dts/bindings/adc/nxp,gau-adc.yaml create mode 100644 include/zephyr/dt-bindings/adc/nxp,gau-adc.h diff --git a/dts/bindings/adc/nxp,gau-adc.yaml b/dts/bindings/adc/nxp,gau-adc.yaml new file mode 100644 index 00000000000000..7f5c5767d78aba --- /dev/null +++ b/dts/bindings/adc/nxp,gau-adc.yaml @@ -0,0 +1,55 @@ +# Copyright 2022 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP GAU GPADC. + +compatible: "nxp,gau-adc" + +include: + - name: base.yaml + - name: adc-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + nxp,clock-divider: + type: int + description: | + Clock divider from 1 to 32. + Default is 1 which is reset value. + default: 1 + + nxp,power-mode: + type: string + description: | + Current bias. + Default is "full-bias" because it is the reset value. + enum: + - "full-bias" + - "half-bias" + default: "full-bias" + + nxp,input-buffer: + type: boolean + description: Enable use of the input buffer + + nxp,calibration-voltage: + type: string + enum: + - "internal" + - "external" + default: "internal" + description: | + Use external calibration voltage. + Default is "internal" because it is the reset value. + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/include/zephyr/dt-bindings/adc/nxp,gau-adc.h b/include/zephyr/dt-bindings/adc/nxp,gau-adc.h new file mode 100644 index 00000000000000..712a342eedc7e7 --- /dev/null +++ b/include/zephyr/dt-bindings/adc/nxp,gau-adc.h @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright 2022 NXP + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NXP_GAU_ADC_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NXP_GAU_ADC_H_ + +#include + +/* Channel Sources */ +#define GAU_ADC_CH0 0 +#define GAU_ADC_CH1 1 +#define GAU_ADC_CH2 2 +#define GAU_ADC_CH3 3 +#define GAU_ADC_CH4 4 +#define GAU_ADC_CH5 5 +#define GAU_ADC_CH6 6 +#define GAU_ADC_CH7 7 +#define GAU_ADC_VBATS 8 +#define GAU_ADC_VREF 9 +#define GAU_ADC_DACA 10 +#define GAU_ADC_DACB 11 +#define GAU_ADC_VSSA 12 +#define GAU_ADC_TEMPP 15 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NXP_GAU_ADC_H_ */ From cacc74cad645b2ef949187c2abe59a2546b2dd30 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0663/1389] drivers: adc: Add NXP GAU ADC Driver Add driver for NXP GAU ADC using MCUX HAL. Signed-off-by: Declan Snyder --- drivers/adc/CMakeLists.txt | 1 + drivers/adc/Kconfig.mcux | 8 + drivers/adc/adc_mcux_gau_adc.c | 392 +++++++++++++++++++++++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 drivers/adc/adc_mcux_gau_adc.c diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index ae0ebcb5b54cc5..cd4006bccd77ed 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -50,3 +50,4 @@ zephyr_library_sources_ifdef(CONFIG_ADC_AD559X adc_ad559x.c) zephyr_library_sources_ifdef(CONFIG_ADC_LTC2451 adc_ltc2451.c) zephyr_library_sources_ifdef(CONFIG_ADC_NUMAKER adc_numaker.c) zephyr_library_sources_ifdef(CONFIG_ADC_ENE_KB1200 adc_ene_kb1200.c) +zephyr_library_sources_ifdef(CONFIG_ADC_MCUX_GAU adc_mcux_gau_adc.c) diff --git a/drivers/adc/Kconfig.mcux b/drivers/adc/Kconfig.mcux index 725ec32c2c8926..a61e7068e886c4 100644 --- a/drivers/adc/Kconfig.mcux +++ b/drivers/adc/Kconfig.mcux @@ -41,6 +41,14 @@ config ADC_MCUX_ETC help Enable the MCUX ADC ETC driver. +config ADC_MCUX_GAU + bool "MCUX GAU ADC driver" + default y + depends on DT_HAS_NXP_GAU_ADC_ENABLED + select ADC_CONFIGURABLE_INPUTS + help + Enable the GAU ADC driver + if ADC_MCUX_ADC16 choice diff --git a/drivers/adc/adc_mcux_gau_adc.c b/drivers/adc/adc_mcux_gau_adc.c new file mode 100644 index 00000000000000..137c33feeaf47a --- /dev/null +++ b/drivers/adc/adc_mcux_gau_adc.c @@ -0,0 +1,392 @@ +/* + * Copyright 2022-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_gau_adc + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(adc_mcux_gau_adc, CONFIG_ADC_LOG_LEVEL); + +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +#include + +#define NUM_ADC_CHANNELS 16 + +struct mcux_gau_adc_config { + ADC_Type *base; + void (*irq_config_func)(const struct device *dev); + adc_clock_divider_t clock_div; + adc_analog_portion_power_mode_t power_mode; + bool input_gain_buffer; + adc_calibration_ref_t cal_volt; +}; + +struct mcux_gau_adc_data { + const struct device *dev; + struct adc_context ctx; + adc_channel_source_t channel_sources[NUM_ADC_CHANNELS]; + uint8_t scan_length; + uint16_t *results; + size_t results_length; + uint16_t *repeat; + struct k_work read_samples_work; +}; + +static int mcux_gau_adc_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + const struct mcux_gau_adc_config *config = dev->config; + struct mcux_gau_adc_data *data = dev->data; + ADC_Type *base = config->base; + uint8_t channel_id = channel_cfg->channel_id; + uint8_t source_channel = channel_cfg->input_positive; + uint32_t tmp_reg; + + if (channel_cfg->differential) { + LOG_ERR("Differential channels not yet supported"); + return -ENOTSUP; + } + + if (channel_id >= NUM_ADC_CHANNELS) { + LOG_ERR("ADC does not support more than %d channels", NUM_ADC_CHANNELS); + return -ENOTSUP; + } + + if (source_channel > 12 && source_channel != 15) { + LOG_ERR("Invalid source channel"); + return -EINVAL; + } + + /* Set Acquisition/Warmup time */ + tmp_reg = base->ADC_REG_INTERVAL; + base->ADC_REG_INTERVAL &= ~ADC_ADC_REG_INTERVAL_WARMUP_TIME_MASK; + base->ADC_REG_INTERVAL &= ~ADC_ADC_REG_INTERVAL_BYPASS_WARMUP_MASK; + if (channel_cfg->acquisition_time == 0) { + base->ADC_REG_INTERVAL |= ADC_ADC_REG_INTERVAL_BYPASS_WARMUP_MASK; + } else if (channel_cfg->acquisition_time <= 32) { + base->ADC_REG_INTERVAL |= + ADC_ADC_REG_INTERVAL_WARMUP_TIME(channel_cfg->acquisition_time - 1); + } else { + LOG_ERR("Invalid acquisition time requested of ADC"); + return -EINVAL; + } + /* If user changed the warmup time, warn */ + if (base->ADC_REG_INTERVAL != tmp_reg) { + LOG_WRN("Acquisition/Warmup time is global to entire ADC peripheral, " + "i.e. channel_setup will override this property for all previous channels."); + } + + /* Set Input Gain */ + tmp_reg = base->ADC_REG_ANA; + base->ADC_REG_ANA &= ~ADC_ADC_REG_ANA_INBUF_GAIN_MASK; + if (channel_cfg->gain == ADC_GAIN_1) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_INBUF_GAIN(kADC_InputGain1); + } else if (channel_cfg->gain == ADC_GAIN_1_2) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_INBUF_GAIN(kADC_InputGain0P5); + } else if (channel_cfg->gain == ADC_GAIN_2) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_INBUF_GAIN(kADC_InputGain2); + } else { + LOG_ERR("Invalid gain"); + return -EINVAL; + } + /* If user changed the gain, warn */ + if (base->ADC_REG_ANA != tmp_reg) { + LOG_WRN("Input gain is global to entire ADC peripheral, " + "i.e. channel_setup will override this property for all previous channels."); + } + + /* Set Reference voltage of ADC */ + tmp_reg = base->ADC_REG_ANA; + base->ADC_REG_ANA &= ~ADC_ADC_REG_ANA_VREF_SEL_MASK; + if (channel_cfg->reference == ADC_REF_INTERNAL) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_VREF_SEL(kADC_Vref1P2V); + } else if (channel_cfg->reference == ADC_REF_EXTERNAL0) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_VREF_SEL(kADC_VrefExternal); + } else if (channel_cfg->reference == ADC_REF_VDD_1) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_VREF_SEL(kADC_Vref1P8V); + } else { + LOG_ERR("Vref not supported"); + return -ENOTSUP; + } + /* if user changed the reference voltage, warn */ + if (base->ADC_REG_ANA != tmp_reg) { + LOG_WRN("Reference voltage is global to entire ADC peripheral, " + "i.e. channel_setup will override this property for all previous channels."); + } + + data->channel_sources[channel_id] = source_channel; + + return 0; +} + +static void mcux_gau_adc_read_samples(struct k_work *work) +{ + struct mcux_gau_adc_data *data = + CONTAINER_OF(work, struct mcux_gau_adc_data, + read_samples_work); + const struct device *dev = data->dev; + const struct mcux_gau_adc_config *config = dev->config; + ADC_Type *base = config->base; + + /* using this variable to prevent buffer overflow */ + size_t length = data->results_length; + + while ((ADC_GetFifoDataCount(base) > 0) && (--length > 0)) { + *(data->results++) = (uint16_t)ADC_GetConversionResult(base); + } + + adc_context_on_sampling_done(&data->ctx, dev); +} + + +static void mcux_gau_adc_isr(const struct device *dev) +{ + const struct mcux_gau_adc_config *config = dev->config; + struct mcux_gau_adc_data *data = dev->data; + ADC_Type *base = config->base; + + if (ADC_GetStatusFlags(base) & kADC_DataReadyInterruptFlag) { + /* Clear flag to avoid infinite interrupt */ + ADC_ClearStatusFlags(base, kADC_DataReadyInterruptFlag); + + /* offload and do not block during irq */ + k_work_submit(&data->read_samples_work); + } else { + LOG_ERR("ADC received unimplemented interrupt"); + } +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct mcux_gau_adc_data *data = + CONTAINER_OF(ctx, struct mcux_gau_adc_data, ctx); + const struct mcux_gau_adc_config *config = data->dev->config; + ADC_Type *base = config->base; + + ADC_StopConversion(base); + ADC_DoSoftwareTrigger(base); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, + bool repeat_sampling) +{ + struct mcux_gau_adc_data *data = + CONTAINER_OF(ctx, struct mcux_gau_adc_data, ctx); + + if (repeat_sampling) { + data->results = data->repeat; + } +} + +static int mcux_gau_adc_do_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + const struct mcux_gau_adc_config *config = dev->config; + ADC_Type *base = config->base; + struct mcux_gau_adc_data *data = dev->data; + uint8_t num_channels = 0; + + /* if user selected channel >= NUM_ADC_CHANNELS that is invalid */ + if (sequence->channels & (0xFFFF << NUM_ADC_CHANNELS)) { + LOG_ERR("Invalid channels selected for sequence"); + return -EINVAL; + } + + /* Count channels */ + for (int i = 0; i < NUM_ADC_CHANNELS; i++) { + num_channels += ((sequence->channels & (0x1 << i)) ? 1 : 0); + } + + /* Buffer must hold (number of samples per channel) * (number of channels) samples */ + if ((sequence->options != NULL && sequence->buffer_size < + ((1 + sequence->options->extra_samplings) * num_channels)) || + (sequence->options == NULL && sequence->buffer_size < num_channels)) { + LOG_ERR("Buffer size too small"); + return -ENOMEM; + } + + /* Set scan length in data struct for isr to understand & set scan length register */ + base->ADC_REG_CONFIG &= ~ADC_ADC_REG_CONFIG_SCAN_LENGTH_MASK; + data->scan_length = num_channels; + /* Register Value is 1 less than what it represents */ + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_SCAN_LENGTH(data->scan_length - 1); + + /* Set up scan channels */ + for (int channel = 0; channel < NUM_ADC_CHANNELS; channel++) { + if (sequence->channels & (0x1 << channel)) { + ADC_SetScanChannel(base, + data->scan_length - num_channels--, + data->channel_sources[channel]); + } + } + + /* Set resolution of ADC */ + base->ADC_REG_ANA &= ~ADC_ADC_REG_ANA_RES_SEL_MASK; + /* odd numbers are for differential channels */ + if (sequence->resolution == 12 || sequence->resolution == 11) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_RES_SEL(kADC_Resolution12Bit); + } else if (sequence->resolution == 14 || sequence->resolution == 13) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_RES_SEL(kADC_Resolution14Bit); + } else if (sequence->resolution == 16 || sequence->resolution == 15) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_RES_SEL(kADC_Resolution16Bit); + } else { + LOG_ERR("Invalid resolution"); + return -EINVAL; + } + + /* Set oversampling */ + base->ADC_REG_CONFIG &= ~ADC_ADC_REG_CONFIG_AVG_SEL_MASK; + if (sequence->oversampling == 0) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_AverageNone); + } else if (sequence->oversampling == 1) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average2); + } else if (sequence->oversampling == 2) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average4); + } else if (sequence->oversampling == 3) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average8); + } else if (sequence->oversampling == 4) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average16); + } else { + LOG_ERR("Invalid oversampling setting"); + return -EINVAL; + } + + /* Calibrate if requested */ + if (sequence->calibrate) { + if (ADC_DoAutoCalibration(base, config->cal_volt)) { + LOG_WRN("Calibration of ADC failed!"); + } + } + + data->results = sequence->buffer; + data->results_length = sequence->buffer_size; + data->repeat = sequence->buffer; + + adc_context_start_read(&data->ctx, sequence); + + return adc_context_wait_for_completion(&data->ctx); +} + +static int mcux_gau_adc_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + struct mcux_gau_adc_data *data = dev->data; + int error; + + adc_context_lock(&data->ctx, false, NULL); + error = mcux_gau_adc_do_read(dev, sequence); + adc_context_release(&data->ctx, error); + return error; +} + +#ifdef CONFIG_ADC_ASYNC +static int mcux_gau_adc_read_async(const struct device *dev, + const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + struct mcux_gau_adc_data *data = dev->data; + int error; + + adc_context_lock(&data->ctx, true, async); + error = mcux_gau_adc_do_read(dev, sequence); + adc_context_release(&data->ctx, error); + return error; +} +#endif + + +static int mcux_gau_adc_init(const struct device *dev) +{ + const struct mcux_gau_adc_config *config = dev->config; + struct mcux_gau_adc_data *data = dev->data; + ADC_Type *base = config->base; + adc_config_t adc_config; + + data->dev = dev; + + LOG_DBG("Initializing ADC"); + + ADC_GetDefaultConfig(&adc_config); + + /* DT configs */ + adc_config.clockDivider = config->clock_div; + adc_config.powerMode = config->power_mode; + adc_config.enableInputGainBuffer = config->input_gain_buffer; + adc_config.triggerSource = kADC_TriggerSourceSoftware; + + adc_config.inputMode = kADC_InputSingleEnded; + /* One shot meets the needs of the current zephyr adc context/api */ + adc_config.conversionMode = kADC_ConversionOneShot; + /* since using one shot mode, just interrupt on one sample (agnostic to # channels) */ + adc_config.fifoThreshold = kADC_FifoThresholdData1; + /* 32 bit width not supported in this driver; zephyr seems to use 16 bit */ + adc_config.resultWidth = kADC_ResultWidth16; + adc_config.enableDMA = false; + adc_config.enableADC = true; + + ADC_Init(base, &adc_config); + + if (ADC_DoAutoCalibration(base, config->cal_volt)) { + LOG_WRN("Calibration of ADC failed!"); + } + + ADC_ClearStatusFlags(base, kADC_DataReadyInterruptFlag); + + config->irq_config_func(dev); + ADC_EnableInterrupts(base, kADC_DataReadyInterruptEnable); + + k_work_init(&data->read_samples_work, &mcux_gau_adc_read_samples); + + adc_context_init(&data->ctx); + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static const struct adc_driver_api mcux_gau_adc_driver_api = { + .channel_setup = mcux_gau_adc_channel_setup, + .read = mcux_gau_adc_read, +#ifdef CONFIG_ADC_ASYNC + .read_async = mcux_gau_adc_read_async, +#endif + .ref_internal = 1200, +}; + + +#define GAU_ADC_MCUX_INIT(n) \ + \ + static void mcux_gau_adc_config_func_##n(const struct device *dev); \ + \ + static const struct mcux_gau_adc_config mcux_gau_adc_config_##n = { \ + .base = (ADC_Type *)DT_INST_REG_ADDR(n), \ + .irq_config_func = mcux_gau_adc_config_func_##n, \ + /* Minus one because DT starts at 1, HAL enum starts at 0 */ \ + .clock_div = DT_INST_PROP(n, nxp_clock_divider) - 1, \ + .power_mode = DT_INST_ENUM_IDX(n, nxp_power_mode), \ + .input_gain_buffer = DT_INST_PROP(n, nxp_input_buffer), \ + .cal_volt = DT_INST_ENUM_IDX(n, nxp_calibration_voltage), \ + }; \ + \ + static struct mcux_gau_adc_data mcux_gau_adc_data_##n = {0}; \ + \ + DEVICE_DT_INST_DEFINE(n, &mcux_gau_adc_init, NULL, \ + &mcux_gau_adc_data_##n, &mcux_gau_adc_config_##n, \ + POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ + &mcux_gau_adc_driver_api); \ + \ + static void mcux_gau_adc_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + mcux_gau_adc_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } + +DT_INST_FOREACH_STATUS_OKAY(GAU_ADC_MCUX_INIT) From 4e1ab4b1c55ea7cc322d8aef6e63ababcb280dd7 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0664/1389] drivers: dac: Add driver for NXP GAU DAC Add driver for NXP GAU DAC using MCUX HAL. Signed-off-by: Declan Snyder --- drivers/dac/CMakeLists.txt | 1 + drivers/dac/Kconfig.mcux | 7 +++ drivers/dac/dac_mcux_gau.c | 116 +++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 drivers/dac/dac_mcux_gau.c diff --git a/drivers/dac/CMakeLists.txt b/drivers/dac/CMakeLists.txt index 50cd660ac524e0..d6869cc234a1c9 100644 --- a/drivers/dac/CMakeLists.txt +++ b/drivers/dac/CMakeLists.txt @@ -23,3 +23,4 @@ zephyr_library_sources_ifdef(CONFIG_DAC_AD559X dac_ad559x.c) zephyr_library_sources_ifdef(CONFIG_DAC_AD56XX dac_ad56xx.c) zephyr_library_sources_ifdef(CONFIG_DAC_AD569X dac_ad569x.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c) +zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_GAU dac_mcux_gau.c) diff --git a/drivers/dac/Kconfig.mcux b/drivers/dac/Kconfig.mcux index 87869775d03c19..417e1b9be943a9 100644 --- a/drivers/dac/Kconfig.mcux +++ b/drivers/dac/Kconfig.mcux @@ -31,3 +31,10 @@ config DAC_MCUX_DAC32_TESTOUT depends on DAC_MCUX_DAC32 help Enable the DAC test output. + +config DAC_MCUX_GAU + bool "NXP GAU DAC driver" + default y + depends on DT_HAS_NXP_GAU_DAC_ENABLED + help + Enable the driver for the NXP GAU DAC. diff --git a/drivers/dac/dac_mcux_gau.c b/drivers/dac/dac_mcux_gau.c new file mode 100644 index 00000000000000..ba4835b1c70468 --- /dev/null +++ b/drivers/dac/dac_mcux_gau.c @@ -0,0 +1,116 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_gau_dac + +#include + +#include + +#define LOG_LEVEL CONFIG_DAC_LOG_LEVEL +#include +#include +LOG_MODULE_REGISTER(nxp_gau_dac); + +struct nxp_gau_dac_config { + DAC_Type *base; + dac_conversion_rate_t conversion_rate : 2; + dac_reference_voltage_source_t voltage_ref : 1; + dac_output_voltage_range_t output_range : 2; +}; + +static inline dac_channel_id_t convert_channel_id(uint8_t channel_id) +{ + switch (channel_id) { + case 0: return kDAC_ChannelA; + case 1: return kDAC_ChannelB; + default: + LOG_ERR("Invalid DAC channel ID"); + return -EINVAL; + }; +} + +static int nxp_gau_dac_channel_setup(const struct device *dev, + const struct dac_channel_cfg *channel_cfg) +{ + const struct nxp_gau_dac_config *config = dev->config; + dac_channel_config_t dac_channel_config = {0}; + + if (channel_cfg->resolution != 10) { + LOG_ERR("DAC only support 10 bit resolution"); + return -EINVAL; + } + + if (channel_cfg->buffered) { + /* External and internal output are mutually exclusive */ + LOG_WRN("Note: buffering DAC output to pad disconnects internal output"); + } + + dac_channel_config.waveType = kDAC_WaveNormal; + dac_channel_config.outMode = channel_cfg->buffered ? + kDAC_ChannelOutputPAD : kDAC_ChannelOutputInternal; + dac_channel_config.timingMode = kDAC_NonTimingCorrelated; + dac_channel_config.enableTrigger = false; + dac_channel_config.enableDMA = false; + dac_channel_config.enableConversion = true; + + DAC_SetChannelConfig(config->base, + (uint32_t)convert_channel_id(channel_cfg->channel_id), + &dac_channel_config); + + return 0; +}; + +static int nxp_gau_dac_write_value(const struct device *dev, + uint8_t channel, uint32_t value) +{ + const struct nxp_gau_dac_config *config = dev->config; + + DAC_SetChannelData(config->base, + (uint32_t)convert_channel_id(channel), + (uint16_t)value); + return 0; +}; + +static const struct dac_driver_api nxp_gau_dac_driver_api = { + .channel_setup = nxp_gau_dac_channel_setup, + .write_value = nxp_gau_dac_write_value, +}; + +static int nxp_gau_dac_init(const struct device *dev) +{ + const struct nxp_gau_dac_config *config = dev->config; + dac_config_t dac_cfg; + + DAC_GetDefaultConfig(&dac_cfg); + + dac_cfg.conversionRate = config->conversion_rate; + dac_cfg.refSource = config->voltage_ref; + dac_cfg.rangeSelect = config->output_range; + + DAC_Init(config->base, &dac_cfg); + + return 0; +}; + +#define NXP_GAU_DAC_INIT(inst) \ + \ + const struct nxp_gau_dac_config nxp_gau_dac_##inst##_config = { \ + .base = (DAC_Type *) DT_INST_REG_ADDR(inst), \ + .voltage_ref = DT_INST_ENUM_IDX(inst, nxp_dac_reference), \ + .conversion_rate = DT_INST_ENUM_IDX(inst, nxp_conversion_rate), \ + .output_range = DT_INST_ENUM_IDX(inst, \ + nxp_output_voltage_range), \ + }; \ + \ + \ + DEVICE_DT_INST_DEFINE(inst, &nxp_gau_dac_init, NULL, \ + NULL, \ + &nxp_gau_dac_##inst##_config, \ + POST_KERNEL, CONFIG_DAC_INIT_PRIORITY, \ + &nxp_gau_dac_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NXP_GAU_DAC_INIT) From afaa9d8b30d003774b00c64c4cc177b48b5144a3 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0665/1389] soc: nxp: rw: Support ADC and DAC Add DT node entries to RW for DAC and ADC. Support the SOC required initialization of the DAC and ADC on RW. Signed-off-by: Declan Snyder --- dts/arm/nxp/nxp_rw6xx_common.dtsi | 31 +++++++++++++++++++++++++++++++ soc/nxp/rw/soc.c | 12 ++++++++++++ 2 files changed, 43 insertions(+) diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index d78879e107a4d8..22e34b4777ac12 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { chosen { @@ -361,6 +362,36 @@ }; }; + + gau { + ranges = <>; + #address-cells = <1>; + #size-cells = <1>; + + adc0: gau_adc0@38000 { + compatible = "nxp,gau-adc"; + reg = <0x38000 0x100>; + interrupts = <112 0>; + status = "disabled"; + #io-channel-cells = <1>; + }; + + adc1: gau_adc1@38100 { + compatible = "nxp,gau-adc"; + reg = <0x38100 0x100>; + interrupts = <111 0>; + status = "disabled"; + #io-channel-cells = <1>; + }; + + dac0: dac@38200 { + compatible = "nxp,gau-dac"; + reg = <0x38200 0x30>; + interrupts = <108 0>; + status = "disabled"; + #io-channel-cells = <0>; + }; + }; }; &flexspi { diff --git a/soc/nxp/rw/soc.c b/soc/nxp/rw/soc.c index f20393ee6dc668..dcf52c84377859 100644 --- a/soc/nxp/rw/soc.c +++ b/soc/nxp/rw/soc.c @@ -147,6 +147,14 @@ __ramfunc void clock_init(void) CLOCK_AttachClk(kNONE_to_WDT0_CLK); #endif +#if defined(CONFIG_ADC_MCUX_GAU) || defined(CONFIG_DAC_MCUX_GAU) + /* Attack clock for GAU and reset */ + CLOCK_AttachClk(kMAIN_CLK_to_GAU_CLK); + CLOCK_SetClkDiv(kCLOCK_DivGauClk, 1U); + CLOCK_EnableClock(kCLOCK_Gau); + RESET_PeripheralReset(kGAU_RST_SHIFT_RSTn); +#endif /* GAU */ + /* Any flexcomm can be USART */ #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_usart, okay)) && CONFIG_SERIAL CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){0, kCLOCK_FrgPllDiv, 255, 0}); @@ -290,6 +298,10 @@ static int nxp_rw600_init(void) /* Initialize clock */ clock_init(); +#if defined(CONFIG_ADC_MCUX_GAU) || defined(CONFIG_DAC_MCUX_GAU) + POWER_PowerOnGau(); +#endif + return 0; } From 03d05bb106037f8742f0b310b5110b5c85caf40b Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0666/1389] boards: nxp: rd_rw612_bga: Enable GAU DAC/ADC Enable the GAU analog converters on the RD_RW612_BGA board. Signed-off-by: Declan Snyder --- boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi index 21872376294bfa..6216d381d037a9 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi @@ -246,3 +246,11 @@ zephyr_udc0: &usb_otg { , ; }; + +&adc0 { + status = "okay"; +}; + +&dac0 { + status = "okay"; +}; From b65d419692659238dee3183a6b0b059253806345 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0667/1389] tests: adc: Test RW612 ADC Enable RW612 RD board to test ADC Signed-off-by: Declan Snyder --- boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml | 1 + .../adc/adc_dt/boards/rd_rw612_bga.overlay | 38 +++++++++++++++++++ samples/drivers/adc/adc_dt/sample.yaml | 1 + .../adc/adc_api/boards/rd_rw612_bga.overlay | 38 +++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay create mode 100644 tests/drivers/adc/adc_api/boards/rd_rw612_bga.overlay diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml b/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml index db7445f1c95418..d821b46b45c312 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml @@ -25,3 +25,4 @@ supported: - watchdog - counter - hwinfo + - adc diff --git a/samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay b/samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..32098b10883ce6 --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay @@ -0,0 +1,38 @@ +/* + * Copyright 2022 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0 &adc0 1>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; +}; diff --git a/samples/drivers/adc/adc_dt/sample.yaml b/samples/drivers/adc/adc_dt/sample.yaml index a4d6c8f5fea033..2096ad78eb9b45 100644 --- a/samples/drivers/adc/adc_dt/sample.yaml +++ b/samples/drivers/adc/adc_dt/sample.yaml @@ -29,6 +29,7 @@ tests: - mr_canhubk3 - longan_nano - longan_nano/gd32vf103/lite + - rd_rw612_bga integration_platforms: - nucleo_l073rz - nrf52840dk/nrf52840 diff --git a/tests/drivers/adc/adc_api/boards/rd_rw612_bga.overlay b/tests/drivers/adc/adc_api/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..53596ab11c413d --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/rd_rw612_bga.overlay @@ -0,0 +1,38 @@ +/* + * Copyright 2023 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0 &adc0 1>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; +}; From 27d5359e56bbb3acdb3739a65b46cf927f1e3ac5 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0668/1389] samples: dac: Enable RW612 DAC Enable RW612 RD board for the DAC sample Signed-off-by: Declan Snyder --- boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml | 1 + samples/drivers/dac/boards/rd_rw612_bga.overlay | 12 ++++++++++++ samples/drivers/dac/sample.yaml | 1 + 3 files changed, 14 insertions(+) create mode 100644 samples/drivers/dac/boards/rd_rw612_bga.overlay diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml b/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml index d821b46b45c312..919f10479ee433 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml @@ -26,3 +26,4 @@ supported: - counter - hwinfo - adc + - dac diff --git a/samples/drivers/dac/boards/rd_rw612_bga.overlay b/samples/drivers/dac/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..55409f2be18675 --- /dev/null +++ b/samples/drivers/dac/boards/rd_rw612_bga.overlay @@ -0,0 +1,12 @@ +/ { + zephyr,user { + dac = <&dac0>; + dac-channel-id = <0>; + dac-resolution = <10>; + }; +}; + +&dac0 { + nxp,conversion-rate = "500K"; + nxp,output-voltage-range = "large"; +}; diff --git a/samples/drivers/dac/sample.yaml b/samples/drivers/dac/sample.yaml index e83c20d5fc0fff..9c7a53beef1f34 100644 --- a/samples/drivers/dac/sample.yaml +++ b/samples/drivers/dac/sample.yaml @@ -43,6 +43,7 @@ tests: - stm32l562e_dk - twr_ke18f - lpcxpresso55s36 + - rd_rw612_bga depends_on: dac integration_platforms: - nucleo_l152re From 9b21cf0b4de8b557fbb26efade92bbab96c36012 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0669/1389] include: usb_hid: remove conditional definition from struct hid_ops For upcoming HID support in the new device stack and to provide API backward compatibility, there must be no conditional definitions in the header. Signed-off-by: Johann Fischer --- include/zephyr/usb/class/usb_hid.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/zephyr/usb/class/usb_hid.h b/include/zephyr/usb/class/usb_hid.h index 8fc380b970e0bb..f15d0526e4ac18 100644 --- a/include/zephyr/usb/class/usb_hid.h +++ b/include/zephyr/usb/class/usb_hid.h @@ -54,9 +54,7 @@ struct hid_ops { * the next transfer. */ hid_int_ready_callback int_in_ready; -#ifdef CONFIG_ENABLE_HID_INT_OUT_EP hid_int_ready_callback int_out_ready; -#endif }; /** From eb86b9c95d8b410843d1b2792862237b3a9e4aa5 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0670/1389] usb: device_next: allow Get Descriptor with recipient interface If the recipient is not the device then it is probably a class specific request where wIndex is the interface number or endpoing and not the language ID. e.g. HID Class Get Descriptor request. Signed-off-by: Johann Fischer --- subsys/usb/device_next/usbd_ch9.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index cec26a508ec7f1..755950cc6519fd 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -28,6 +28,9 @@ LOG_MODULE_REGISTER(usbd_ch9, CONFIG_USBD_LOG_LEVEL); #define SF_TEST_MODE_SELECTOR(wIndex) ((uint8_t)((wIndex) >> 8)) #define SF_TEST_LOWER_BYTE(wIndex) ((uint8_t)(wIndex)) +static int nonstd_request(struct usbd_contex *const uds_ctx, + struct net_buf *const dbuf); + static bool reqtype_is_to_host(const struct usb_setup_packet *const setup) { return setup->wLength && USB_REQTYPE_GET_DIR(setup->bmRequestType); @@ -602,6 +605,16 @@ static int sreq_get_descriptor(struct usbd_contex *const uds_ctx, LOG_DBG("Get Descriptor request type %u index %u", desc_type, desc_idx); + if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_DEVICE) { + /* + * If the recipient is not the device then it is probably a + * class specific request where wIndex is the interface + * number or endpoint and not the language ID. e.g. HID + * Class Get Descriptor request. + */ + return nonstd_request(uds_ctx, buf); + } + switch (desc_type) { case USB_DESC_DEVICE: return sreq_get_desc(uds_ctx, buf, USB_DESC_DEVICE, 0); From a968ca31bd53511b2f5e20dd9bc4dad53da8b72e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0671/1389] usb: device_next: add initial HID device support Add initial HID device support. Unlike the existing HID implementation, the new implementation uses a devicetree to instantiate a HID device. To the user, the HID device appears as a normal Zephyr RTOS device. Signed-off-by: Johann Fischer --- dts/bindings/usb/zephyr,hid-device.yaml | 58 + include/zephyr/usb/class/usbd_hid.h | 218 +++ subsys/usb/device_next/CMakeLists.txt | 6 + subsys/usb/device_next/class/Kconfig | 1 + subsys/usb/device_next/class/Kconfig.hid | 37 + subsys/usb/device_next/class/usbd_hid.c | 744 +++++++++++ subsys/usb/device_next/class/usbd_hid_api.c | 216 +++ .../usb/device_next/class/usbd_hid_internal.h | 23 + .../usb/device_next/class/usbd_hid_macros.h | 1169 +++++++++++++++++ 9 files changed, 2472 insertions(+) create mode 100644 dts/bindings/usb/zephyr,hid-device.yaml create mode 100644 include/zephyr/usb/class/usbd_hid.h create mode 100644 subsys/usb/device_next/class/Kconfig.hid create mode 100644 subsys/usb/device_next/class/usbd_hid.c create mode 100644 subsys/usb/device_next/class/usbd_hid_api.c create mode 100644 subsys/usb/device_next/class/usbd_hid_internal.h create mode 100644 subsys/usb/device_next/class/usbd_hid_macros.h diff --git a/dts/bindings/usb/zephyr,hid-device.yaml b/dts/bindings/usb/zephyr,hid-device.yaml new file mode 100644 index 00000000000000..03887acb0d887b --- /dev/null +++ b/dts/bindings/usb/zephyr,hid-device.yaml @@ -0,0 +1,58 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Bindings for HID device + +compatible: "zephyr,hid-device" + +include: base.yaml + +properties: + interface-name: + type: string + description: | + HID device name. When this property is present, a USB device will use it + as the string descriptor of the interface. + + protocol-code: + type: string + description: | + This property corresponds to the protocol codes defined in Chapter 4.3 + of the HID specification. Only boot devices are required to set one of + the protocols, keyboard or mouse. For non-boot devices, this property is + not required or can be set to none. + - none: Device does not support the boot interface + - keyboard: Device supports boot interface and keyboard protocol + - mouse: Device supports boot interface and mouse protocol + enum: + - none + - keyboard + - mouse + + in-report-size: + type: int + required: true + description: | + The size of the longest input report that the HID device can generate. + This property is used to determine the buffer length used for transfers. + + in-polling-rate: + type: int + required: true + description: | + Input or output type reports polling rate in microseconds. For USB full + speed this could be clamped to 1ms or 255ms depending on the value. + + out-report-size: + type: int + description: | + The size of the longest output report that the HID device can generate. + When this property is present, a USB device will use out pipe for output + reports, otherwise control pipe will be used for output reports. + + out-polling-rate: + type: int + description: | + Output type reports polling rate in microseconds. For USB full + speed this could be clamped to 1ms or 255ms depending on the value. + This option is only effective if the out-report-size property is defined. diff --git a/include/zephyr/usb/class/usbd_hid.h b/include/zephyr/usb/class/usbd_hid.h new file mode 100644 index 00000000000000..5dd6d0dad2354f --- /dev/null +++ b/include/zephyr/usb/class/usbd_hid.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief USBD HID device API header + */ + +#ifndef ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ +#define ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief USBD HID Device API + * @defgroup usbd_hid_device USBD HID device API + * @ingroup usb + * @{ + */ + +/* + * HID Device overview: + * + * +---------------------+ + * | | + * | | + * | HID Device | + * | User "top half" | + * | of the device that +-------+ + * | deals with input | | + * | sampling | | + * | | | + * | | | + * | ------------------- | | + * | | | + * | HID Device user | | + * | callbacks | | + * | handlers | | + * +---------------------+ | + * ^ | HID Device Driver API: + * | | + * set_protocol() | | hid_device_register() + * get_report() | | hid_device_submit_report( + * .... | | ... + * v | + * +---------------------+ | + * | | | + * | HID Device | | + * | "bottom half" |<------+ + * | USB HID class | + * | implementation | + * | | + * | | + * +---------------------+ + * ^ + * v + * +--------------------+ + * | | + * | USB Device | + * | Support | + * | | + * +--------------------+ + */ + +/** HID report types + * Report types used in Get/Set Report requests. + */ +enum { + HID_REPORT_TYPE_INPUT = 1, + HID_REPORT_TYPE_OUTPUT, + HID_REPORT_TYPE_FEATURE, +}; + +/** + * @brief HID device user callbacks + * + * Each device depends on a user part that handles feature, input, and output + * report processing according to the device functionality described by the + * report descriptor. Which callbacks must be implemented depends on the device + * functionality. The USB device part of the HID device, cannot interpret + * device specific report descriptor and only handles USB specific parts, + * transfers and validation of requests, all reports are opaque to it. + * Callbacks are called from the USB device stack thread and must not block. + */ +struct hid_device_ops { + /** + * The interface ready callback is called with the ready argument set + * to true when the corresponding interface is part of the active + * configuration and the device can e.g. begin submitting input + * reports, and with the argument set to false when the interface is no + * longer active. This callback is optional. + */ + void (*iface_ready)(const struct device *dev, const bool ready); + + /** + * This callback is called for the HID Get Report request to get a + * 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. + */ + int (*get_report)(const struct device *dev, + const uint8_t type, const uint8_t id, + const uint16_t len, uint8_t *const buf); + + /** + * This callback is called for the HID Set Report request to set a + * 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. + */ + int (*set_report)(const struct device *dev, + const uint8_t type, const uint8_t id, + const uint16_t len, const uint8_t *const buf); + + /** + * Notification to limit intput report frequency. + * The device should mute an input report submission until a new + * event occurs or until the time specified by the duration value has + * elapsed. If a report ID is used in the report descriptor, the + * device must store the duration and handle the specified report + * accordingly. Duration time resolution is in miliseconds. + */ + void (*set_idle)(const struct device *dev, + const uint8_t id, const uint32_t duration); + + /** + * If a report ID is used in the report descriptor, the device + * must implement this callback and return the duration for the + * specified report ID. Duration time resolution is in miliseconds. + */ + uint32_t (*get_idle)(const struct device *dev, const uint8_t id); + + /** + * Notification that the host has changed the protocol from + * Boot Protocol(0) to Report Protocol(1) or vice versa. + */ + void (*set_protocol)(const struct device *dev, const uint8_t proto); + + /** + * Notification that input report submitted with + * hid_device_submit_report() has been sent. + * If the device does not use the callback, hid_device_submit_report() + * will be processed synchronously. + */ + void (*input_report_done)(const struct device *dev); + + /** + * New output report callback. Callback will only be called for reports + * received through the optional interrupt OUT pipe. If there is no + * interrupt OUT pipe, output reports will be received using set_report(). + * If a report ID is used in the report descriptor, the host places the ID + * in the buffer first, followed by the report data. + */ + void (*output_report)(const struct device *dev, const uint16_t len, + const uint8_t *const buf); + /** + * Optional Start of Frame (SoF) event callback. + * There will always be software and hardware dependent jitter and + * latency. This should be used very carefully, it should not block + * and the execution time should be quite short. + */ + void (*sof)(const struct device *dev); +}; + +/** + * @brief Register HID device report descriptor and user callbacks + * + * The device must register report descriptor and user callbacks before + * USB device support is initialized and enabled. + * + * @param[in] dev Pointer to HID device + * @param[in] rdesc Pointer to HID report descriptor + * @param[in] rsize Size of HID report descriptor + * @param[in] ops Pointer to HID device callbacks + */ +int hid_device_register(const struct device *dev, + const uint8_t *const rdesc, const uint16_t rsize, + const struct hid_device_ops *const ops); + +/** + * @brief Submit new input report + * + * Submit a new input report to be sent via the interrupt IN pipe. If sync is + * true, the functions will block until the report is sent. + * If the device does not provide input_report_done() callback, + * hid_device_submit_report() will be processed synchronously. + * + * @param[in] dev Pointer to HID device + * @param[in] size Size of the input report + * @param[in] report Input report buffer. Report buffer must be aligned. + * + * @return 0 on success, negative errno code on fail. + */ +int hid_device_submit_report(const struct device *dev, + const uint16_t size, const uint8_t *const report); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ */ diff --git a/subsys/usb/device_next/CMakeLists.txt b/subsys/usb/device_next/CMakeLists.txt index 281c2286328148..0c6c9b2426950d 100644 --- a/subsys/usb/device_next/CMakeLists.txt +++ b/subsys/usb/device_next/CMakeLists.txt @@ -62,4 +62,10 @@ zephyr_library_sources_ifdef( class/usbd_uac2.c ) +zephyr_library_sources_ifdef( + CONFIG_USBD_HID_SUPPORT + class/usbd_hid.c + class/usbd_hid_api.c +) + zephyr_linker_sources(DATA_SECTIONS usbd_data.ld) diff --git a/subsys/usb/device_next/class/Kconfig b/subsys/usb/device_next/class/Kconfig index 19fe3cceb8c65f..42e489e9f4db80 100644 --- a/subsys/usb/device_next/class/Kconfig +++ b/subsys/usb/device_next/class/Kconfig @@ -8,3 +8,4 @@ rsource "Kconfig.cdc_ecm" rsource "Kconfig.bt" rsource "Kconfig.msc" rsource "Kconfig.uac2" +rsource "Kconfig.hid" diff --git a/subsys/usb/device_next/class/Kconfig.hid b/subsys/usb/device_next/class/Kconfig.hid new file mode 100644 index 00000000000000..8e3133a1dde892 --- /dev/null +++ b/subsys/usb/device_next/class/Kconfig.hid @@ -0,0 +1,37 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menuconfig USBD_HID_SUPPORT + bool "USB Human Interface Device support" + default y + depends on DT_HAS_ZEPHYR_HID_DEVICE_ENABLED + help + Enables USB Human Interface Device support. + +if USBD_HID_SUPPORT + +config USBD_HID_IN_BUF_COUNT + int "Number of buffers in the IN pool" + range 1 256 + default 2 + help + Number of buffers in the IN pool per HID instance. + +config USBD_HID_OUT_BUF_COUNT + int "Number of buffers in the OUT pool" + range 1 256 + default 2 + help + Number of buffers in the OUT pool per HID instance. + +config USBD_HID_INIT_PRIORITY + int "HID device init priority" + default KERNEL_INIT_PRIORITY_DEVICE + help + HID device initialization priority + +module = USBD_HID +module-str = usbd hid +source "subsys/logging/Kconfig.template.log_config" + +endif # USBD_HID_SUPPORT diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c new file mode 100644 index 00000000000000..befdc9db9ccc93 --- /dev/null +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -0,0 +1,744 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_hid_device + +#include "usbd_hid_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(usbd_hid, CONFIG_USBD_HID_LOG_LEVEL); + +#define HID_GET_IDLE_DURATION(wValue) ((wValue) >> 8) +#define HID_GET_IDLE_ID(wValue) (wValue) +#define HID_GET_REPORT_TYPE(wValue) ((wValue) >> 8) +#define HID_GET_REPORT_ID(wValue) (wValue) + +#define HID_SUBORDINATE_DESC_NUM 1 + +struct subordinate_info { + uint8_t bDescriptorType; + uint16_t wDescriptorLength; +} __packed; + +/* See HID spec. 6.2 Class-Specific Descriptors */ +struct hid_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + /* At least report subordinate descriptor is required. */ + struct subordinate_info sub[HID_SUBORDINATE_DESC_NUM]; +} __packed; + +struct usbd_hid_descriptor { + struct usb_if_descriptor if0; + struct hid_descriptor hid; + struct usb_ep_descriptor in_ep; + struct usb_ep_descriptor hs_in_ep; + struct usb_ep_descriptor out_ep; + struct usb_ep_descriptor hs_out_ep; + + struct usb_if_descriptor if0_1; + struct usb_ep_descriptor alt_hs_in_ep; + struct usb_ep_descriptor alt_hs_out_ep; +}; + +enum { + HID_DEV_CLASS_ENABLED, +}; + +struct hid_device_data { + struct usbd_hid_descriptor *const desc; + struct usbd_class_data *c_data; + struct net_buf_pool *const pool_out; + struct net_buf_pool *const pool_in; + const struct hid_device_ops *ops; + const uint8_t *rdesc; + size_t rsize; + const struct usb_desc_header **const fs_desc; + const struct usb_desc_header **const hs_desc; + atomic_t state; + struct k_sem in_sem; + struct k_work output_work; + uint8_t idle_rate; + uint8_t protocol; +}; + +static inline uint8_t hid_get_in_ep(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + struct usbd_hid_descriptor *desc = ddata->desc; + + return desc->in_ep.bEndpointAddress; +} + +static inline uint8_t hid_get_out_ep(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + struct usbd_hid_descriptor *desc = ddata->desc; + + return desc->out_ep.bEndpointAddress; +} + +static int usbd_hid_request(struct usbd_class_data *const c_data, + struct net_buf *const buf, const int err) +{ + struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + const struct hid_device_ops *ops = ddata->ops; + struct udc_buf_info *bi; + + bi = udc_get_buf_info(buf); + + if (bi->ep == hid_get_out_ep(c_data)) { + if (ops->output_report != NULL) { + if (err == 0) { + ops->output_report(dev, buf->len, buf->data); + } + + k_work_submit(&ddata->output_work); + } + } + + if (bi->ep == hid_get_in_ep(c_data)) { + if (ops->input_report_done != NULL) { + ops->input_report_done(dev); + } else { + k_sem_give(&ddata->in_sem); + } + } + + return usbd_ep_buf_free(uds_ctx, buf); +} + +static int handle_set_idle(const struct device *dev, + const struct usb_setup_packet *const setup) +{ + const uint32_t duration = HID_GET_IDLE_DURATION(setup->wValue); + const uint8_t id = HID_GET_IDLE_ID(setup->wValue); + struct hid_device_data *const ddata = dev->data; + const struct hid_device_ops *ops = ddata->ops; + + if (id == 0U) { + /* Only the common idle rate is stored. */ + ddata->idle_rate = duration; + } + + if (ops->set_idle != NULL) { + ops->set_idle(dev, id, duration * 4UL); + } else { + errno = -ENOTSUP; + } + + LOG_DBG("Set Idle, Report ID %u Duration %u", id, duration); + + return 0; +} + +static int handle_get_idle(const struct device *dev, + const struct usb_setup_packet *const setup, + struct net_buf *const buf) +{ + const uint8_t id = HID_GET_IDLE_ID(setup->wValue); + struct hid_device_data *const ddata = dev->data; + const struct hid_device_ops *ops = ddata->ops; + uint32_t duration; + + if (setup->wLength != 1U) { + errno = -ENOTSUP; + return 0; + } + + /* + * There is no Get Idle callback in the leagacy API, do not issue a + * protocol error if no callback is provided but ID is 0. + */ + if (id != 0U && ops->get_idle == NULL) { + errno = -ENOTSUP; + return 0; + } + + if (id == 0U) { + /* Only the common idle rate is stored. */ + duration = ddata->idle_rate; + } else { + duration = ops->get_idle(dev, id) / 4UL; + } + + LOG_DBG("Get Idle, Report ID %u Duration %u", id, duration); + net_buf_add_u8(buf, duration); + + return 0; +} + +static int handle_set_report(const struct device *dev, + const struct usb_setup_packet *const setup, + const struct net_buf *const buf) +{ + const uint8_t type = HID_GET_REPORT_TYPE(setup->wValue); + 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; + + if (ops->set_report == NULL) { + errno = -ENOTSUP; + LOG_DBG("Set Report not supported"); + return 0; + } + + switch (type) { + case HID_REPORT_TYPE_INPUT: + LOG_DBG("Set Report, Input Report ID %u", id); + errno = ops->set_report(dev, type, id, buf->len, buf->data); + break; + case HID_REPORT_TYPE_OUTPUT: + LOG_DBG("Set Report, Output Report ID %u", id); + errno = ops->set_report(dev, type, id, buf->len, buf->data); + break; + case HID_REPORT_TYPE_FEATURE: + LOG_DBG("Set Report, Feature Report ID %u", id); + errno = ops->set_report(dev, type, id, buf->len, buf->data); + break; + default: + errno = -ENOTSUP; + break; + } + + return 0; +} + +static int handle_get_report(const struct device *dev, + const struct usb_setup_packet *const setup, + struct net_buf *const buf) +{ + const uint8_t type = HID_GET_REPORT_TYPE(setup->wValue); + 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; + + 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); + 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); + 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); + break; + default: + errno = -ENOTSUP; + break; + } + + return 0; +} + +static int handle_set_protocol(const struct device *dev, + const struct usb_setup_packet *const setup) +{ + struct hid_device_data *const ddata = dev->data; + struct usbd_hid_descriptor *const desc = ddata->desc; + const struct hid_device_ops *const ops = ddata->ops; + const uint16_t protocol = setup->wValue; + + if (protocol > HID_PROTOCOL_REPORT) { + /* Can only be 0 (Boot Protocol) or 1 (Report Protocol). */ + errno = -ENOTSUP; + return 0; + } + + if (desc->if0.bInterfaceSubClass == 0) { + /* + * The device does not support the boot protocol and we will + * not notify it. + */ + errno = -ENOTSUP; + return 0; + } + + LOG_DBG("Set Protocol: %s", protocol ? "Report" : "Boot"); + + if (ddata->protocol != protocol) { + ddata->protocol = protocol; + + if (ops->set_protocol) { + ops->set_protocol(dev, protocol); + } + } + + return 0; +} + +static int handle_get_protocol(const struct device *dev, + const struct usb_setup_packet *const setup, + struct net_buf *const buf) +{ + struct hid_device_data *const ddata = dev->data; + struct usbd_hid_descriptor *const desc = ddata->desc; + + if (setup->wValue != 0 || setup->wLength != 1) { + errno = -ENOTSUP; + return 0; + } + + if (desc->if0.bInterfaceSubClass == 0) { + /* The device does not support the boot protocol */ + errno = -ENOTSUP; + return 0; + } + + LOG_DBG("Get Protocol: %s", ddata->protocol ? "Report" : "Boot"); + net_buf_add_u8(buf, ddata->protocol); + + return 0; +} + +static int handle_get_descriptor(const struct device *dev, + const struct usb_setup_packet *const setup, + struct net_buf *const buf) +{ + struct hid_device_data *const ddata = dev->data; + uint8_t desc_type = USB_GET_DESCRIPTOR_TYPE(setup->wValue); + uint8_t desc_idx = USB_GET_DESCRIPTOR_INDEX(setup->wValue); + struct usbd_hid_descriptor *const desc = ddata->desc; + + switch (desc_type) { + case USB_DESC_HID_REPORT: + LOG_DBG("Get descriptor report"); + net_buf_add_mem(buf, ddata->rdesc, MIN(ddata->rsize, setup->wLength)); + break; + case USB_DESC_HID: + LOG_DBG("Get descriptor HID"); + net_buf_add_mem(buf, &desc->hid, MIN(desc->hid.bLength, setup->wLength)); + break; + case USB_DESC_HID_PHYSICAL: + LOG_DBG("Get descriptor physical %u", desc_idx); + errno = -ENOTSUP; + break; + default: + errno = -ENOTSUP; + break; + } + + return 0; +} + +static int usbd_hid_ctd(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup, + const struct net_buf *const buf) +{ + const struct device *dev = usbd_class_get_private(c_data); + int ret = 0; + + switch (setup->bRequest) { + case USB_HID_SET_IDLE: + ret = handle_set_idle(dev, setup); + break; + case USB_HID_SET_REPORT: + ret = handle_set_report(dev, setup, buf); + break; + case USB_HID_SET_PROTOCOL: + ret = handle_set_protocol(dev, setup); + break; + default: + errno = -ENOTSUP; + break; + } + + return ret; +} + +static int usbd_hid_cth(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup, + struct net_buf *const buf) +{ + const struct device *dev = usbd_class_get_private(c_data); + int ret = 0; + + switch (setup->bRequest) { + case USB_HID_GET_IDLE: + ret = handle_get_idle(dev, setup, buf); + break; + case USB_HID_GET_REPORT: + ret = handle_get_report(dev, setup, buf); + break; + case USB_HID_GET_PROTOCOL: + ret = handle_get_protocol(dev, setup, buf); + break; + case USB_SREQ_GET_DESCRIPTOR: + ret = handle_get_descriptor(dev, setup, buf); + break; + default: + errno = -ENOTSUP; + break; + } + + return ret; +} + +static void usbd_hid_sof(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + const struct hid_device_ops *const ops = ddata->ops; + + if (ops->sof) { + ops->sof(dev); + } +} + +static void usbd_hid_enable(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + const struct hid_device_ops *const ops = ddata->ops; + struct usbd_hid_descriptor *const desc = ddata->desc; + + atomic_set_bit(&ddata->state, HID_DEV_CLASS_ENABLED); + ddata->protocol = HID_PROTOCOL_REPORT; + if (ops->iface_ready) { + ops->iface_ready(dev, true); + } + + if (desc->out_ep.bLength != 0U) { + k_work_submit(&ddata->output_work); + } + + LOG_DBG("Configuration enabled"); +} + +static void usbd_hid_disable(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + const struct hid_device_ops *const ops = ddata->ops; + + atomic_clear_bit(&ddata->state, HID_DEV_CLASS_ENABLED); + if (ops->iface_ready) { + ops->iface_ready(dev, false); + } + + LOG_DBG("Configuration disabled"); +} + +static void usbd_hid_suspended(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + + LOG_DBG("Configuration suspended, device %s", dev->name); +} + +static void usbd_hid_resumed(struct usbd_class_data *const c_data) +{ + const struct device *dev = usbd_class_get_private(c_data); + + LOG_DBG("Configuration resumed, device %s", dev->name); +} + +static void *usbd_hid_get_desc(struct usbd_class_data *const c_data, + const enum usbd_speed speed) +{ + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *ddata = dev->data; + + if (speed == USBD_SPEED_HS) { + return ddata->hs_desc; + } + + return ddata->fs_desc; +} + +static int usbd_hid_init(struct usbd_class_data *const c_data) +{ + LOG_DBG("HID class %s init", c_data->name); + + return 0; +} + +static void usbd_hid_shutdown(struct usbd_class_data *const c_data) +{ + LOG_DBG("HID class %s shutdown", c_data->name); +} + +static struct net_buf *hid_buf_alloc_ext(struct hid_device_data *const ddata, + const uint16_t size, void *const data, + const uint8_t ep) +{ + struct net_buf *buf = NULL; + struct udc_buf_info *bi; + + buf = net_buf_alloc_with_data(ddata->pool_in, data, size, K_NO_WAIT); + if (!buf) { + return NULL; + } + + bi = udc_get_buf_info(buf); + memset(bi, 0, sizeof(struct udc_buf_info)); + bi->ep = ep; + + return buf; +} + +static struct net_buf *hid_buf_alloc(struct hid_device_data *const ddata, + const uint8_t ep) +{ + struct net_buf *buf = NULL; + struct udc_buf_info *bi; + + buf = net_buf_alloc(ddata->pool_out, K_NO_WAIT); + if (!buf) { + return NULL; + } + + bi = udc_get_buf_info(buf); + memset(bi, 0, sizeof(struct udc_buf_info)); + bi->ep = ep; + + return buf; +} + +static void hid_dev_output_handler(struct k_work *work) +{ + struct hid_device_data *ddata = CONTAINER_OF(work, + struct hid_device_data, + output_work); + struct usbd_class_data *c_data = ddata->c_data; + struct net_buf *buf; + + if (!atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) { + return; + } + + buf = hid_buf_alloc(ddata, hid_get_out_ep(c_data)); + if (buf == NULL) { + LOG_ERR("Failed to allocate buffer"); + return; + } + + if (usbd_ep_enqueue(c_data, buf)) { + net_buf_unref(buf); + LOG_ERR("Failed to enqueue buffer"); + } +} + +static int hid_dev_submit_report(const struct device *dev, + const uint16_t size, const uint8_t *const report) +{ + struct hid_device_data *const ddata = dev->data; + const struct hid_device_ops *ops = ddata->ops; + struct usbd_class_data *c_data = ddata->c_data; + struct net_buf *buf; + int ret; + + __ASSERT(IS_ALIGNED(report, sizeof(void *)), "Report buffer is not aligned"); + + if (!atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) { + return -EACCES; + } + + buf = hid_buf_alloc_ext(ddata, size, (void *)report, hid_get_in_ep(c_data)); + if (buf == NULL) { + LOG_ERR("Failed to allocate net_buf"); + return -ENOMEM; + } + + ret = usbd_ep_enqueue(c_data, buf); + if (ret) { + net_buf_unref(buf); + return ret; + } + + if (ops->input_report_done == NULL) { + k_sem_take(&ddata->in_sem, K_FOREVER); + } + + return 0; +} + +static int hid_dev_register(const struct device *dev, + const uint8_t *const rdesc, const uint16_t rsize, + const struct hid_device_ops *const ops) +{ + struct hid_device_data *const ddata = dev->data; + struct usbd_hid_descriptor *const desc = ddata->desc; + + if (atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) { + return -EALREADY; + } + + /* Get Report is required for all HID device types. */ + if (ops == NULL || ops->get_report == NULL) { + LOG_ERR("get_report callback is missing"); + return -EINVAL; + } + + /* Set Report is required when an output report is declared. */ + if (desc->out_ep.bLength && ops->set_report == NULL) { + LOG_ERR("set_report callback is missing"); + return -EINVAL; + } + + /* + * Get/Set Protocol are required when device supports boot interface. + * Get Protocol is handled internally, no callback is required. + */ + if (desc->if0.bInterfaceSubClass && ops->set_protocol == NULL) { + LOG_ERR("set_protocol callback is missing"); + return -EINVAL; + } + + ddata->rdesc = rdesc; + ddata->rsize = rsize; + ddata->ops = ops; + + sys_put_le16(ddata->rsize, (uint8_t *)&(desc->hid.sub[0].wDescriptorLength)); + + return 0; +} + +static int hid_device_init(const struct device *dev) +{ + struct hid_device_data *const ddata = dev->data; + + k_work_init(&ddata->output_work, hid_dev_output_handler); + LOG_DBG("HID device %s init", dev->name); + + return 0; +} + +struct usbd_class_api usbd_hid_api = { + .request = usbd_hid_request, + .update = NULL, + .sof = usbd_hid_sof, + .enable = usbd_hid_enable, + .disable = usbd_hid_disable, + .suspended = usbd_hid_suspended, + .resumed = usbd_hid_resumed, + .control_to_dev = usbd_hid_ctd, + .control_to_host = usbd_hid_cth, + .get_desc = usbd_hid_get_desc, + .init = usbd_hid_init, + .shutdown = usbd_hid_shutdown, +}; + +static const struct hid_device_driver_api hid_device_api = { + .submit_report = hid_dev_submit_report, + .dev_register = hid_dev_register, +}; + +#include "usbd_hid_macros.h" + +#define USBD_HID_INTERFACE_SIMPLE_DEFINE(n) \ + static struct usbd_hid_descriptor hid_desc_##n = { \ + .if0 = HID_INTERFACE_DEFINE(n, 0), \ + .hid = HID_DESCRIPTOR_DEFINE(n), \ + .in_ep = HID_IN_EP_DEFINE(n, false, true), \ + .hs_in_ep = HID_IN_EP_DEFINE(n, true, true), \ + .out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, false, true), \ + .hs_out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, true, true), \ + }; \ + \ + const static struct usb_desc_header *hid_fs_desc_##n[] = { \ + (struct usb_desc_header *) &hid_desc_##n.if0, \ + (struct usb_desc_header *) &hid_desc_##n.hid, \ + (struct usb_desc_header *) &hid_desc_##n.in_ep, \ + (struct usb_desc_header *) &hid_desc_##n.out_ep, \ + NULL, \ + }; \ + \ + const static struct usb_desc_header *hid_hs_desc_##n[] = { \ + (struct usb_desc_header *) &hid_desc_##n.if0, \ + (struct usb_desc_header *) &hid_desc_##n.hid, \ + (struct usb_desc_header *) &hid_desc_##n.hs_in_ep, \ + (struct usb_desc_header *) &hid_desc_##n.hs_out_ep, \ + NULL, \ + } + +#define USBD_HID_INTERFACE_ALTERNATE_DEFINE(n) \ + static struct usbd_hid_descriptor hid_desc_##n = { \ + .if0 = HID_INTERFACE_DEFINE(n, 0), \ + .hid = HID_DESCRIPTOR_DEFINE(n), \ + .in_ep = HID_IN_EP_DEFINE(n, false, false), \ + .hs_in_ep = HID_IN_EP_DEFINE(n, true, false), \ + .out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, false, false), \ + .hs_out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, true, false), \ + .if0_1 = HID_INTERFACE_DEFINE(n, 1), \ + .alt_hs_in_ep = HID_IN_EP_DEFINE(n, true, true), \ + .alt_hs_out_ep = HID_OUT_EP_DEFINE_OR_ZERO(n, true, true), \ + }; \ + \ + const static struct usb_desc_header *hid_fs_desc_##n[] = { \ + (struct usb_desc_header *) &hid_desc_##n.if0, \ + (struct usb_desc_header *) &hid_desc_##n.hid, \ + (struct usb_desc_header *) &hid_desc_##n.in_ep, \ + (struct usb_desc_header *) &hid_desc_##n.out_ep, \ + NULL, \ + }; \ + \ + const static struct usb_desc_header *hid_hs_desc_##n[] = { \ + (struct usb_desc_header *) &hid_desc_##n.if0, \ + (struct usb_desc_header *) &hid_desc_##n.hid, \ + (struct usb_desc_header *) &hid_desc_##n.hs_in_ep, \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ + ((struct usb_desc_header *) &hid_desc_##n.hs_out_ep,), ()) \ + (struct usb_desc_header *)&hid_desc_##n.if0_1, \ + (struct usb_desc_header *) &hid_desc_##n.hid, \ + (struct usb_desc_header *) &hid_desc_##n.alt_hs_in_ep, \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ + ((struct usb_desc_header *) &hid_desc_##n.alt_hs_out_ep,), ()) \ + NULL, \ + } + +#define USBD_HID_INTERFACE_DEFINE(n) \ + COND_CODE_1(HID_ALL_MPS_LESS_65(n), \ + (USBD_HID_INTERFACE_SIMPLE_DEFINE(n)), \ + (USBD_HID_INTERFACE_ALTERNATE_DEFINE(n))) + +#define USBD_HID_INSTANCE_DEFINE(n) \ + NET_BUF_POOL_DEFINE(hid_buf_pool_in_##n, \ + CONFIG_USBD_HID_IN_BUF_COUNT, 0, \ + sizeof(struct udc_buf_info), NULL); \ + \ + HID_OUT_POOL_DEFINE(n); \ + USBD_HID_INTERFACE_DEFINE(n); \ + \ + USBD_DEFINE_CLASS(hid_##n, \ + &usbd_hid_api, \ + (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \ + \ + static struct hid_device_data hid_data_##n = { \ + .desc = &hid_desc_##n, \ + .c_data = &hid_##n, \ + .pool_in = &hid_buf_pool_in_##n, \ + .pool_out = HID_OUT_POOL_ADDR(n), \ + .in_sem = Z_SEM_INITIALIZER(hid_data_##n.in_sem, 0, 1), \ + .fs_desc = hid_fs_desc_##n, \ + .hs_desc = hid_hs_desc_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, hid_device_init, NULL, \ + &hid_data_##n, NULL, \ + POST_KERNEL, CONFIG_USBD_HID_INIT_PRIORITY, \ + &hid_device_api); + +DT_INST_FOREACH_STATUS_OKAY(USBD_HID_INSTANCE_DEFINE); diff --git a/subsys/usb/device_next/class/usbd_hid_api.c b/subsys/usb/device_next/class/usbd_hid_api.c new file mode 100644 index 00000000000000..17b0efc1fbbe98 --- /dev/null +++ b/subsys/usb/device_next/class/usbd_hid_api.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "usbd_hid_internal.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(hid_api, CONFIG_USBD_HID_LOG_LEVEL); + +int hid_device_submit_report(const struct device *dev, + const uint16_t size, const uint8_t *const report) +{ + const struct hid_device_driver_api *api = dev->api; + + return api->submit_report(dev, size, report); +} + +int hid_device_register(const struct device *dev, + const uint8_t *const rdesc, const uint16_t rsize, + const struct hid_device_ops *const ops) +{ + const struct hid_device_driver_api *api = dev->api; + + return api->dev_register(dev, rdesc, rsize, ops); +} + +/* Legacy HID API wrapper below */ + +struct legacy_wrapper { + const struct device *dev; + const struct hid_ops *legacy_ops; + struct hid_device_ops *ops; +}; + +static struct hid_device_ops wrapper_ops; + +#define DT_DRV_COMPAT zephyr_hid_device + +#define USBD_HID_WRAPPER_DEFINE(n) \ + { \ + .dev = DEVICE_DT_GET(DT_DRV_INST(n)), \ + .ops = &wrapper_ops, \ + }, + +static struct legacy_wrapper wrappers[] = { + DT_INST_FOREACH_STATUS_OKAY(USBD_HID_WRAPPER_DEFINE) +}; + +static const struct hid_ops *get_legacy_ops(const struct device *dev) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(wrappers); i++) { + if (wrappers[i].dev == dev) { + return wrappers[i].legacy_ops; + } + } + + return NULL; +} + +int wrapper_get_report(const struct device *dev, + const uint8_t type, const uint8_t id, + const uint16_t len, uint8_t *const buf) +{ + const struct hid_ops *legacy_ops = get_legacy_ops(dev); + struct usb_setup_packet setup = { + .bmRequestType = 0, + .bRequest = 0, + .wValue = (type << 8) | id, + .wIndex = 0, + .wLength = len, + }; + uint8_t *d = buf; + int l = len; + + if (legacy_ops != NULL && legacy_ops->get_report != NULL) { + return legacy_ops->get_report(dev, &setup, &l, &d); + } + + return -ENOTSUP; +} + +int wrapper_set_report(const struct device *dev, + const uint8_t type, const uint8_t id, + const uint16_t len, const uint8_t *const buf) +{ + const struct hid_ops *legacy_ops = get_legacy_ops(dev); + struct usb_setup_packet setup = { + .bmRequestType = 0, + .bRequest = 0, + .wValue = (type << 8) | id, + .wIndex = 0, + .wLength = len, + }; + uint8_t *d = (void *)buf; + int l = len; + + if (legacy_ops != NULL && legacy_ops->set_report != NULL) { + return legacy_ops->set_report(dev, &setup, &l, &d); + } + + return -ENOTSUP; +} + +void wrapper_set_idle(const struct device *dev, + const uint8_t id, const uint32_t duration) +{ + if (id != 0U) { + LOG_ERR("Set Idle for %s ID %u duration %u cannot be propagated", + dev->name, id, duration); + } +} + +void wrapper_set_protocol(const struct device *dev, const uint8_t proto) +{ + const struct hid_ops *legacy_ops = get_legacy_ops(dev); + + if (legacy_ops != NULL && legacy_ops->protocol_change != NULL) { + legacy_ops->protocol_change(dev, proto); + } +} + +void wrapper_input_report_done(const struct device *dev) +{ + const struct hid_ops *legacy_ops = get_legacy_ops(dev); + + if (legacy_ops != NULL && legacy_ops->int_in_ready != NULL) { + legacy_ops->int_in_ready(dev); + } +} + +void wrapper_output_report(const struct device *dev, + const uint16_t len, const uint8_t *const buf) +{ + ARG_UNUSED(dev); + ARG_UNUSED(len); + ARG_UNUSED(buf); + + __ASSERT(false, "Output report callback is not supported"); +} + +static struct hid_device_ops wrapper_ops = { + .get_report = wrapper_get_report, + .set_report = wrapper_set_report, + .set_idle = wrapper_set_idle, + .set_protocol = wrapper_set_protocol, + .input_report_done = wrapper_input_report_done, + .output_report = wrapper_output_report, +}; + +int hid_int_ep_write(const struct device *dev, + const uint8_t *data, uint32_t data_len, uint32_t *bytes_ret) +{ + int ret; + + ret = hid_device_submit_report(dev, data_len, data); + if (bytes_ret != NULL) { + *bytes_ret = ret == 0 ? data_len : 0; + } + + return ret; +} + +int hid_int_ep_read(const struct device *dev, + uint8_t *data, uint32_t max_data_len, uint32_t *ret_bytes) +{ + ARG_UNUSED(dev); + ARG_UNUSED(data); + ARG_UNUSED(max_data_len); + ARG_UNUSED(ret_bytes); + + LOG_ERR("Not supported"); + + return -ENOTSUP; +} + +int usb_hid_set_proto_code(const struct device *dev, uint8_t proto_code) +{ + ARG_UNUSED(dev); + ARG_UNUSED(proto_code); + + LOG_WRN("Protocol code is set using DT property protocol-code"); + + return 0; +} + +int usb_hid_init(const struct device *dev) +{ + LOG_DBG("It does nothing for dev %s", dev->name); + + return 0; +} + +void usb_hid_register_device(const struct device *dev, + const uint8_t *desc, size_t size, + const struct hid_ops *ops) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(wrappers); i++) { + if (wrappers[i].dev == dev) { + wrappers[i].legacy_ops = ops; + if (hid_device_register(dev, desc, size, wrappers[i].ops)) { + LOG_ERR("Failed to register HID device"); + } + } + } + +} diff --git a/subsys/usb/device_next/class/usbd_hid_internal.h b/subsys/usb/device_next/class/usbd_hid_internal.h new file mode 100644 index 00000000000000..d049b0c22a3574 --- /dev/null +++ b/subsys/usb/device_next/class/usbd_hid_internal.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* + * HID device driver API, we can keep internally as long as it is only used in + * USB. + */ + +struct hid_device_driver_api { + int (*enable_output)(const struct device *dev, const bool enable); + int (*submit_report)(const struct device *dev, + const uint16_t size, const uint8_t *const report); + int (*dev_register)(const struct device *dev, + const uint8_t *const rdesc, const uint16_t rsize, + const struct hid_device_ops *const ops); +}; diff --git a/subsys/usb/device_next/class/usbd_hid_macros.h b/subsys/usb/device_next/class/usbd_hid_macros.h new file mode 100644 index 00000000000000..c00a18b227a092 --- /dev/null +++ b/subsys/usb/device_next/class/usbd_hid_macros.h @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * The macros in this file are not for public use, but only for HID driver + * instantiation. + */ + +#include +#include + +#ifndef ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ +#define ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ + +/* + * This long list of definitions is used in HID_MPS_LESS_65 macro to determine + * whether an endpoint MPS is equal to or less than 64 bytes. + */ +#define HID_MPS_LESS_65_0 1 +#define HID_MPS_LESS_65_1 1 +#define HID_MPS_LESS_65_2 1 +#define HID_MPS_LESS_65_3 1 +#define HID_MPS_LESS_65_4 1 +#define HID_MPS_LESS_65_5 1 +#define HID_MPS_LESS_65_6 1 +#define HID_MPS_LESS_65_7 1 +#define HID_MPS_LESS_65_8 1 +#define HID_MPS_LESS_65_9 1 +#define HID_MPS_LESS_65_10 1 +#define HID_MPS_LESS_65_11 1 +#define HID_MPS_LESS_65_12 1 +#define HID_MPS_LESS_65_13 1 +#define HID_MPS_LESS_65_14 1 +#define HID_MPS_LESS_65_15 1 +#define HID_MPS_LESS_65_16 1 +#define HID_MPS_LESS_65_17 1 +#define HID_MPS_LESS_65_18 1 +#define HID_MPS_LESS_65_19 1 +#define HID_MPS_LESS_65_20 1 +#define HID_MPS_LESS_65_21 1 +#define HID_MPS_LESS_65_22 1 +#define HID_MPS_LESS_65_23 1 +#define HID_MPS_LESS_65_24 1 +#define HID_MPS_LESS_65_25 1 +#define HID_MPS_LESS_65_26 1 +#define HID_MPS_LESS_65_27 1 +#define HID_MPS_LESS_65_28 1 +#define HID_MPS_LESS_65_29 1 +#define HID_MPS_LESS_65_30 1 +#define HID_MPS_LESS_65_31 1 +#define HID_MPS_LESS_65_32 1 +#define HID_MPS_LESS_65_33 1 +#define HID_MPS_LESS_65_34 1 +#define HID_MPS_LESS_65_35 1 +#define HID_MPS_LESS_65_36 1 +#define HID_MPS_LESS_65_37 1 +#define HID_MPS_LESS_65_38 1 +#define HID_MPS_LESS_65_39 1 +#define HID_MPS_LESS_65_40 1 +#define HID_MPS_LESS_65_41 1 +#define HID_MPS_LESS_65_42 1 +#define HID_MPS_LESS_65_43 1 +#define HID_MPS_LESS_65_44 1 +#define HID_MPS_LESS_65_45 1 +#define HID_MPS_LESS_65_46 1 +#define HID_MPS_LESS_65_47 1 +#define HID_MPS_LESS_65_48 1 +#define HID_MPS_LESS_65_49 1 +#define HID_MPS_LESS_65_50 1 +#define HID_MPS_LESS_65_51 1 +#define HID_MPS_LESS_65_52 1 +#define HID_MPS_LESS_65_53 1 +#define HID_MPS_LESS_65_54 1 +#define HID_MPS_LESS_65_55 1 +#define HID_MPS_LESS_65_56 1 +#define HID_MPS_LESS_65_57 1 +#define HID_MPS_LESS_65_58 1 +#define HID_MPS_LESS_65_59 1 +#define HID_MPS_LESS_65_60 1 +#define HID_MPS_LESS_65_61 1 +#define HID_MPS_LESS_65_62 1 +#define HID_MPS_LESS_65_63 1 +#define HID_MPS_LESS_65_64 1 +#define HID_MPS_LESS_65_65 0 +#define HID_MPS_LESS_65_66 0 +#define HID_MPS_LESS_65_67 0 +#define HID_MPS_LESS_65_68 0 +#define HID_MPS_LESS_65_69 0 +#define HID_MPS_LESS_65_70 0 +#define HID_MPS_LESS_65_71 0 +#define HID_MPS_LESS_65_72 0 +#define HID_MPS_LESS_65_73 0 +#define HID_MPS_LESS_65_74 0 +#define HID_MPS_LESS_65_75 0 +#define HID_MPS_LESS_65_76 0 +#define HID_MPS_LESS_65_77 0 +#define HID_MPS_LESS_65_78 0 +#define HID_MPS_LESS_65_79 0 +#define HID_MPS_LESS_65_80 0 +#define HID_MPS_LESS_65_81 0 +#define HID_MPS_LESS_65_82 0 +#define HID_MPS_LESS_65_83 0 +#define HID_MPS_LESS_65_84 0 +#define HID_MPS_LESS_65_85 0 +#define HID_MPS_LESS_65_86 0 +#define HID_MPS_LESS_65_87 0 +#define HID_MPS_LESS_65_88 0 +#define HID_MPS_LESS_65_89 0 +#define HID_MPS_LESS_65_90 0 +#define HID_MPS_LESS_65_91 0 +#define HID_MPS_LESS_65_92 0 +#define HID_MPS_LESS_65_93 0 +#define HID_MPS_LESS_65_94 0 +#define HID_MPS_LESS_65_95 0 +#define HID_MPS_LESS_65_96 0 +#define HID_MPS_LESS_65_97 0 +#define HID_MPS_LESS_65_98 0 +#define HID_MPS_LESS_65_99 0 +#define HID_MPS_LESS_65_100 0 +#define HID_MPS_LESS_65_101 0 +#define HID_MPS_LESS_65_102 0 +#define HID_MPS_LESS_65_103 0 +#define HID_MPS_LESS_65_104 0 +#define HID_MPS_LESS_65_105 0 +#define HID_MPS_LESS_65_106 0 +#define HID_MPS_LESS_65_107 0 +#define HID_MPS_LESS_65_108 0 +#define HID_MPS_LESS_65_109 0 +#define HID_MPS_LESS_65_110 0 +#define HID_MPS_LESS_65_111 0 +#define HID_MPS_LESS_65_112 0 +#define HID_MPS_LESS_65_113 0 +#define HID_MPS_LESS_65_114 0 +#define HID_MPS_LESS_65_115 0 +#define HID_MPS_LESS_65_116 0 +#define HID_MPS_LESS_65_117 0 +#define HID_MPS_LESS_65_118 0 +#define HID_MPS_LESS_65_119 0 +#define HID_MPS_LESS_65_120 0 +#define HID_MPS_LESS_65_121 0 +#define HID_MPS_LESS_65_122 0 +#define HID_MPS_LESS_65_123 0 +#define HID_MPS_LESS_65_124 0 +#define HID_MPS_LESS_65_125 0 +#define HID_MPS_LESS_65_126 0 +#define HID_MPS_LESS_65_127 0 +#define HID_MPS_LESS_65_128 0 +#define HID_MPS_LESS_65_129 0 +#define HID_MPS_LESS_65_130 0 +#define HID_MPS_LESS_65_131 0 +#define HID_MPS_LESS_65_132 0 +#define HID_MPS_LESS_65_133 0 +#define HID_MPS_LESS_65_134 0 +#define HID_MPS_LESS_65_135 0 +#define HID_MPS_LESS_65_136 0 +#define HID_MPS_LESS_65_137 0 +#define HID_MPS_LESS_65_138 0 +#define HID_MPS_LESS_65_139 0 +#define HID_MPS_LESS_65_140 0 +#define HID_MPS_LESS_65_141 0 +#define HID_MPS_LESS_65_142 0 +#define HID_MPS_LESS_65_143 0 +#define HID_MPS_LESS_65_144 0 +#define HID_MPS_LESS_65_145 0 +#define HID_MPS_LESS_65_146 0 +#define HID_MPS_LESS_65_147 0 +#define HID_MPS_LESS_65_148 0 +#define HID_MPS_LESS_65_149 0 +#define HID_MPS_LESS_65_150 0 +#define HID_MPS_LESS_65_151 0 +#define HID_MPS_LESS_65_152 0 +#define HID_MPS_LESS_65_153 0 +#define HID_MPS_LESS_65_154 0 +#define HID_MPS_LESS_65_155 0 +#define HID_MPS_LESS_65_156 0 +#define HID_MPS_LESS_65_157 0 +#define HID_MPS_LESS_65_158 0 +#define HID_MPS_LESS_65_159 0 +#define HID_MPS_LESS_65_160 0 +#define HID_MPS_LESS_65_161 0 +#define HID_MPS_LESS_65_162 0 +#define HID_MPS_LESS_65_163 0 +#define HID_MPS_LESS_65_164 0 +#define HID_MPS_LESS_65_165 0 +#define HID_MPS_LESS_65_166 0 +#define HID_MPS_LESS_65_167 0 +#define HID_MPS_LESS_65_168 0 +#define HID_MPS_LESS_65_169 0 +#define HID_MPS_LESS_65_170 0 +#define HID_MPS_LESS_65_171 0 +#define HID_MPS_LESS_65_172 0 +#define HID_MPS_LESS_65_173 0 +#define HID_MPS_LESS_65_174 0 +#define HID_MPS_LESS_65_175 0 +#define HID_MPS_LESS_65_176 0 +#define HID_MPS_LESS_65_177 0 +#define HID_MPS_LESS_65_178 0 +#define HID_MPS_LESS_65_179 0 +#define HID_MPS_LESS_65_180 0 +#define HID_MPS_LESS_65_181 0 +#define HID_MPS_LESS_65_182 0 +#define HID_MPS_LESS_65_183 0 +#define HID_MPS_LESS_65_184 0 +#define HID_MPS_LESS_65_185 0 +#define HID_MPS_LESS_65_186 0 +#define HID_MPS_LESS_65_187 0 +#define HID_MPS_LESS_65_188 0 +#define HID_MPS_LESS_65_189 0 +#define HID_MPS_LESS_65_190 0 +#define HID_MPS_LESS_65_191 0 +#define HID_MPS_LESS_65_192 0 +#define HID_MPS_LESS_65_193 0 +#define HID_MPS_LESS_65_194 0 +#define HID_MPS_LESS_65_195 0 +#define HID_MPS_LESS_65_196 0 +#define HID_MPS_LESS_65_197 0 +#define HID_MPS_LESS_65_198 0 +#define HID_MPS_LESS_65_199 0 +#define HID_MPS_LESS_65_200 0 +#define HID_MPS_LESS_65_201 0 +#define HID_MPS_LESS_65_202 0 +#define HID_MPS_LESS_65_203 0 +#define HID_MPS_LESS_65_204 0 +#define HID_MPS_LESS_65_205 0 +#define HID_MPS_LESS_65_206 0 +#define HID_MPS_LESS_65_207 0 +#define HID_MPS_LESS_65_208 0 +#define HID_MPS_LESS_65_209 0 +#define HID_MPS_LESS_65_210 0 +#define HID_MPS_LESS_65_211 0 +#define HID_MPS_LESS_65_212 0 +#define HID_MPS_LESS_65_213 0 +#define HID_MPS_LESS_65_214 0 +#define HID_MPS_LESS_65_215 0 +#define HID_MPS_LESS_65_216 0 +#define HID_MPS_LESS_65_217 0 +#define HID_MPS_LESS_65_218 0 +#define HID_MPS_LESS_65_219 0 +#define HID_MPS_LESS_65_220 0 +#define HID_MPS_LESS_65_221 0 +#define HID_MPS_LESS_65_222 0 +#define HID_MPS_LESS_65_223 0 +#define HID_MPS_LESS_65_224 0 +#define HID_MPS_LESS_65_225 0 +#define HID_MPS_LESS_65_226 0 +#define HID_MPS_LESS_65_227 0 +#define HID_MPS_LESS_65_228 0 +#define HID_MPS_LESS_65_229 0 +#define HID_MPS_LESS_65_230 0 +#define HID_MPS_LESS_65_231 0 +#define HID_MPS_LESS_65_232 0 +#define HID_MPS_LESS_65_233 0 +#define HID_MPS_LESS_65_234 0 +#define HID_MPS_LESS_65_235 0 +#define HID_MPS_LESS_65_236 0 +#define HID_MPS_LESS_65_237 0 +#define HID_MPS_LESS_65_238 0 +#define HID_MPS_LESS_65_239 0 +#define HID_MPS_LESS_65_240 0 +#define HID_MPS_LESS_65_241 0 +#define HID_MPS_LESS_65_242 0 +#define HID_MPS_LESS_65_243 0 +#define HID_MPS_LESS_65_244 0 +#define HID_MPS_LESS_65_245 0 +#define HID_MPS_LESS_65_246 0 +#define HID_MPS_LESS_65_247 0 +#define HID_MPS_LESS_65_248 0 +#define HID_MPS_LESS_65_249 0 +#define HID_MPS_LESS_65_250 0 +#define HID_MPS_LESS_65_251 0 +#define HID_MPS_LESS_65_252 0 +#define HID_MPS_LESS_65_253 0 +#define HID_MPS_LESS_65_254 0 +#define HID_MPS_LESS_65_255 0 +#define HID_MPS_LESS_65_256 0 +#define HID_MPS_LESS_65_257 0 +#define HID_MPS_LESS_65_258 0 +#define HID_MPS_LESS_65_259 0 +#define HID_MPS_LESS_65_260 0 +#define HID_MPS_LESS_65_261 0 +#define HID_MPS_LESS_65_262 0 +#define HID_MPS_LESS_65_263 0 +#define HID_MPS_LESS_65_264 0 +#define HID_MPS_LESS_65_265 0 +#define HID_MPS_LESS_65_266 0 +#define HID_MPS_LESS_65_267 0 +#define HID_MPS_LESS_65_268 0 +#define HID_MPS_LESS_65_269 0 +#define HID_MPS_LESS_65_270 0 +#define HID_MPS_LESS_65_271 0 +#define HID_MPS_LESS_65_272 0 +#define HID_MPS_LESS_65_273 0 +#define HID_MPS_LESS_65_274 0 +#define HID_MPS_LESS_65_275 0 +#define HID_MPS_LESS_65_276 0 +#define HID_MPS_LESS_65_277 0 +#define HID_MPS_LESS_65_278 0 +#define HID_MPS_LESS_65_279 0 +#define HID_MPS_LESS_65_280 0 +#define HID_MPS_LESS_65_281 0 +#define HID_MPS_LESS_65_282 0 +#define HID_MPS_LESS_65_283 0 +#define HID_MPS_LESS_65_284 0 +#define HID_MPS_LESS_65_285 0 +#define HID_MPS_LESS_65_286 0 +#define HID_MPS_LESS_65_287 0 +#define HID_MPS_LESS_65_288 0 +#define HID_MPS_LESS_65_289 0 +#define HID_MPS_LESS_65_290 0 +#define HID_MPS_LESS_65_291 0 +#define HID_MPS_LESS_65_292 0 +#define HID_MPS_LESS_65_293 0 +#define HID_MPS_LESS_65_294 0 +#define HID_MPS_LESS_65_295 0 +#define HID_MPS_LESS_65_296 0 +#define HID_MPS_LESS_65_297 0 +#define HID_MPS_LESS_65_298 0 +#define HID_MPS_LESS_65_299 0 +#define HID_MPS_LESS_65_300 0 +#define HID_MPS_LESS_65_301 0 +#define HID_MPS_LESS_65_302 0 +#define HID_MPS_LESS_65_303 0 +#define HID_MPS_LESS_65_304 0 +#define HID_MPS_LESS_65_305 0 +#define HID_MPS_LESS_65_306 0 +#define HID_MPS_LESS_65_307 0 +#define HID_MPS_LESS_65_308 0 +#define HID_MPS_LESS_65_309 0 +#define HID_MPS_LESS_65_310 0 +#define HID_MPS_LESS_65_311 0 +#define HID_MPS_LESS_65_312 0 +#define HID_MPS_LESS_65_313 0 +#define HID_MPS_LESS_65_314 0 +#define HID_MPS_LESS_65_315 0 +#define HID_MPS_LESS_65_316 0 +#define HID_MPS_LESS_65_317 0 +#define HID_MPS_LESS_65_318 0 +#define HID_MPS_LESS_65_319 0 +#define HID_MPS_LESS_65_320 0 +#define HID_MPS_LESS_65_321 0 +#define HID_MPS_LESS_65_322 0 +#define HID_MPS_LESS_65_323 0 +#define HID_MPS_LESS_65_324 0 +#define HID_MPS_LESS_65_325 0 +#define HID_MPS_LESS_65_326 0 +#define HID_MPS_LESS_65_327 0 +#define HID_MPS_LESS_65_328 0 +#define HID_MPS_LESS_65_329 0 +#define HID_MPS_LESS_65_330 0 +#define HID_MPS_LESS_65_331 0 +#define HID_MPS_LESS_65_332 0 +#define HID_MPS_LESS_65_333 0 +#define HID_MPS_LESS_65_334 0 +#define HID_MPS_LESS_65_335 0 +#define HID_MPS_LESS_65_336 0 +#define HID_MPS_LESS_65_337 0 +#define HID_MPS_LESS_65_338 0 +#define HID_MPS_LESS_65_339 0 +#define HID_MPS_LESS_65_340 0 +#define HID_MPS_LESS_65_341 0 +#define HID_MPS_LESS_65_342 0 +#define HID_MPS_LESS_65_343 0 +#define HID_MPS_LESS_65_344 0 +#define HID_MPS_LESS_65_345 0 +#define HID_MPS_LESS_65_346 0 +#define HID_MPS_LESS_65_347 0 +#define HID_MPS_LESS_65_348 0 +#define HID_MPS_LESS_65_349 0 +#define HID_MPS_LESS_65_350 0 +#define HID_MPS_LESS_65_351 0 +#define HID_MPS_LESS_65_352 0 +#define HID_MPS_LESS_65_353 0 +#define HID_MPS_LESS_65_354 0 +#define HID_MPS_LESS_65_355 0 +#define HID_MPS_LESS_65_356 0 +#define HID_MPS_LESS_65_357 0 +#define HID_MPS_LESS_65_358 0 +#define HID_MPS_LESS_65_359 0 +#define HID_MPS_LESS_65_360 0 +#define HID_MPS_LESS_65_361 0 +#define HID_MPS_LESS_65_362 0 +#define HID_MPS_LESS_65_363 0 +#define HID_MPS_LESS_65_364 0 +#define HID_MPS_LESS_65_365 0 +#define HID_MPS_LESS_65_366 0 +#define HID_MPS_LESS_65_367 0 +#define HID_MPS_LESS_65_368 0 +#define HID_MPS_LESS_65_369 0 +#define HID_MPS_LESS_65_370 0 +#define HID_MPS_LESS_65_371 0 +#define HID_MPS_LESS_65_372 0 +#define HID_MPS_LESS_65_373 0 +#define HID_MPS_LESS_65_374 0 +#define HID_MPS_LESS_65_375 0 +#define HID_MPS_LESS_65_376 0 +#define HID_MPS_LESS_65_377 0 +#define HID_MPS_LESS_65_378 0 +#define HID_MPS_LESS_65_379 0 +#define HID_MPS_LESS_65_380 0 +#define HID_MPS_LESS_65_381 0 +#define HID_MPS_LESS_65_382 0 +#define HID_MPS_LESS_65_383 0 +#define HID_MPS_LESS_65_384 0 +#define HID_MPS_LESS_65_385 0 +#define HID_MPS_LESS_65_386 0 +#define HID_MPS_LESS_65_387 0 +#define HID_MPS_LESS_65_388 0 +#define HID_MPS_LESS_65_389 0 +#define HID_MPS_LESS_65_390 0 +#define HID_MPS_LESS_65_391 0 +#define HID_MPS_LESS_65_392 0 +#define HID_MPS_LESS_65_393 0 +#define HID_MPS_LESS_65_394 0 +#define HID_MPS_LESS_65_395 0 +#define HID_MPS_LESS_65_396 0 +#define HID_MPS_LESS_65_397 0 +#define HID_MPS_LESS_65_398 0 +#define HID_MPS_LESS_65_399 0 +#define HID_MPS_LESS_65_400 0 +#define HID_MPS_LESS_65_401 0 +#define HID_MPS_LESS_65_402 0 +#define HID_MPS_LESS_65_403 0 +#define HID_MPS_LESS_65_404 0 +#define HID_MPS_LESS_65_405 0 +#define HID_MPS_LESS_65_406 0 +#define HID_MPS_LESS_65_407 0 +#define HID_MPS_LESS_65_408 0 +#define HID_MPS_LESS_65_409 0 +#define HID_MPS_LESS_65_410 0 +#define HID_MPS_LESS_65_411 0 +#define HID_MPS_LESS_65_412 0 +#define HID_MPS_LESS_65_413 0 +#define HID_MPS_LESS_65_414 0 +#define HID_MPS_LESS_65_415 0 +#define HID_MPS_LESS_65_416 0 +#define HID_MPS_LESS_65_417 0 +#define HID_MPS_LESS_65_418 0 +#define HID_MPS_LESS_65_419 0 +#define HID_MPS_LESS_65_420 0 +#define HID_MPS_LESS_65_421 0 +#define HID_MPS_LESS_65_422 0 +#define HID_MPS_LESS_65_423 0 +#define HID_MPS_LESS_65_424 0 +#define HID_MPS_LESS_65_425 0 +#define HID_MPS_LESS_65_426 0 +#define HID_MPS_LESS_65_427 0 +#define HID_MPS_LESS_65_428 0 +#define HID_MPS_LESS_65_429 0 +#define HID_MPS_LESS_65_430 0 +#define HID_MPS_LESS_65_431 0 +#define HID_MPS_LESS_65_432 0 +#define HID_MPS_LESS_65_433 0 +#define HID_MPS_LESS_65_434 0 +#define HID_MPS_LESS_65_435 0 +#define HID_MPS_LESS_65_436 0 +#define HID_MPS_LESS_65_437 0 +#define HID_MPS_LESS_65_438 0 +#define HID_MPS_LESS_65_439 0 +#define HID_MPS_LESS_65_440 0 +#define HID_MPS_LESS_65_441 0 +#define HID_MPS_LESS_65_442 0 +#define HID_MPS_LESS_65_443 0 +#define HID_MPS_LESS_65_444 0 +#define HID_MPS_LESS_65_445 0 +#define HID_MPS_LESS_65_446 0 +#define HID_MPS_LESS_65_447 0 +#define HID_MPS_LESS_65_448 0 +#define HID_MPS_LESS_65_449 0 +#define HID_MPS_LESS_65_450 0 +#define HID_MPS_LESS_65_451 0 +#define HID_MPS_LESS_65_452 0 +#define HID_MPS_LESS_65_453 0 +#define HID_MPS_LESS_65_454 0 +#define HID_MPS_LESS_65_455 0 +#define HID_MPS_LESS_65_456 0 +#define HID_MPS_LESS_65_457 0 +#define HID_MPS_LESS_65_458 0 +#define HID_MPS_LESS_65_459 0 +#define HID_MPS_LESS_65_460 0 +#define HID_MPS_LESS_65_461 0 +#define HID_MPS_LESS_65_462 0 +#define HID_MPS_LESS_65_463 0 +#define HID_MPS_LESS_65_464 0 +#define HID_MPS_LESS_65_465 0 +#define HID_MPS_LESS_65_466 0 +#define HID_MPS_LESS_65_467 0 +#define HID_MPS_LESS_65_468 0 +#define HID_MPS_LESS_65_469 0 +#define HID_MPS_LESS_65_470 0 +#define HID_MPS_LESS_65_471 0 +#define HID_MPS_LESS_65_472 0 +#define HID_MPS_LESS_65_473 0 +#define HID_MPS_LESS_65_474 0 +#define HID_MPS_LESS_65_475 0 +#define HID_MPS_LESS_65_476 0 +#define HID_MPS_LESS_65_477 0 +#define HID_MPS_LESS_65_478 0 +#define HID_MPS_LESS_65_479 0 +#define HID_MPS_LESS_65_480 0 +#define HID_MPS_LESS_65_481 0 +#define HID_MPS_LESS_65_482 0 +#define HID_MPS_LESS_65_483 0 +#define HID_MPS_LESS_65_484 0 +#define HID_MPS_LESS_65_485 0 +#define HID_MPS_LESS_65_486 0 +#define HID_MPS_LESS_65_487 0 +#define HID_MPS_LESS_65_488 0 +#define HID_MPS_LESS_65_489 0 +#define HID_MPS_LESS_65_490 0 +#define HID_MPS_LESS_65_491 0 +#define HID_MPS_LESS_65_492 0 +#define HID_MPS_LESS_65_493 0 +#define HID_MPS_LESS_65_494 0 +#define HID_MPS_LESS_65_495 0 +#define HID_MPS_LESS_65_496 0 +#define HID_MPS_LESS_65_497 0 +#define HID_MPS_LESS_65_498 0 +#define HID_MPS_LESS_65_499 0 +#define HID_MPS_LESS_65_500 0 +#define HID_MPS_LESS_65_501 0 +#define HID_MPS_LESS_65_502 0 +#define HID_MPS_LESS_65_503 0 +#define HID_MPS_LESS_65_504 0 +#define HID_MPS_LESS_65_505 0 +#define HID_MPS_LESS_65_506 0 +#define HID_MPS_LESS_65_507 0 +#define HID_MPS_LESS_65_508 0 +#define HID_MPS_LESS_65_509 0 +#define HID_MPS_LESS_65_510 0 +#define HID_MPS_LESS_65_511 0 +#define HID_MPS_LESS_65_512 0 +#define HID_MPS_LESS_65_513 0 +#define HID_MPS_LESS_65_514 0 +#define HID_MPS_LESS_65_515 0 +#define HID_MPS_LESS_65_516 0 +#define HID_MPS_LESS_65_517 0 +#define HID_MPS_LESS_65_518 0 +#define HID_MPS_LESS_65_519 0 +#define HID_MPS_LESS_65_520 0 +#define HID_MPS_LESS_65_521 0 +#define HID_MPS_LESS_65_522 0 +#define HID_MPS_LESS_65_523 0 +#define HID_MPS_LESS_65_524 0 +#define HID_MPS_LESS_65_525 0 +#define HID_MPS_LESS_65_526 0 +#define HID_MPS_LESS_65_527 0 +#define HID_MPS_LESS_65_528 0 +#define HID_MPS_LESS_65_529 0 +#define HID_MPS_LESS_65_530 0 +#define HID_MPS_LESS_65_531 0 +#define HID_MPS_LESS_65_532 0 +#define HID_MPS_LESS_65_533 0 +#define HID_MPS_LESS_65_534 0 +#define HID_MPS_LESS_65_535 0 +#define HID_MPS_LESS_65_536 0 +#define HID_MPS_LESS_65_537 0 +#define HID_MPS_LESS_65_538 0 +#define HID_MPS_LESS_65_539 0 +#define HID_MPS_LESS_65_540 0 +#define HID_MPS_LESS_65_541 0 +#define HID_MPS_LESS_65_542 0 +#define HID_MPS_LESS_65_543 0 +#define HID_MPS_LESS_65_544 0 +#define HID_MPS_LESS_65_545 0 +#define HID_MPS_LESS_65_546 0 +#define HID_MPS_LESS_65_547 0 +#define HID_MPS_LESS_65_548 0 +#define HID_MPS_LESS_65_549 0 +#define HID_MPS_LESS_65_550 0 +#define HID_MPS_LESS_65_551 0 +#define HID_MPS_LESS_65_552 0 +#define HID_MPS_LESS_65_553 0 +#define HID_MPS_LESS_65_554 0 +#define HID_MPS_LESS_65_555 0 +#define HID_MPS_LESS_65_556 0 +#define HID_MPS_LESS_65_557 0 +#define HID_MPS_LESS_65_558 0 +#define HID_MPS_LESS_65_559 0 +#define HID_MPS_LESS_65_560 0 +#define HID_MPS_LESS_65_561 0 +#define HID_MPS_LESS_65_562 0 +#define HID_MPS_LESS_65_563 0 +#define HID_MPS_LESS_65_564 0 +#define HID_MPS_LESS_65_565 0 +#define HID_MPS_LESS_65_566 0 +#define HID_MPS_LESS_65_567 0 +#define HID_MPS_LESS_65_568 0 +#define HID_MPS_LESS_65_569 0 +#define HID_MPS_LESS_65_570 0 +#define HID_MPS_LESS_65_571 0 +#define HID_MPS_LESS_65_572 0 +#define HID_MPS_LESS_65_573 0 +#define HID_MPS_LESS_65_574 0 +#define HID_MPS_LESS_65_575 0 +#define HID_MPS_LESS_65_576 0 +#define HID_MPS_LESS_65_577 0 +#define HID_MPS_LESS_65_578 0 +#define HID_MPS_LESS_65_579 0 +#define HID_MPS_LESS_65_580 0 +#define HID_MPS_LESS_65_581 0 +#define HID_MPS_LESS_65_582 0 +#define HID_MPS_LESS_65_583 0 +#define HID_MPS_LESS_65_584 0 +#define HID_MPS_LESS_65_585 0 +#define HID_MPS_LESS_65_586 0 +#define HID_MPS_LESS_65_587 0 +#define HID_MPS_LESS_65_588 0 +#define HID_MPS_LESS_65_589 0 +#define HID_MPS_LESS_65_590 0 +#define HID_MPS_LESS_65_591 0 +#define HID_MPS_LESS_65_592 0 +#define HID_MPS_LESS_65_593 0 +#define HID_MPS_LESS_65_594 0 +#define HID_MPS_LESS_65_595 0 +#define HID_MPS_LESS_65_596 0 +#define HID_MPS_LESS_65_597 0 +#define HID_MPS_LESS_65_598 0 +#define HID_MPS_LESS_65_599 0 +#define HID_MPS_LESS_65_600 0 +#define HID_MPS_LESS_65_601 0 +#define HID_MPS_LESS_65_602 0 +#define HID_MPS_LESS_65_603 0 +#define HID_MPS_LESS_65_604 0 +#define HID_MPS_LESS_65_605 0 +#define HID_MPS_LESS_65_606 0 +#define HID_MPS_LESS_65_607 0 +#define HID_MPS_LESS_65_608 0 +#define HID_MPS_LESS_65_609 0 +#define HID_MPS_LESS_65_610 0 +#define HID_MPS_LESS_65_611 0 +#define HID_MPS_LESS_65_612 0 +#define HID_MPS_LESS_65_613 0 +#define HID_MPS_LESS_65_614 0 +#define HID_MPS_LESS_65_615 0 +#define HID_MPS_LESS_65_616 0 +#define HID_MPS_LESS_65_617 0 +#define HID_MPS_LESS_65_618 0 +#define HID_MPS_LESS_65_619 0 +#define HID_MPS_LESS_65_620 0 +#define HID_MPS_LESS_65_621 0 +#define HID_MPS_LESS_65_622 0 +#define HID_MPS_LESS_65_623 0 +#define HID_MPS_LESS_65_624 0 +#define HID_MPS_LESS_65_625 0 +#define HID_MPS_LESS_65_626 0 +#define HID_MPS_LESS_65_627 0 +#define HID_MPS_LESS_65_628 0 +#define HID_MPS_LESS_65_629 0 +#define HID_MPS_LESS_65_630 0 +#define HID_MPS_LESS_65_631 0 +#define HID_MPS_LESS_65_632 0 +#define HID_MPS_LESS_65_633 0 +#define HID_MPS_LESS_65_634 0 +#define HID_MPS_LESS_65_635 0 +#define HID_MPS_LESS_65_636 0 +#define HID_MPS_LESS_65_637 0 +#define HID_MPS_LESS_65_638 0 +#define HID_MPS_LESS_65_639 0 +#define HID_MPS_LESS_65_640 0 +#define HID_MPS_LESS_65_641 0 +#define HID_MPS_LESS_65_642 0 +#define HID_MPS_LESS_65_643 0 +#define HID_MPS_LESS_65_644 0 +#define HID_MPS_LESS_65_645 0 +#define HID_MPS_LESS_65_646 0 +#define HID_MPS_LESS_65_647 0 +#define HID_MPS_LESS_65_648 0 +#define HID_MPS_LESS_65_649 0 +#define HID_MPS_LESS_65_650 0 +#define HID_MPS_LESS_65_651 0 +#define HID_MPS_LESS_65_652 0 +#define HID_MPS_LESS_65_653 0 +#define HID_MPS_LESS_65_654 0 +#define HID_MPS_LESS_65_655 0 +#define HID_MPS_LESS_65_656 0 +#define HID_MPS_LESS_65_657 0 +#define HID_MPS_LESS_65_658 0 +#define HID_MPS_LESS_65_659 0 +#define HID_MPS_LESS_65_660 0 +#define HID_MPS_LESS_65_661 0 +#define HID_MPS_LESS_65_662 0 +#define HID_MPS_LESS_65_663 0 +#define HID_MPS_LESS_65_664 0 +#define HID_MPS_LESS_65_665 0 +#define HID_MPS_LESS_65_666 0 +#define HID_MPS_LESS_65_667 0 +#define HID_MPS_LESS_65_668 0 +#define HID_MPS_LESS_65_669 0 +#define HID_MPS_LESS_65_670 0 +#define HID_MPS_LESS_65_671 0 +#define HID_MPS_LESS_65_672 0 +#define HID_MPS_LESS_65_673 0 +#define HID_MPS_LESS_65_674 0 +#define HID_MPS_LESS_65_675 0 +#define HID_MPS_LESS_65_676 0 +#define HID_MPS_LESS_65_677 0 +#define HID_MPS_LESS_65_678 0 +#define HID_MPS_LESS_65_679 0 +#define HID_MPS_LESS_65_680 0 +#define HID_MPS_LESS_65_681 0 +#define HID_MPS_LESS_65_682 0 +#define HID_MPS_LESS_65_683 0 +#define HID_MPS_LESS_65_684 0 +#define HID_MPS_LESS_65_685 0 +#define HID_MPS_LESS_65_686 0 +#define HID_MPS_LESS_65_687 0 +#define HID_MPS_LESS_65_688 0 +#define HID_MPS_LESS_65_689 0 +#define HID_MPS_LESS_65_690 0 +#define HID_MPS_LESS_65_691 0 +#define HID_MPS_LESS_65_692 0 +#define HID_MPS_LESS_65_693 0 +#define HID_MPS_LESS_65_694 0 +#define HID_MPS_LESS_65_695 0 +#define HID_MPS_LESS_65_696 0 +#define HID_MPS_LESS_65_697 0 +#define HID_MPS_LESS_65_698 0 +#define HID_MPS_LESS_65_699 0 +#define HID_MPS_LESS_65_700 0 +#define HID_MPS_LESS_65_701 0 +#define HID_MPS_LESS_65_702 0 +#define HID_MPS_LESS_65_703 0 +#define HID_MPS_LESS_65_704 0 +#define HID_MPS_LESS_65_705 0 +#define HID_MPS_LESS_65_706 0 +#define HID_MPS_LESS_65_707 0 +#define HID_MPS_LESS_65_708 0 +#define HID_MPS_LESS_65_709 0 +#define HID_MPS_LESS_65_710 0 +#define HID_MPS_LESS_65_711 0 +#define HID_MPS_LESS_65_712 0 +#define HID_MPS_LESS_65_713 0 +#define HID_MPS_LESS_65_714 0 +#define HID_MPS_LESS_65_715 0 +#define HID_MPS_LESS_65_716 0 +#define HID_MPS_LESS_65_717 0 +#define HID_MPS_LESS_65_718 0 +#define HID_MPS_LESS_65_719 0 +#define HID_MPS_LESS_65_720 0 +#define HID_MPS_LESS_65_721 0 +#define HID_MPS_LESS_65_722 0 +#define HID_MPS_LESS_65_723 0 +#define HID_MPS_LESS_65_724 0 +#define HID_MPS_LESS_65_725 0 +#define HID_MPS_LESS_65_726 0 +#define HID_MPS_LESS_65_727 0 +#define HID_MPS_LESS_65_728 0 +#define HID_MPS_LESS_65_729 0 +#define HID_MPS_LESS_65_730 0 +#define HID_MPS_LESS_65_731 0 +#define HID_MPS_LESS_65_732 0 +#define HID_MPS_LESS_65_733 0 +#define HID_MPS_LESS_65_734 0 +#define HID_MPS_LESS_65_735 0 +#define HID_MPS_LESS_65_736 0 +#define HID_MPS_LESS_65_737 0 +#define HID_MPS_LESS_65_738 0 +#define HID_MPS_LESS_65_739 0 +#define HID_MPS_LESS_65_740 0 +#define HID_MPS_LESS_65_741 0 +#define HID_MPS_LESS_65_742 0 +#define HID_MPS_LESS_65_743 0 +#define HID_MPS_LESS_65_744 0 +#define HID_MPS_LESS_65_745 0 +#define HID_MPS_LESS_65_746 0 +#define HID_MPS_LESS_65_747 0 +#define HID_MPS_LESS_65_748 0 +#define HID_MPS_LESS_65_749 0 +#define HID_MPS_LESS_65_750 0 +#define HID_MPS_LESS_65_751 0 +#define HID_MPS_LESS_65_752 0 +#define HID_MPS_LESS_65_753 0 +#define HID_MPS_LESS_65_754 0 +#define HID_MPS_LESS_65_755 0 +#define HID_MPS_LESS_65_756 0 +#define HID_MPS_LESS_65_757 0 +#define HID_MPS_LESS_65_758 0 +#define HID_MPS_LESS_65_759 0 +#define HID_MPS_LESS_65_760 0 +#define HID_MPS_LESS_65_761 0 +#define HID_MPS_LESS_65_762 0 +#define HID_MPS_LESS_65_763 0 +#define HID_MPS_LESS_65_764 0 +#define HID_MPS_LESS_65_765 0 +#define HID_MPS_LESS_65_766 0 +#define HID_MPS_LESS_65_767 0 +#define HID_MPS_LESS_65_768 0 +#define HID_MPS_LESS_65_769 0 +#define HID_MPS_LESS_65_770 0 +#define HID_MPS_LESS_65_771 0 +#define HID_MPS_LESS_65_772 0 +#define HID_MPS_LESS_65_773 0 +#define HID_MPS_LESS_65_774 0 +#define HID_MPS_LESS_65_775 0 +#define HID_MPS_LESS_65_776 0 +#define HID_MPS_LESS_65_777 0 +#define HID_MPS_LESS_65_778 0 +#define HID_MPS_LESS_65_779 0 +#define HID_MPS_LESS_65_780 0 +#define HID_MPS_LESS_65_781 0 +#define HID_MPS_LESS_65_782 0 +#define HID_MPS_LESS_65_783 0 +#define HID_MPS_LESS_65_784 0 +#define HID_MPS_LESS_65_785 0 +#define HID_MPS_LESS_65_786 0 +#define HID_MPS_LESS_65_787 0 +#define HID_MPS_LESS_65_788 0 +#define HID_MPS_LESS_65_789 0 +#define HID_MPS_LESS_65_790 0 +#define HID_MPS_LESS_65_791 0 +#define HID_MPS_LESS_65_792 0 +#define HID_MPS_LESS_65_793 0 +#define HID_MPS_LESS_65_794 0 +#define HID_MPS_LESS_65_795 0 +#define HID_MPS_LESS_65_796 0 +#define HID_MPS_LESS_65_797 0 +#define HID_MPS_LESS_65_798 0 +#define HID_MPS_LESS_65_799 0 +#define HID_MPS_LESS_65_800 0 +#define HID_MPS_LESS_65_801 0 +#define HID_MPS_LESS_65_802 0 +#define HID_MPS_LESS_65_803 0 +#define HID_MPS_LESS_65_804 0 +#define HID_MPS_LESS_65_805 0 +#define HID_MPS_LESS_65_806 0 +#define HID_MPS_LESS_65_807 0 +#define HID_MPS_LESS_65_808 0 +#define HID_MPS_LESS_65_809 0 +#define HID_MPS_LESS_65_810 0 +#define HID_MPS_LESS_65_811 0 +#define HID_MPS_LESS_65_812 0 +#define HID_MPS_LESS_65_813 0 +#define HID_MPS_LESS_65_814 0 +#define HID_MPS_LESS_65_815 0 +#define HID_MPS_LESS_65_816 0 +#define HID_MPS_LESS_65_817 0 +#define HID_MPS_LESS_65_818 0 +#define HID_MPS_LESS_65_819 0 +#define HID_MPS_LESS_65_820 0 +#define HID_MPS_LESS_65_821 0 +#define HID_MPS_LESS_65_822 0 +#define HID_MPS_LESS_65_823 0 +#define HID_MPS_LESS_65_824 0 +#define HID_MPS_LESS_65_825 0 +#define HID_MPS_LESS_65_826 0 +#define HID_MPS_LESS_65_827 0 +#define HID_MPS_LESS_65_828 0 +#define HID_MPS_LESS_65_829 0 +#define HID_MPS_LESS_65_830 0 +#define HID_MPS_LESS_65_831 0 +#define HID_MPS_LESS_65_832 0 +#define HID_MPS_LESS_65_833 0 +#define HID_MPS_LESS_65_834 0 +#define HID_MPS_LESS_65_835 0 +#define HID_MPS_LESS_65_836 0 +#define HID_MPS_LESS_65_837 0 +#define HID_MPS_LESS_65_838 0 +#define HID_MPS_LESS_65_839 0 +#define HID_MPS_LESS_65_840 0 +#define HID_MPS_LESS_65_841 0 +#define HID_MPS_LESS_65_842 0 +#define HID_MPS_LESS_65_843 0 +#define HID_MPS_LESS_65_844 0 +#define HID_MPS_LESS_65_845 0 +#define HID_MPS_LESS_65_846 0 +#define HID_MPS_LESS_65_847 0 +#define HID_MPS_LESS_65_848 0 +#define HID_MPS_LESS_65_849 0 +#define HID_MPS_LESS_65_850 0 +#define HID_MPS_LESS_65_851 0 +#define HID_MPS_LESS_65_852 0 +#define HID_MPS_LESS_65_853 0 +#define HID_MPS_LESS_65_854 0 +#define HID_MPS_LESS_65_855 0 +#define HID_MPS_LESS_65_856 0 +#define HID_MPS_LESS_65_857 0 +#define HID_MPS_LESS_65_858 0 +#define HID_MPS_LESS_65_859 0 +#define HID_MPS_LESS_65_860 0 +#define HID_MPS_LESS_65_861 0 +#define HID_MPS_LESS_65_862 0 +#define HID_MPS_LESS_65_863 0 +#define HID_MPS_LESS_65_864 0 +#define HID_MPS_LESS_65_865 0 +#define HID_MPS_LESS_65_866 0 +#define HID_MPS_LESS_65_867 0 +#define HID_MPS_LESS_65_868 0 +#define HID_MPS_LESS_65_869 0 +#define HID_MPS_LESS_65_870 0 +#define HID_MPS_LESS_65_871 0 +#define HID_MPS_LESS_65_872 0 +#define HID_MPS_LESS_65_873 0 +#define HID_MPS_LESS_65_874 0 +#define HID_MPS_LESS_65_875 0 +#define HID_MPS_LESS_65_876 0 +#define HID_MPS_LESS_65_877 0 +#define HID_MPS_LESS_65_878 0 +#define HID_MPS_LESS_65_879 0 +#define HID_MPS_LESS_65_880 0 +#define HID_MPS_LESS_65_881 0 +#define HID_MPS_LESS_65_882 0 +#define HID_MPS_LESS_65_883 0 +#define HID_MPS_LESS_65_884 0 +#define HID_MPS_LESS_65_885 0 +#define HID_MPS_LESS_65_886 0 +#define HID_MPS_LESS_65_887 0 +#define HID_MPS_LESS_65_888 0 +#define HID_MPS_LESS_65_889 0 +#define HID_MPS_LESS_65_890 0 +#define HID_MPS_LESS_65_891 0 +#define HID_MPS_LESS_65_892 0 +#define HID_MPS_LESS_65_893 0 +#define HID_MPS_LESS_65_894 0 +#define HID_MPS_LESS_65_895 0 +#define HID_MPS_LESS_65_896 0 +#define HID_MPS_LESS_65_897 0 +#define HID_MPS_LESS_65_898 0 +#define HID_MPS_LESS_65_899 0 +#define HID_MPS_LESS_65_900 0 +#define HID_MPS_LESS_65_901 0 +#define HID_MPS_LESS_65_902 0 +#define HID_MPS_LESS_65_903 0 +#define HID_MPS_LESS_65_904 0 +#define HID_MPS_LESS_65_905 0 +#define HID_MPS_LESS_65_906 0 +#define HID_MPS_LESS_65_907 0 +#define HID_MPS_LESS_65_908 0 +#define HID_MPS_LESS_65_909 0 +#define HID_MPS_LESS_65_910 0 +#define HID_MPS_LESS_65_911 0 +#define HID_MPS_LESS_65_912 0 +#define HID_MPS_LESS_65_913 0 +#define HID_MPS_LESS_65_914 0 +#define HID_MPS_LESS_65_915 0 +#define HID_MPS_LESS_65_916 0 +#define HID_MPS_LESS_65_917 0 +#define HID_MPS_LESS_65_918 0 +#define HID_MPS_LESS_65_919 0 +#define HID_MPS_LESS_65_920 0 +#define HID_MPS_LESS_65_921 0 +#define HID_MPS_LESS_65_922 0 +#define HID_MPS_LESS_65_923 0 +#define HID_MPS_LESS_65_924 0 +#define HID_MPS_LESS_65_925 0 +#define HID_MPS_LESS_65_926 0 +#define HID_MPS_LESS_65_927 0 +#define HID_MPS_LESS_65_928 0 +#define HID_MPS_LESS_65_929 0 +#define HID_MPS_LESS_65_930 0 +#define HID_MPS_LESS_65_931 0 +#define HID_MPS_LESS_65_932 0 +#define HID_MPS_LESS_65_933 0 +#define HID_MPS_LESS_65_934 0 +#define HID_MPS_LESS_65_935 0 +#define HID_MPS_LESS_65_936 0 +#define HID_MPS_LESS_65_937 0 +#define HID_MPS_LESS_65_938 0 +#define HID_MPS_LESS_65_939 0 +#define HID_MPS_LESS_65_940 0 +#define HID_MPS_LESS_65_941 0 +#define HID_MPS_LESS_65_942 0 +#define HID_MPS_LESS_65_943 0 +#define HID_MPS_LESS_65_944 0 +#define HID_MPS_LESS_65_945 0 +#define HID_MPS_LESS_65_946 0 +#define HID_MPS_LESS_65_947 0 +#define HID_MPS_LESS_65_948 0 +#define HID_MPS_LESS_65_949 0 +#define HID_MPS_LESS_65_950 0 +#define HID_MPS_LESS_65_951 0 +#define HID_MPS_LESS_65_952 0 +#define HID_MPS_LESS_65_953 0 +#define HID_MPS_LESS_65_954 0 +#define HID_MPS_LESS_65_955 0 +#define HID_MPS_LESS_65_956 0 +#define HID_MPS_LESS_65_957 0 +#define HID_MPS_LESS_65_958 0 +#define HID_MPS_LESS_65_959 0 +#define HID_MPS_LESS_65_960 0 +#define HID_MPS_LESS_65_961 0 +#define HID_MPS_LESS_65_962 0 +#define HID_MPS_LESS_65_963 0 +#define HID_MPS_LESS_65_964 0 +#define HID_MPS_LESS_65_965 0 +#define HID_MPS_LESS_65_966 0 +#define HID_MPS_LESS_65_967 0 +#define HID_MPS_LESS_65_968 0 +#define HID_MPS_LESS_65_969 0 +#define HID_MPS_LESS_65_970 0 +#define HID_MPS_LESS_65_971 0 +#define HID_MPS_LESS_65_972 0 +#define HID_MPS_LESS_65_973 0 +#define HID_MPS_LESS_65_974 0 +#define HID_MPS_LESS_65_975 0 +#define HID_MPS_LESS_65_976 0 +#define HID_MPS_LESS_65_977 0 +#define HID_MPS_LESS_65_978 0 +#define HID_MPS_LESS_65_979 0 +#define HID_MPS_LESS_65_980 0 +#define HID_MPS_LESS_65_981 0 +#define HID_MPS_LESS_65_982 0 +#define HID_MPS_LESS_65_983 0 +#define HID_MPS_LESS_65_984 0 +#define HID_MPS_LESS_65_985 0 +#define HID_MPS_LESS_65_986 0 +#define HID_MPS_LESS_65_987 0 +#define HID_MPS_LESS_65_988 0 +#define HID_MPS_LESS_65_989 0 +#define HID_MPS_LESS_65_990 0 +#define HID_MPS_LESS_65_991 0 +#define HID_MPS_LESS_65_992 0 +#define HID_MPS_LESS_65_993 0 +#define HID_MPS_LESS_65_994 0 +#define HID_MPS_LESS_65_995 0 +#define HID_MPS_LESS_65_996 0 +#define HID_MPS_LESS_65_997 0 +#define HID_MPS_LESS_65_998 0 +#define HID_MPS_LESS_65_999 0 +#define HID_MPS_LESS_65_1000 0 +#define HID_MPS_LESS_65_1001 0 +#define HID_MPS_LESS_65_1002 0 +#define HID_MPS_LESS_65_1003 0 +#define HID_MPS_LESS_65_1004 0 +#define HID_MPS_LESS_65_1005 0 +#define HID_MPS_LESS_65_1006 0 +#define HID_MPS_LESS_65_1007 0 +#define HID_MPS_LESS_65_1008 0 +#define HID_MPS_LESS_65_1009 0 +#define HID_MPS_LESS_65_1010 0 +#define HID_MPS_LESS_65_1011 0 +#define HID_MPS_LESS_65_1012 0 +#define HID_MPS_LESS_65_1013 0 +#define HID_MPS_LESS_65_1014 0 +#define HID_MPS_LESS_65_1015 0 +#define HID_MPS_LESS_65_1016 0 +#define HID_MPS_LESS_65_1017 0 +#define HID_MPS_LESS_65_1018 0 +#define HID_MPS_LESS_65_1019 0 +#define HID_MPS_LESS_65_1020 0 +#define HID_MPS_LESS_65_1021 0 +#define HID_MPS_LESS_65_1022 0 +#define HID_MPS_LESS_65_1023 0 +#define HID_MPS_LESS_65_1024 0 + +#define HID_MPS_LESS_65(x) UTIL_PRIMITIVE_CAT(HID_MPS_LESS_65_, x) + +/* + * If all the endpoint MPS are less than 65 bytes, we do not need to define and + * configure an alternate interface. + */ +#define HID_ALL_MPS_LESS_65(n) \ + UTIL_AND(HID_MPS_LESS_65(DT_INST_PROP(n, out_report_size)), \ + HID_MPS_LESS_65(DT_INST_PROP(n, in_report_size))) + +/* Get IN endpoint polling rate based on the desired speed. */ +#define HID_IN_EP_INTERVAL(n, hs) \ + COND_CODE_1(hs, \ + (USB_HS_INT_EP_INTERVAL(DT_INST_PROP(n, in_polling_rate))), \ + (USB_FS_INT_EP_INTERVAL(DT_INST_PROP(n, in_polling_rate)))) + +/* Get OUT endpoint polling rate based on the desired speed. */ +#define HID_OUT_EP_INTERVAL(n, hs) \ + COND_CODE_1(hs, \ + (USB_HS_INT_EP_INTERVAL(DT_INST_PROP(n, out_polling_rate))),\ + (USB_FS_INT_EP_INTERVAL(DT_INST_PROP(n, out_polling_rate)))) + +/* Get the number of endpoints, which can be either 1 or 2 */ +#define HID_NUM_ENDPOINTS(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), (2), (1)) + +/* + * Either the device does not support a boot protocol, or it supports the + * keyboard or mouse boot protocol. + */ +#define HID_INTERFACE_PROTOCOL(n) DT_INST_ENUM_IDX_OR(n, protocol_code, 0) + +/* bInterfaceSubClass must be set to 1 if a boot device protocol is supported */ +#define HID_INTERFACE_SUBCLASS(n) \ + COND_CODE_0(HID_INTERFACE_PROTOCOL(n), (0), (1)) + +#define HID_INTERFACE_DEFINE(n, alt) \ + { \ + .bLength = sizeof(struct usb_if_descriptor), \ + .bDescriptorType = USB_DESC_INTERFACE, \ + .bInterfaceNumber = 0, \ + .bAlternateSetting = alt, \ + .bNumEndpoints = HID_NUM_ENDPOINTS(n), \ + .bInterfaceClass = USB_BCC_HID, \ + .bInterfaceSubClass = HID_INTERFACE_SUBCLASS(n), \ + .bInterfaceProtocol = HID_INTERFACE_PROTOCOL(n), \ + .iInterface = 0, \ + } + +#define HID_DESCRIPTOR_DEFINE(n) \ + { \ + .bLength = sizeof(struct hid_descriptor), \ + .bDescriptorType = USB_DESC_HID, \ + .bcdHID = sys_cpu_to_le16(USB_HID_VERSION), \ + .bCountryCode = 0, \ + .bNumDescriptors = HID_SUBORDINATE_DESC_NUM, \ + .sub[0] = { \ + .bDescriptorType = USB_DESC_HID_REPORT, \ + .wDescriptorLength = 0, \ + }, \ + } \ + +/* + * OUT endpoint MPS for either default or alternate interface. + * MPS for the default interface is always limited to 64 bytes. + */ +#define HID_OUT_EP_MPS(n, alt) \ + COND_CODE_1(alt, \ + (sys_cpu_to_le16(DT_INST_PROP(n, out_report_size))), \ + (sys_cpu_to_le16(MIN(DT_INST_PROP(n, out_report_size), 64U)))) + +/* + * IN endpoint MPS for either default or alternate interface. + * MPS for the default interface is always limited to 64 bytes. + */ +#define HID_IN_EP_MPS(n, alt) \ + COND_CODE_1(alt, \ + (sys_cpu_to_le16(DT_INST_PROP(n, in_report_size))), \ + (sys_cpu_to_le16(MIN(DT_INST_PROP(n, in_report_size), 64U)))) + +#define HID_OUT_EP_DEFINE(n, hs, alt) \ + { \ + .bLength = sizeof(struct usb_ep_descriptor), \ + .bDescriptorType = USB_DESC_ENDPOINT, \ + .bEndpointAddress = 0x01, \ + .bmAttributes = USB_EP_TYPE_INTERRUPT, \ + .wMaxPacketSize = HID_OUT_EP_MPS(n, alt), \ + .bInterval = HID_OUT_EP_INTERVAL(n, hs), \ + } + +#define HID_IN_EP_DEFINE(n, hs, alt) \ + { \ + .bLength = sizeof(struct usb_ep_descriptor), \ + .bDescriptorType = USB_DESC_ENDPOINT, \ + .bEndpointAddress = 0x81, \ + .bmAttributes = USB_EP_TYPE_INTERRUPT, \ + .wMaxPacketSize = HID_IN_EP_MPS(n, alt), \ + .bInterval = HID_IN_EP_INTERVAL(n, hs), \ + } + +/* + * Both the optional OUT endpoint and the associated pool are only defined if + * there is an out-report-size property. + */ +#define HID_OUT_EP_DEFINE_OR_ZERO(n, hs, alt) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ + (HID_OUT_EP_DEFINE(n, hs, alt)), \ + ({0})) + +#define HID_OUT_POOL_DEFINE(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ + (NET_BUF_POOL_DEFINE(hid_buf_pool_out_##n, \ + CONFIG_USBD_HID_OUT_BUF_COUNT, \ + DT_INST_PROP(n, out_report_size), \ + sizeof(struct udc_buf_info), NULL)), \ + ()) + +#define HID_OUT_POOL_ADDR(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \ + (&hid_buf_pool_out_##n), (NULL)) + +#endif /* ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ */ From f3c6f9617350f73461a58e0b39dbc879be43d4bb Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0672/1389] samples: hid-mouse: add support for the new HID implementation Add support for the new HID implementation. Signed-off-by: Johann Fischer --- samples/subsys/usb/hid-mouse/CMakeLists.txt | 1 + samples/subsys/usb/hid-mouse/Kconfig | 9 +++++ samples/subsys/usb/hid-mouse/sample.yaml | 19 ++++++--- samples/subsys/usb/hid-mouse/src/main.c | 39 ++++++++++++++++++- .../subsys/usb/hid-mouse/usbd_next.overlay | 15 +++++++ .../subsys/usb/hid-mouse/usbd_next_prj.conf | 11 ++++++ 6 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 samples/subsys/usb/hid-mouse/Kconfig create mode 100644 samples/subsys/usb/hid-mouse/usbd_next.overlay create mode 100644 samples/subsys/usb/hid-mouse/usbd_next_prj.conf diff --git a/samples/subsys/usb/hid-mouse/CMakeLists.txt b/samples/subsys/usb/hid-mouse/CMakeLists.txt index d384859f9fce62..d2217c00a47277 100644 --- a/samples/subsys/usb/hid-mouse/CMakeLists.txt +++ b/samples/subsys/usb/hid-mouse/CMakeLists.txt @@ -4,5 +4,6 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(hid-mouse) +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/hid-mouse/Kconfig b/samples/subsys/usb/hid-mouse/Kconfig new file mode 100644 index 00000000000000..96c5455894806d --- /dev/null +++ b/samples/subsys/usb/hid-mouse/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Source common USB sample options used to initialize new experimental USB +# device stack. The scope of these options is limited to USB samples in project +# tree, you cannot use them in your own application. +source "samples/subsys/usb/common/Kconfig.sample_usbd" + +source "Kconfig.zephyr" diff --git a/samples/subsys/usb/hid-mouse/sample.yaml b/samples/subsys/usb/hid-mouse/sample.yaml index f638fefc58c21c..018c1a04b8021d 100644 --- a/samples/subsys/usb/hid-mouse/sample.yaml +++ b/samples/subsys/usb/hid-mouse/sample.yaml @@ -1,10 +1,19 @@ sample: name: USB HID mouse sample +common: + harness: button + filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + depends_on: + - usb_device + - gpio tests: sample.usb.hid-mouse: - depends_on: - - usb_device - - gpio - harness: button - filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + tags: usb + sample.usb_device_next.hid-mouse: + platform_allow: + - nrf52840dk/nrf52840 + - frdm_k64f + extra_args: + - CONF_FILE="usbd_next_prj.conf" + - EXTRA_DTC_OVERLAY_FILE="usbd_next.overlay" tags: usb diff --git a/samples/subsys/usb/hid-mouse/src/main.c b/samples/subsys/usb/hid-mouse/src/main.c index 6a297418b4cbb0..c42a96ed47408d 100644 --- a/samples/subsys/usb/hid-mouse/src/main.c +++ b/samples/subsys/usb/hid-mouse/src/main.c @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include #include @@ -14,6 +16,7 @@ #include #include +#include #include #include @@ -34,10 +37,10 @@ enum mouse_report_idx { MOUSE_REPORT_COUNT = 4, }; -static uint8_t report[MOUSE_REPORT_COUNT]; +static uint8_t __aligned(sizeof(void *)) report[MOUSE_REPORT_COUNT]; static K_SEM_DEFINE(report_sem, 0, 1); -static void status_cb(enum usb_dc_status_code status, const uint8_t *param) +static inline void status_cb(enum usb_dc_status_code status, const uint8_t *param) { usb_status = status; } @@ -93,6 +96,30 @@ static void input_cb(struct input_event *evt) INPUT_CALLBACK_DEFINE(NULL, input_cb); +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) +static int enable_usb_device_next(void) +{ + struct usbd_contex *sample_usbd; + int err; + + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; + } + + err = usbd_enable(sample_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return err; + } + + LOG_DBG("USB device support enabled"); + + return 0; +} +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK_NEXT) */ + int main(void) { const struct device *hid_dev; @@ -103,7 +130,11 @@ int main(void) return 0; } +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); +#else hid_dev = device_get_binding("HID_0"); +#endif if (hid_dev == NULL) { LOG_ERR("Cannot get USB HID Device"); return 0; @@ -121,7 +152,11 @@ int main(void) usb_hid_init(hid_dev); +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + ret = enable_usb_device_next(); +#else ret = usb_enable(status_cb); +#endif if (ret != 0) { LOG_ERR("Failed to enable USB"); return 0; diff --git a/samples/subsys/usb/hid-mouse/usbd_next.overlay b/samples/subsys/usb/hid-mouse/usbd_next.overlay new file mode 100644 index 00000000000000..8b7b5c5182139c --- /dev/null +++ b/samples/subsys/usb/hid-mouse/usbd_next.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + protocol-code = "none"; + in-polling-rate = <1000>; + in-report-size = <64>; + }; +}; diff --git a/samples/subsys/usb/hid-mouse/usbd_next_prj.conf b/samples/subsys/usb/hid-mouse/usbd_next_prj.conf new file mode 100644 index 00000000000000..9c8894b2126c6a --- /dev/null +++ b/samples/subsys/usb/hid-mouse/usbd_next_prj.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_HID_SUPPORT=y + +CONFIG_LOG=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_HID_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0007 + +CONFIG_GPIO=y +CONFIG_INPUT=y From bf5ee92ef2fe0a1b28eff1335e651cb0bed11507 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0673/1389] samples: usb: add HID keyboard sample Add HID keyboard sample for the new experimental USB device support. This is a limited and not fully compliant HID keyboard implementation. Signed-off-by: Johann Fischer --- .../subsys/usb/hid-keyboard/CMakeLists.txt | 9 + samples/subsys/usb/hid-keyboard/Kconfig | 9 + samples/subsys/usb/hid-keyboard/README.rst | 36 +++ samples/subsys/usb/hid-keyboard/app.overlay | 15 + .../usb/hid-keyboard/large_in_report.overlay | 14 + .../usb/hid-keyboard/large_out_report.overlay | 15 + .../usb/hid-keyboard/out_report.overlay | 15 + samples/subsys/usb/hid-keyboard/prj.conf | 12 + samples/subsys/usb/hid-keyboard/sample.yaml | 26 ++ samples/subsys/usb/hid-keyboard/src/main.c | 257 ++++++++++++++++++ 10 files changed, 408 insertions(+) create mode 100644 samples/subsys/usb/hid-keyboard/CMakeLists.txt create mode 100644 samples/subsys/usb/hid-keyboard/Kconfig create mode 100644 samples/subsys/usb/hid-keyboard/README.rst create mode 100644 samples/subsys/usb/hid-keyboard/app.overlay create mode 100644 samples/subsys/usb/hid-keyboard/large_in_report.overlay create mode 100644 samples/subsys/usb/hid-keyboard/large_out_report.overlay create mode 100644 samples/subsys/usb/hid-keyboard/out_report.overlay create mode 100644 samples/subsys/usb/hid-keyboard/prj.conf create mode 100644 samples/subsys/usb/hid-keyboard/sample.yaml create mode 100644 samples/subsys/usb/hid-keyboard/src/main.c diff --git a/samples/subsys/usb/hid-keyboard/CMakeLists.txt b/samples/subsys/usb/hid-keyboard/CMakeLists.txt new file mode 100644 index 00000000000000..76d18842cff3a0 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hid-keyboard) + +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/hid-keyboard/Kconfig b/samples/subsys/usb/hid-keyboard/Kconfig new file mode 100644 index 00000000000000..96c5455894806d --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Source common USB sample options used to initialize new experimental USB +# device stack. The scope of these options is limited to USB samples in project +# tree, you cannot use them in your own application. +source "samples/subsys/usb/common/Kconfig.sample_usbd" + +source "Kconfig.zephyr" diff --git a/samples/subsys/usb/hid-keyboard/README.rst b/samples/subsys/usb/hid-keyboard/README.rst new file mode 100644 index 00000000000000..b1936b55588684 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/README.rst @@ -0,0 +1,36 @@ +.. zephyr:code-sample:: usb-hid-keyboard + :name: USB HID keyboard + :relevant-api: usbd_api usbd_hid_class input_interface + + Implement a basic HID keyboard device. + +Overview +******** + +This sample application demonstrates the HID keyboard implementation using the +new experimental USB device stack. + +Requirements +************ + +This project requires an experimental USB device driver (UDC API) and uses the +:ref:`input` API. There must be a :dtcompatible:`gpio-keys` group of buttons +or keys defined at the board level that can generate input events. +At least one key is required and up to four can be used. The first three keys +are used for Num Lock, Caps Lock and Scroll Lock. The fourth key is used to +report HID keys 1, 2, 3 and the right Alt modifier at once. + +The example can use up to three LEDs, configured via the devicetree alias such +as ``led0``, to indicate the state of the keyboard LEDs. + +Building and Running +******************** + +This sample can be built for multiple boards, in this example we will build it +for the nRF52840DK board: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/hid-keyboard + :board: nrf52840dk/nrf52840 + :goals: build flash + :compact: diff --git a/samples/subsys/usb/hid-keyboard/app.overlay b/samples/subsys/usb/hid-keyboard/app.overlay new file mode 100644 index 00000000000000..6433abbe7061b6 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/app.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + protocol-code = "keyboard"; + in-report-size = <64>; + in-polling-rate = <1000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/large_in_report.overlay b/samples/subsys/usb/hid-keyboard/large_in_report.overlay new file mode 100644 index 00000000000000..2eb82c5df619ce --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/large_in_report.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + in-report-size = <256>; + in-polling-rate = <1000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/large_out_report.overlay b/samples/subsys/usb/hid-keyboard/large_out_report.overlay new file mode 100644 index 00000000000000..16b02a9efb0593 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/large_out_report.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "large_in_report.overlay" + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + out-report-size = <128>; + out-polling-rate = <16000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/out_report.overlay b/samples/subsys/usb/hid-keyboard/out_report.overlay new file mode 100644 index 00000000000000..bcd776622e843d --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/out_report.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "app.overlay" + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + out-report-size = <64>; + out-polling-rate = <16000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/prj.conf b/samples/subsys/usb/hid-keyboard/prj.conf new file mode 100644 index 00000000000000..04ce14ad588e1b --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/prj.conf @@ -0,0 +1,12 @@ +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_HID_SUPPORT=y + +CONFIG_LOG=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_HID_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0007 + +CONFIG_GPIO=y +CONFIG_INPUT=y +CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/samples/subsys/usb/hid-keyboard/sample.yaml b/samples/subsys/usb/hid-keyboard/sample.yaml new file mode 100644 index 00000000000000..daf6703b81a5dd --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/sample.yaml @@ -0,0 +1,26 @@ +sample: + name: USB HID keyboard sample +common: + harness: button + filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + depends_on: + - usb_device + - gpio + platform_allow: + - nrf52840dk/nrf52840 + - frdm_k64f +tests: + sample.usbd.hid-keyboard: + tags: usb + sample.usbd.hid-keyboard.out-report: + tags: usb + extra_args: + - EXTRA_DTC_OVERLAY_FILE="out_report.overlay" + sample.usbd.hid-keyboard.large-report: + tags: usb + extra_args: + - EXTRA_DTC_OVERLAY_FILE="large_in_report.overlay" + sample.usbd.hid-keyboard.large-out-report: + tags: usb + extra_args: + - EXTRA_DTC_OVERLAY_FILE="large_out_report.overlay" diff --git a/samples/subsys/usb/hid-keyboard/src/main.c b/samples/subsys/usb/hid-keyboard/src/main.c new file mode 100644 index 00000000000000..1a2a146a5a95c6 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/src/main.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); + +static const uint8_t hid_report_desc[] = HID_KEYBOARD_REPORT_DESC(); + +enum kb_leds_idx { + KB_LED_NUMLOCK = 0, + KB_LED_CAPSLOCK, + KB_LED_SCROLLLOCK, + KB_LED_COUNT, +}; + +static const struct gpio_dt_spec kb_leds[KB_LED_COUNT] = { + GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios, {0}), + GPIO_DT_SPEC_GET_OR(DT_ALIAS(led1), gpios, {0}), + GPIO_DT_SPEC_GET_OR(DT_ALIAS(led2), gpios, {0}), +}; + +enum kb_report_idx { + KB_MOD_KEY = 0, + KB_RESERVED, + KB_KEY_CODE1, + KB_KEY_CODE2, + KB_KEY_CODE3, + KB_KEY_CODE4, + KB_KEY_CODE5, + KB_KEY_CODE6, + KB_REPORT_COUNT, +}; + +struct kb_event { + uint16_t code; + int32_t value; +}; + +K_MSGQ_DEFINE(kb_msgq, sizeof(struct kb_event), 2, 1); + +static uint8_t __aligned(sizeof(void *)) report[KB_REPORT_COUNT]; +static uint32_t kb_duration; +static bool kb_ready; + +static void input_cb(struct input_event *evt) +{ + struct kb_event kb_evt; + + kb_evt.code = evt->code; + kb_evt.value = evt->value; + if (k_msgq_put(&kb_msgq, &kb_evt, K_NO_WAIT) != 0) { + LOG_ERR("Failed to put new input event"); + } +} + +INPUT_CALLBACK_DEFINE(NULL, input_cb); + +static void kb_iface_ready(const struct device *dev, const bool ready) +{ + LOG_INF("HID device %s interface is %s", + dev->name, ready ? "ready" : "not ready"); + kb_ready = ready; +} + +static int kb_get_report(const struct device *dev, + const uint8_t type, const uint8_t id, const uint16_t len, + uint8_t *const buf) +{ + LOG_WRN("Get Report not implemented, Type %u ID %u", type, id); + + return 0; +} + +static int kb_set_report(const struct device *dev, + const uint8_t type, const uint8_t id, const uint16_t len, + const uint8_t *const buf) +{ + if (type != HID_REPORT_TYPE_OUTPUT) { + LOG_WRN("Unsupported report type"); + return -ENOTSUP; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(kb_leds); i++) { + if (kb_leds[i].port == NULL) { + continue; + } + + (void)gpio_pin_set_dt(&kb_leds[i], buf[0] & BIT(i)); + } + + return 0; +} + +/* Idle duration is stored but not used to calculate idle reports. */ +static void kb_set_idle(const struct device *dev, + const uint8_t id, const uint32_t duration) +{ + LOG_INF("Set Idle %u to %u", id, duration); + kb_duration = duration; +} + +static uint32_t kb_get_idle(const struct device *dev, const uint8_t id) +{ + LOG_INF("Get Idle %u to %u", id, kb_duration); + return kb_duration; +} + +static void kb_set_protocol(const struct device *dev, const uint8_t proto) +{ + LOG_INF("Protocol changed to %s", + proto == 0U ? "Boot Protocol" : "Report Protocol"); +} + +static void kb_output_report(const struct device *dev, const uint16_t len, + const uint8_t *const buf) +{ + LOG_HEXDUMP_DBG(buf, len, "o.r."); + kb_set_report(dev, HID_REPORT_TYPE_OUTPUT, 0U, len, buf); +} + +struct hid_device_ops kb_ops = { + .iface_ready = kb_iface_ready, + .get_report = kb_get_report, + .set_report = kb_set_report, + .set_idle = kb_set_idle, + .get_idle = kb_get_idle, + .set_protocol = kb_set_protocol, + .output_report = kb_output_report, +}; + +int main(void) +{ + struct usbd_contex *sample_usbd; + const struct device *hid_dev; + int ret; + + for (unsigned int i = 0; i < ARRAY_SIZE(kb_leds); i++) { + if (kb_leds[i].port == NULL) { + continue; + } + + if (!gpio_is_ready_dt(&kb_leds[i])) { + LOG_ERR("LED device %s is not ready", kb_leds[i].port->name); + return -EIO; + } + + ret = gpio_pin_configure_dt(&kb_leds[i], GPIO_OUTPUT_INACTIVE); + if (ret != 0) { + LOG_ERR("Failed to configure the LED pin, %d", ret); + return -EIO; + } + } + + hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); + if (!device_is_ready(hid_dev)) { + LOG_ERR("HID Device is not ready"); + return -EIO; + } + + ret = hid_device_register(hid_dev, + hid_report_desc, sizeof(hid_report_desc), + &kb_ops); + if (ret != 0) { + LOG_ERR("Failed to register HID Device, %d", ret); + return ret; + } + + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; + } + + ret = usbd_enable(sample_usbd); + if (ret) { + LOG_ERR("Failed to enable device support"); + return ret; + } + + LOG_INF("HID keyboard sample is initialized"); + + while (true) { + struct kb_event kb_evt; + + k_msgq_get(&kb_msgq, &kb_evt, K_FOREVER); + + switch (kb_evt.code) { + case INPUT_KEY_0: + if (kb_evt.value) { + report[KB_KEY_CODE1] = HID_KEY_NUMLOCK; + } else { + report[KB_KEY_CODE1] = 0; + } + + break; + case INPUT_KEY_1: + if (kb_evt.value) { + report[KB_KEY_CODE2] = HID_KEY_CAPSLOCK; + } else { + report[KB_KEY_CODE2] = 0; + } + + break; + case INPUT_KEY_2: + if (kb_evt.value) { + report[KB_KEY_CODE3] = HID_KEY_SCROLLLOCK; + } else { + report[KB_KEY_CODE3] = 0; + } + + break; + case INPUT_KEY_3: + if (kb_evt.value) { + report[KB_MOD_KEY] = HID_KBD_MODIFIER_RIGHT_ALT; + report[KB_KEY_CODE4] = HID_KEY_1; + report[KB_KEY_CODE5] = HID_KEY_2; + report[KB_KEY_CODE6] = HID_KEY_3; + } else { + report[KB_MOD_KEY] = HID_KBD_MODIFIER_NONE; + report[KB_KEY_CODE4] = 0; + report[KB_KEY_CODE5] = 0; + report[KB_KEY_CODE6] = 0; + } + + break; + default: + LOG_INF("Unrecognized input code %u value %d", + kb_evt.code, kb_evt.value); + continue; + } + + if (!kb_ready) { + LOG_INF("USB HID device is not ready"); + continue; + } + + ret = hid_device_submit_report(hid_dev, sizeof(report), report); + if (ret) { + LOG_ERR("HID submit report error, %d", ret); + } + } + + return 0; +} From 82926d66b1a071d37e4392f3c96805bff401a47e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:01 +0200 Subject: [PATCH 0674/1389] drivers: sensor: stm32_vbat: get rid of floating point computation Instead of using floating point operations to compute the vbat voltage, it is possible to do the computation using 32-bit variables by reordering operations and using the sensor_value_from_milli() function. On a STM32G0, this saves 140 bytes of flash, excluding the FP library needed on a FPU less MCU. Signed-off-by: Aurelien Jarno --- drivers/sensor/st/stm32_vbat/stm32_vbat.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/sensor/st/stm32_vbat/stm32_vbat.c b/drivers/sensor/st/stm32_vbat/stm32_vbat.c index 8379670fab380b..84511c1a4ccc50 100644 --- a/drivers/sensor/st/stm32_vbat/stm32_vbat.c +++ b/drivers/sensor/st/stm32_vbat/stm32_vbat.c @@ -77,18 +77,16 @@ static int stm32_vbat_channel_get(const struct device *dev, enum sensor_channel { struct stm32_vbat_data *data = dev->data; const struct stm32_vbat_config *cfg = dev->config; - float voltage; + int32_t voltage; if (chan != SENSOR_CHAN_VOLTAGE) { return -ENOTSUP; } - /* Sensor value in millivolts */ - voltage = data->raw * adc_ref_internal(data->adc) / 0x0FFF; - /* considering the vbat input through a resistor bridge */ - voltage = voltage * cfg->ratio / 1000; /* value of SENSOR_CHAN_VOLTAGE in Volt */ + /* Sensor value in millivolts considering the vbat input through a resistor bridge */ + voltage = data->raw * adc_ref_internal(data->adc) * cfg->ratio / 0x0FFF; - return sensor_value_from_double(val, voltage); + return sensor_value_from_milli(val, voltage); } static const struct sensor_driver_api stm32_vbat_driver_api = { From cd3e791bceb8a0ec34722e687bff43f5afb37eff Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0675/1389] drivers: sensor: stm32_vref: get rid of floating point computation Instead of using floating point operations to compute the vref voltage, it is possible to use the sensor_value_from_milli() function. On a STM32G0, this saves 130 bytes of flash, excluding the FP library needed on a FPU less MCU. Signed-off-by: Aurelien Jarno --- drivers/sensor/st/stm32_vref/stm32_vref.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/st/stm32_vref/stm32_vref.c b/drivers/sensor/st/stm32_vref/stm32_vref.c index 3532d2aeddd769..14412a6579a621 100644 --- a/drivers/sensor/st/stm32_vref/stm32_vref.c +++ b/drivers/sensor/st/stm32_vref/stm32_vref.c @@ -81,7 +81,7 @@ static int stm32_vref_channel_get(const struct device *dev, enum sensor_channel { struct stm32_vref_data *data = dev->data; const struct stm32_vref_config *cfg = dev->config; - float vref; + int32_t vref; if (chan != SENSOR_CHAN_VOLTAGE) { return -ENOTSUP; @@ -112,14 +112,12 @@ static int stm32_vref_channel_get(const struct device *dev, enum sensor_channel #else vref = cfg->cal_mv * (*cfg->cal_addr) / data->raw; #endif /* CONFIG_SOC_SERIES_STM32H5X */ - /* millivolt to volt */ - vref /= 1000; #if defined(CONFIG_SOC_SERIES_STM32H5X) LL_ICACHE_Enable(); #endif /* CONFIG_SOC_SERIES_STM32H5X */ - return sensor_value_from_double(val, vref); + return sensor_value_from_milli(val, vref); } static const struct sensor_driver_api stm32_vref_driver_api = { From f1468fa434afe019b40cab7578e279079a95c900 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0676/1389] modem: modem_cellular: make `modem_cellular_config` structure constant Remove redundant `const` qualifiers in `struct modem_cellular_config` and add `const` to the declaration to ensure the structure resides in read-only memory (rodata). Signed-off-by: Pisit Sawangvonganan --- drivers/modem/modem_cellular.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/modem/modem_cellular.c b/drivers/modem/modem_cellular.c index 7f646f4e789511..ca48f140b86c27 100644 --- a/drivers/modem/modem_cellular.c +++ b/drivers/modem/modem_cellular.c @@ -134,13 +134,13 @@ struct modem_cellular_data { struct modem_cellular_config { const struct device *uart; - const struct gpio_dt_spec power_gpio; - const struct gpio_dt_spec reset_gpio; - const uint16_t power_pulse_duration_ms; - const uint16_t reset_pulse_duration_ms; - const uint16_t startup_time_ms; - const uint16_t shutdown_time_ms; - const bool autostarts; + struct gpio_dt_spec power_gpio; + struct gpio_dt_spec reset_gpio; + uint16_t power_pulse_duration_ms; + uint16_t reset_pulse_duration_ms; + uint16_t startup_time_ms; + uint16_t shutdown_time_ms; + bool autostarts; const struct modem_chat_script *init_chat_script; const struct modem_chat_script *dial_chat_script; const struct modem_chat_script *periodic_chat_script; @@ -2089,7 +2089,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2118,7 +2118,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2147,7 +2147,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2176,7 +2176,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2205,7 +2205,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2234,7 +2234,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2264,7 +2264,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2293,7 +2293,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2321,7 +2321,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2350,7 +2350,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ From 2a23a9d0d02980e85aa2b290323a607d06750d15 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0677/1389] net: http_server: Add support for specifying Content-Type Allow user to specify the Content-Type header field for the HTTP response. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/server.h | 3 ++ subsys/net/lib/http/http_server_http1.c | 45 +++++++++++++++++++------ subsys/net/lib/http/http_server_http2.c | 21 ++++++++---- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index d493e5b3251eb5..7bfb609384356c 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -82,6 +82,9 @@ struct http_resource_detail { /** Content encoding of the resource. */ const char *content_encoding; + + /** Content type of the resource. */ + const char *content_type; }; /** @cond INTERNAL_HIDDEN */ diff --git a/subsys/net/lib/http/http_server_http1.c b/subsys/net/lib/http/http_server_http1.c index 799485f537c25c..d718c37bc3505e 100644 --- a/subsys/net/lib/http/http_server_http1.c +++ b/subsys/net/lib/http/http_server_http1.c @@ -31,12 +31,13 @@ static int handle_http1_static_resource( { #define RESPONSE_TEMPLATE \ "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n" \ + "%s%s\r\n" \ "Content-Length: %d\r\n" /* Add couple of bytes to total response */ char http_response[sizeof(RESPONSE_TEMPLATE) + sizeof("Content-Encoding: 01234567890123456789\r\n") + + sizeof("Content-Type: \r\n") + HTTP_SERVER_MAX_CONTENT_TYPE_LEN + sizeof("xxxx") + sizeof("\r\n")]; const char *data; @@ -51,10 +52,17 @@ static int handle_http1_static_resource( static_detail->common.content_encoding[0] != '\0') { snprintk(http_response, sizeof(http_response), RESPONSE_TEMPLATE "Content-Encoding: %s\r\n\r\n", + "Content-Type: ", + static_detail->common.content_type == NULL ? + "text/html" : static_detail->common.content_type, len, static_detail->common.content_encoding); } else { snprintk(http_response, sizeof(http_response), - RESPONSE_TEMPLATE "\r\n", len); + RESPONSE_TEMPLATE "\r\n", + "Content-Type: ", + static_detail->common.content_type == NULL ? + "text/html" : static_detail->common.content_type, + len); } ret = http_server_sendall(client, http_response, @@ -74,12 +82,28 @@ static int handle_http1_static_resource( #define RESPONSE_TEMPLATE_CHUNKED \ "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n" \ + "%s%s\r\n" \ "Transfer-Encoding: chunked\r\n\r\n" #define RESPONSE_TEMPLATE_DYNAMIC \ "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n\r\n" \ + "%s%s\r\n\r\n" + +#define SEND_RESPONSE(_template, _content_type) ({ \ + char http_response[sizeof(_template) + \ + sizeof("Content-Type: \r\n") + \ + HTTP_SERVER_MAX_CONTENT_TYPE_LEN + \ + sizeof("xxxx") + \ + sizeof("\r\n")]; \ + snprintk(http_response, sizeof(http_response), \ + _template "\r\n", \ + "Content-Type: ", \ + _content_type == NULL ? \ + "text/html" : _content_type); \ + ret = http_server_sendall(client, http_response, \ + strnlen(http_response, \ + sizeof(_template) - 1)); \ + ret; }) static int dynamic_get_req(struct http_resource_detail_dynamic *dynamic_detail, struct http_client_ctx *client) @@ -89,8 +113,8 @@ static int dynamic_get_req(struct http_resource_detail_dynamic *dynamic_detail, char *ptr; char tmp[TEMP_BUF_LEN]; - ret = http_server_sendall(client, RESPONSE_TEMPLATE_CHUNKED, - sizeof(RESPONSE_TEMPLATE_CHUNKED) - 1); + ret = SEND_RESPONSE(RESPONSE_TEMPLATE_CHUNKED, + dynamic_detail->common.content_type); if (ret < 0) { return ret; } @@ -167,8 +191,8 @@ static int dynamic_post_req(struct http_resource_detail_dynamic *dynamic_detail, } if (!client->headers_sent) { - ret = http_server_sendall(client, RESPONSE_TEMPLATE_CHUNKED, - sizeof(RESPONSE_TEMPLATE_CHUNKED) - 1); + ret = SEND_RESPONSE(RESPONSE_TEMPLATE_CHUNKED, + dynamic_detail->common.content_type); if (ret < 0) { return ret; } @@ -266,9 +290,8 @@ static int handle_http1_dynamic_resource( switch (client->method) { case HTTP_HEAD: if (user_method & BIT(HTTP_HEAD)) { - ret = http_server_sendall( - client, RESPONSE_TEMPLATE_DYNAMIC, - sizeof(RESPONSE_TEMPLATE_DYNAMIC) - 1); + ret = SEND_RESPONSE(RESPONSE_TEMPLATE_DYNAMIC, + dynamic_detail->common.content_type); if (ret < 0) { return ret; } diff --git a/subsys/net/lib/http/http_server_http2.c b/subsys/net/lib/http/http_server_http2.c index 3948401057f78b..b455340bf389e8 100644 --- a/subsys/net/lib/http/http_server_http2.c +++ b/subsys/net/lib/http/http_server_http2.c @@ -149,7 +149,8 @@ static void encode_frame_header(uint8_t *buf, uint32_t payload_len, static int send_headers_frame(struct http_client_ctx *client, enum http_status status, uint32_t stream_id, - const char *content_encoding, uint8_t flags) + struct http_resource_detail *detail_common, + uint8_t flags) { uint8_t headers_frame[64]; uint8_t status_str[4]; @@ -168,7 +169,7 @@ static int send_headers_frame(struct http_client_ctx *client, return ret; } - if (content_encoding != NULL) { + if (detail_common && detail_common->content_encoding != NULL) { ret = add_header_field(client, &buf, &buflen, "content-encoding", "gzip"); if (ret < 0) { @@ -176,6 +177,14 @@ static int send_headers_frame(struct http_client_ctx *client, } } + if (detail_common && detail_common->content_type != NULL) { + ret = add_header_field(client, &buf, &buflen, "content-type", + detail_common->content_type); + if (ret < 0) { + return ret; + } + } + payload_len = sizeof(headers_frame) - buflen - HTTP_SERVER_FRAME_HEADER_SIZE; flags |= HTTP_SERVER_FLAG_END_HEADERS; @@ -349,7 +358,7 @@ static int handle_http2_static_resource( content_len = static_detail->static_data_len; ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier, - static_detail->common.content_encoding, 0); + &static_detail->common, 0); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); goto out; @@ -375,7 +384,7 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai char *ptr; ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier, - dynamic_detail->common.content_encoding, 0); + &dynamic_detail->common, 0); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); return ret; @@ -481,7 +490,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta if (!client->headers_sent) { ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, - dynamic_detail->common.content_encoding, 0); + &dynamic_detail->common, 0); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); return ret; @@ -518,7 +527,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta */ ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, - dynamic_detail->common.content_encoding, + &dynamic_detail->common, HTTP_SERVER_FLAG_END_STREAM); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); From be219de1280db3892536cf647b465792725258d8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0678/1389] samples: net: http_server: Add example of passing Content-Type field Show how to pass Content-Type header field to client. Signed-off-by: Jukka Rissanen --- samples/net/sockets/http_server/src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/net/sockets/http_server/src/main.c b/samples/net/sockets/http_server/src/main.c index be564ac4a541e5..ff72f2ed5bbde2 100644 --- a/samples/net/sockets/http_server/src/main.c +++ b/samples/net/sockets/http_server/src/main.c @@ -31,6 +31,7 @@ struct http_resource_detail_static index_html_gz_resource_detail = { .type = HTTP_RESOURCE_TYPE_STATIC, .bitmask_of_supported_http_methods = BIT(HTTP_GET), .content_encoding = "gzip", + .content_type = "text/html", }, .static_data = index_html_gz, .static_data_len = sizeof(index_html_gz), From be8af23affeef17bd584ffdf7e08439a80aea666 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0679/1389] drivers: video: csi: Rename sensor to source The CSI can connect to either a camera sensor (as on i.MX RT10xx) or a MIPI CSI-2 receiver (as on i.MX RT11xx). To be generic, change the naming from sensor to source. Signed-off-by: Phi Bang Nguyen --- boards/madmachine/mm_swiftio/mm_swiftio.dts | 2 +- boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts | 2 +- drivers/video/video_mcux_csi.c | 38 ++++++++++---------- dts/bindings/video/nxp,imx-csi.yaml | 5 +-- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/boards/madmachine/mm_swiftio/mm_swiftio.dts b/boards/madmachine/mm_swiftio/mm_swiftio.dts index b9994d1e8c1157..e4212cd8294c6d 100644 --- a/boards/madmachine/mm_swiftio/mm_swiftio.dts +++ b/boards/madmachine/mm_swiftio/mm_swiftio.dts @@ -192,7 +192,7 @@ &csi { status = "okay"; - sensor = <&ov7725>; + source = <&ov7725>; pinctrl-0 = <&pinmux_csi>; pinctrl-names = "default"; diff --git a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts index c20be8ad6a892c..387b116d601544 100644 --- a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts +++ b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts @@ -272,7 +272,7 @@ zephyr_udc0: &usb1 { &csi { status = "okay"; - sensor = <&mt9m114>; + source = <&mt9m114>; pinctrl-0 = <&pinmux_csi>; pinctrl-names = "default"; diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index d267ea7a5ad8f5..77022d037d898c 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -20,7 +20,7 @@ struct video_mcux_csi_config { CSI_Type *base; - const struct device *sensor_dev; + const struct device *source_dev; const struct pinctrl_dev_config *pincfg; }; @@ -144,7 +144,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_ return -EIO; } - if (config->sensor_dev && video_set_format(config->sensor_dev, ep, fmt)) { + if (config->source_dev && video_set_format(config->source_dev, ep, fmt)) { return -EIO; } @@ -160,8 +160,8 @@ static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_ return -EINVAL; } - if (config->sensor_dev && !video_get_format(config->sensor_dev, ep, fmt)) { - /* align CSI with sensor fmt */ + if (config->source_dev && !video_get_format(config->source_dev, ep, fmt)) { + /* align CSI with source fmt */ return video_mcux_csi_set_fmt(dev, ep, fmt); } @@ -179,7 +179,7 @@ static int video_mcux_csi_stream_start(const struct device *dev) return -EIO; } - if (config->sensor_dev && video_stream_start(config->sensor_dev)) { + if (config->source_dev && video_stream_start(config->source_dev)) { return -EIO; } @@ -192,7 +192,7 @@ static int video_mcux_csi_stream_stop(const struct device *dev) struct video_mcux_csi_data *data = dev->data; status_t ret; - if (config->sensor_dev && video_stream_stop(config->sensor_dev)) { + if (config->source_dev && video_stream_stop(config->source_dev)) { return -EIO; } @@ -283,9 +283,9 @@ static inline int video_mcux_csi_set_ctrl(const struct device *dev, unsigned int const struct video_mcux_csi_config *config = dev->config; int ret = -ENOTSUP; - /* Forward to sensor dev if any */ - if (config->sensor_dev) { - ret = video_set_ctrl(config->sensor_dev, cid, value); + /* Forward to source dev if any */ + if (config->source_dev) { + ret = video_set_ctrl(config->source_dev, cid, value); } return ret; @@ -296,9 +296,9 @@ static inline int video_mcux_csi_get_ctrl(const struct device *dev, unsigned int const struct video_mcux_csi_config *config = dev->config; int ret = -ENOTSUP; - /* Forward to sensor dev if any */ - if (config->sensor_dev) { - ret = video_get_ctrl(config->sensor_dev, cid, value); + /* Forward to source dev if any */ + if (config->source_dev) { + ret = video_get_ctrl(config->source_dev, cid, value); } return ret; @@ -314,15 +314,15 @@ static int video_mcux_csi_get_caps(const struct device *dev, enum video_endpoint return -EINVAL; } - /* Just forward to sensor dev for now */ - if (config->sensor_dev) { - err = video_get_caps(config->sensor_dev, ep, caps); + /* Just forward to source dev for now */ + if (config->source_dev) { + err = video_get_caps(config->source_dev, ep, caps); } /* NXP MCUX CSI request at least 2 buffer before starting */ caps->min_vbuf_count = 2; - /* no sensor dev */ + /* no source dev */ return err; } @@ -344,10 +344,10 @@ static int video_mcux_csi_init(const struct device *dev) CSI_GetDefaultConfig(&data->csi_config); - /* check if there is any sensor device (video ctrl device) + /* check if there is any source device (video ctrl device) * the device is not yet initialized so we only check if it exists */ - if (config->sensor_dev == NULL) { + if (config->source_dev == NULL) { return -ENODEV; } @@ -396,7 +396,7 @@ PINCTRL_DT_INST_DEFINE(0); static const struct video_mcux_csi_config video_mcux_csi_config_0 = { .base = (CSI_Type *)DT_INST_REG_ADDR(0), - .sensor_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, sensor)), + .source_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, source)), .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), }; diff --git a/dts/bindings/video/nxp,imx-csi.yaml b/dts/bindings/video/nxp,imx-csi.yaml index d2553d68911844..bf7fd01eeaadd3 100644 --- a/dts/bindings/video/nxp,imx-csi.yaml +++ b/dts/bindings/video/nxp,imx-csi.yaml @@ -14,7 +14,8 @@ properties: interrupts: required: true - sensor: + source: required: true type: phandle - description: phandle of connected sensor device + description: the connected source device, + e.g., a mipi csi or a camera sensor From db42756cf69e0252c49693d5d3908c4fc1da80c8 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0680/1389] drivers: sdhc: imx_usdhc: move voltage selection to separate function Some USDHC IP instances do not have the voltage control bit present, as they can only operate at 3.3V. Move code to select 1.8V mode into a separate helper, and guard the call to UDSHC_SelectVoltage() behind a feature macro from MCUX SDK. Signed-off-by: Daniel DeGrasse --- drivers/sdhc/imx_usdhc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/sdhc/imx_usdhc.c b/drivers/sdhc/imx_usdhc.c index 84f8f2aee3b0b2..812305a7135048 100644 --- a/drivers/sdhc/imx_usdhc.c +++ b/drivers/sdhc/imx_usdhc.c @@ -159,6 +159,14 @@ static void card_detect_gpio_cb(const struct device *port, } } +static void imx_usdhc_select_1_8v(USDHC_Type *base, bool enable_1_8v) +{ +#if !(defined(FSL_FEATURE_USDHC_HAS_NO_VOLTAGE_SELECT) && \ + (FSL_FEATURE_USDHC_HAS_NO_VOLTAGE_SELECT)) + UDSHC_SelectVoltage(base, enable_1_8v); +#endif +} + static int imx_usdhc_dat3_pull(const struct usdhc_config *cfg, bool pullup) { @@ -256,7 +264,7 @@ static int imx_usdhc_reset(const struct device *dev) { const struct usdhc_config *cfg = dev->config; /* Switch to default I/O voltage of 3.3V */ - UDSHC_SelectVoltage(cfg->base, false); + imx_usdhc_select_1_8v(cfg->base, false); USDHC_EnableDDRMode(cfg->base, false, 0U); #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE) USDHC_EnableStandardTuning(cfg->base, 0, 0, false); @@ -353,7 +361,7 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) switch (ios->signal_voltage) { case SD_VOL_3_3_V: case SD_VOL_3_0_V: - UDSHC_SelectVoltage(cfg->base, false); + imx_usdhc_select_1_8v(cfg->base, false); break; case SD_VOL_1_8_V: /** @@ -367,7 +375,7 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) * 10 ms, then allow it to be gated again. */ /* Switch to 1.8V */ - UDSHC_SelectVoltage(cfg->base, true); + imx_usdhc_select_1_8v(cfg->base, true); /* Wait 10 ms- clock will be gated during this period */ k_msleep(10); /* Force the clock on */ From 7d55200ff04fd2f42253fc94e4eef9b82fe07404 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0681/1389] drivers: sdhc: imx_usdhc: remove dead code for waiting for clock gate Remove function for waiting for clock gate, as this is not used anywhere within the USDHC driver. Signed-off-by: Daniel DeGrasse --- drivers/sdhc/imx_usdhc.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/sdhc/imx_usdhc.c b/drivers/sdhc/imx_usdhc.c index 812305a7135048..2265a60202483b 100644 --- a/drivers/sdhc/imx_usdhc.c +++ b/drivers/sdhc/imx_usdhc.c @@ -282,21 +282,6 @@ static int imx_usdhc_reset(const struct device *dev) return USDHC_Reset(cfg->base, kUSDHC_ResetAll, 100U) == true ? 0 : -ETIMEDOUT; } -/* Wait for USDHC to gate clock when it is disabled */ -static inline void imx_usdhc_wait_clock_gate(USDHC_Type *base) -{ - uint32_t timeout = 1000; - - while (timeout--) { - if (base->PRES_STATE & USDHC_PRES_STATE_SDOFF_MASK) { - break; - } - } - if (timeout == 0) { - LOG_WRN("SD clock did not gate in time"); - } -} - /* * Set SDHC io properties */ From d1aff171ff0ef9af743d7e2dc55e4a0c6d8b25f2 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0682/1389] drivers: sdhc: imx_usdhc: extend reset timeout duration Some instances of the USDHC peripheral take longer to reset, and will timeout with the previous delay of 100 cycles. Extend this delay to 1000 cycles to resolve this. Signed-off-by: Daniel DeGrasse --- drivers/sdhc/imx_usdhc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sdhc/imx_usdhc.c b/drivers/sdhc/imx_usdhc.c index 2265a60202483b..2909ea104b15d0 100644 --- a/drivers/sdhc/imx_usdhc.c +++ b/drivers/sdhc/imx_usdhc.c @@ -279,7 +279,7 @@ static int imx_usdhc_reset(const struct device *dev) #endif /* Reset data/command/tuning circuit */ - return USDHC_Reset(cfg->base, kUSDHC_ResetAll, 100U) == true ? 0 : -ETIMEDOUT; + return USDHC_Reset(cfg->base, kUSDHC_ResetAll, 1000U) == true ? 0 : -ETIMEDOUT; } /* From a1cc413d5a3ce384faef332eab25c40e4bbb6ac5 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0683/1389] dts: arm: nxp: mcxn94x: add USDHC0 node Add USDHC0 node to the mcxn94x devicetree. This node describes the one instance of the Ultra Secured Digital Host Controller IP present on the MCXN94x series SOCs. Signed-off-by: Daniel DeGrasse --- dts/arm/nxp/nxp_mcxn94x_common.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index ad7d25a8ec72b9..2410a6377c792a 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -786,6 +786,16 @@ input = <0>; prescale = <0>; }; + + usdhc0: usdhc@109000 { + compatible = "nxp,imx-usdhc"; + reg = <0x109000 0x1000>; + interrupts = <61 0>; + status = "disabled"; + clocks = <&syscon MCUX_USDHC1_CLK>; + max-bus-freq = <52000000>; + min-bus-freq = <400000>; + }; }; &systick { From 7631d6551b35975e283eaf3008b2012f65ba3782 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0684/1389] boards: nxp: frdm_mcxn947: add support for USDHC0 Add support for USDHC0 controller on FRDM_MCXN947 board. This support was verified using the `tests/subsys/sd/sdmmc` and `tests/subsys/sd/sdio` testcases. Note that this board does not ship with the SD header (J12) populated by default, so the user must populate one. Signed-off-by: Daniel DeGrasse --- boards/nxp/frdm_mcxn947/Kconfig.defconfig | 8 ++++++++ boards/nxp/frdm_mcxn947/board.c | 5 +++++ boards/nxp/frdm_mcxn947/doc/index.rst | 2 ++ .../frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi | 19 +++++++++++++++++++ boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi | 10 ++++++++++ .../frdm_mcxn947_mcxn947_cpu0.dts | 12 ++++++++++++ .../frdm_mcxn947_mcxn947_cpu0.yaml | 1 + 7 files changed, 57 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/Kconfig.defconfig b/boards/nxp/frdm_mcxn947/Kconfig.defconfig index 72cc76170b9744..461a4ed628642d 100644 --- a/boards/nxp/frdm_mcxn947/Kconfig.defconfig +++ b/boards/nxp/frdm_mcxn947/Kconfig.defconfig @@ -6,4 +6,12 @@ if BOARD_FRDM_MCXN947 config NET_L2_ETHERNET default y if NETWORKING +if SD_STACK + +# SD stack requires larger main stack size +config MAIN_STACK_SIZE + default 1536 + +endif + endif diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index 29b4bbf846129b..0481fafddf55e2 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -192,6 +192,11 @@ static int frdm_mcxn947_init(void) CLOCK_AttachClk(kPLL0_to_CTIMER4); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc0), okay) + CLOCK_SetClkDiv(kCLOCK_DivUSdhcClk, 1u); + CLOCK_AttachClk(kFRO_HF_to_USDHC); +#endif + #if CONFIG_FLASH_MCUX_FLEXSPI_NOR /* We downclock the FlexSPI to 50MHz, it will be set to the * optimum speed supported by the Flash device during FLEXSPI diff --git a/boards/nxp/frdm_mcxn947/doc/index.rst b/boards/nxp/frdm_mcxn947/doc/index.rst index cf63ab6abff72c..9dd884e07283c3 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -82,6 +82,8 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | CTIMER | on-chip | counter | +-----------+------------+-------------------------------------+ +| USDHC | on-chip | sdhc | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi index 11bb253d66a98d..4d3e9771382985 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi @@ -129,4 +129,23 @@ }; }; + pinmux_usdhc0: pinmux_usdhc0 { + group0 { + pinmux = , + , + , + , + ; + slew-rate = "fast"; + drive-strength = "low"; + bias-pull-up; + input-enable; + }; + group1 { + pinmux = ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + }; + }; }; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi index e1543f19692a28..0634ddcae56ffa 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi @@ -14,6 +14,7 @@ led2 = &blue_led; sw0 = &user_button_2; sw1 = &user_button_3; + sdhc0 = &usdhc0; }; leds { @@ -173,3 +174,12 @@ pinctrl-0 = <&pinmux_flexpwm1_pwm0>; pinctrl-names = "default"; }; + +&usdhc0 { + pinctrl-0 = <&pinmux_usdhc0>; + pinctrl-1 = <&pinmux_usdhc0>; + pinctrl-2 = <&pinmux_usdhc0>; + cd-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "slow", "med"; + no-1-8-v; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts index 4865e16784ea87..462edb3332bc37 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -58,6 +58,10 @@ status = "okay"; }; +&gpio2 { + status = "okay"; +}; + &green_led { status = "okay"; }; @@ -141,3 +145,11 @@ &ctimer0 { status = "okay"; }; + +&usdhc0 { + status = "okay"; + sdmmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml index 2e9c4f6c2830d8..a1c2b1c2da1287 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml @@ -23,4 +23,5 @@ supported: - watchdog - pwm - counter + - sdhc vendor: nxp From 5551637bb3c5640d1b21c83f1cb3ba0324ddfd98 Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0685/1389] ci: codecov: Add upload token for codecov action This commit adds the token for uploading to codecov.io because codecov now requires a token and rejects any upload requests without one. It also updates the codecov-action version from v3 to v4, which is required for using a "global upload token." Signed-off-by: Stephanos Ioannidis --- .github/workflows/codecov.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 1c5ded582f0df1..63812a85eb2916 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -220,10 +220,11 @@ jobs: - name: Upload coverage to Codecov if: always() - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: directory: ./coverage/reports env_vars: OS,PYTHON fail_ci_if_error: false verbose: true + token: ${{ secrets.CODECOV_TOKEN }} files: merged.xml From f09bdf63173159ff812b9397e2b9af321df57d52 Mon Sep 17 00:00:00 2001 From: Troels Nilsson Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0686/1389] Bluetooth: Controller: Add parameter to ISOALs sdu_write For vendor datapaths that do not use a netbuffer to write SDUs into, the callee of sdu_write currently has to keep track itself of how much data has been written to the current SDU; This is wasteful since ISOAL already keeps track of that. Add an sdu_written parameter to the callback to inform the callee how much has been written to the current SDU already so the callee can write using the correct offset Signed-off-by: Troels Nilsson --- subsys/bluetooth/controller/hci/hci_driver.c | 3 + subsys/bluetooth/controller/ll_sw/isoal.c | 1 + subsys/bluetooth/controller/ll_sw/isoal.h | 3 + .../ctrl_isoal/src/sub_sets/isoal_test_rx.c | 194 +++++++++++++++++- tests/bsim/bluetooth/ll/bis/src/main.c | 3 +- 5 files changed, 196 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index a7251748cca3ae..f174ca02c728c0 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -256,9 +256,12 @@ isoal_status_t sink_sdu_emit_hci(const struct isoal_sink *sink_ctx, } isoal_status_t sink_sdu_write_hci(void *dbuf, + const size_t sdu_written, const uint8_t *pdu_payload, const size_t consume_len) { + ARG_UNUSED(sdu_written); + struct net_buf *buf = (struct net_buf *) dbuf; LL_ASSERT(buf); diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index 48ad0835074ddb..ff06068a8e6028 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -694,6 +694,7 @@ static isoal_status_t isoal_rx_append_to_sdu(struct isoal_sink *sink, const struct isoal_sink_session *session = &sink->session; err |= session->sdu_write(sdu->contents.dbuf, + sp->sdu_written, pdu_payload, consume_len); pdu_payload += consume_len; diff --git a/subsys/bluetooth/controller/ll_sw/isoal.h b/subsys/bluetooth/controller/ll_sw/isoal.h index 61d3773c43d0a1..0e50bea63be176 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.h +++ b/subsys/bluetooth/controller/ll_sw/isoal.h @@ -242,6 +242,8 @@ typedef isoal_status_t (*isoal_sink_sdu_emit_cb)( typedef isoal_status_t (*isoal_sink_sdu_write_cb)( /*!< [in] Destination buffer */ void *dbuf, + /*!< [in] Number of bytes already written to this SDU */ + const size_t sdu_written, /*!< [in] Source data */ const uint8_t *pdu_payload, /*!< [in] Number of bytes to be copied */ @@ -450,6 +452,7 @@ isoal_status_t sink_sdu_emit_hci(const struct isoal_sink *sink_ctx, const struct isoal_emitted_sdu_frag *sdu_frag, const struct isoal_emitted_sdu *sdu); isoal_status_t sink_sdu_write_hci(void *dbuf, + const size_t sdu_written, const uint8_t *pdu_payload, const size_t consume_len); diff --git a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c index 06407816c38e1c..b7beb40f38a11e 100644 --- a/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c +++ b/tests/bluetooth/ctrl_isoal/src/sub_sets/isoal_test_rx.c @@ -176,17 +176,20 @@ static isoal_status_t custom_sink_sdu_emit_test(const struct isoal_sink *sink_ct _expected, \ sink_sdu_emit_test_fake.call_count) -FAKE_VALUE_FUNC(isoal_status_t, sink_sdu_write_test, void *, const uint8_t *, const size_t); +FAKE_VALUE_FUNC(isoal_status_t, sink_sdu_write_test, void *, const size_t, + const uint8_t *, const size_t); /** * Callback test fixture to be provided for RX sink creation. Writes provided * data into target SDU buffer. * @param dbuf SDU buffer (Includes current write location field) + * @param sdu_written Number of bytes already written to this SDU * @param pdu_payload Current PDU being reassembled by ISO-AL * @param consume_len Length of data to transfer * @return Status of the operation */ static isoal_status_t -custom_sink_sdu_write_test(void *dbuf, const uint8_t *pdu_payload, const size_t consume_len) +custom_sink_sdu_write_test(void *dbuf, const size_t sdu_written, + const uint8_t *pdu_payload, const size_t consume_len) { isoal_test_debug_trace_func_call(__func__, "IN"); @@ -204,22 +207,27 @@ custom_sink_sdu_write_test(void *dbuf, const uint8_t *pdu_payload, const size_t return sink_sdu_write_test_fake.return_val; } -#define ZASSERT_ISOAL_SDU_WRITE_TEST(_typ, _frag_buf, _payload_buf, _length) \ +#define ZASSERT_ISOAL_SDU_WRITE_TEST(_typ, _frag_buf, _sdu_written, _payload_buf, _length) \ zassert_equal_ptr(_frag_buf, \ sink_sdu_write_test_fake.arg0_##_typ, \ "\t\tExpected write buffer at %p, got %p.", \ _frag_buf, \ sink_sdu_write_test_fake.arg0_##_typ); \ + zassert_equal(_sdu_written, \ + sink_sdu_write_test_fake.arg1_##_typ, \ + "\t\tExpected sdu_written of %u, got %u.", \ + _sdu_written, \ + sink_sdu_write_test_fake.arg1_##_typ); \ zassert_equal_ptr(_payload_buf, \ - sink_sdu_write_test_fake.arg1_##_typ, \ + sink_sdu_write_test_fake.arg2_##_typ, \ "\t\tExpected write source at %p, got %p.", \ _payload_buf, \ - sink_sdu_write_test_fake.arg1_##_typ); \ + sink_sdu_write_test_fake.arg2_##_typ); \ zassert_equal(_length, \ - sink_sdu_write_test_fake.arg2_##_typ, \ + sink_sdu_write_test_fake.arg3_##_typ, \ "\t\tExpected write length of %u, got %u.", \ _length, \ - sink_sdu_write_test_fake.arg2_##_typ) + sink_sdu_write_test_fake.arg3_##_typ) #define ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(_expected) \ zassert_equal(_expected, \ @@ -877,6 +885,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1047,6 +1056,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu_ts_wrap1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1182,6 +1192,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_single_pdu_ts_wrap2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1231,6 +1242,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -1312,6 +1324,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1328,6 +1341,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu) /* PDU 1 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -1360,6 +1374,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1414,6 +1429,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -1493,6 +1509,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1508,6 +1525,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU 0 - PDU 1 -----------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -1538,6 +1556,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1563,6 +1582,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU 1 - PDU 2 -----------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; seqn++; sdu_timestamp = (uint32_t)((int64_t)pdu_timestamp + latency + sdu_interval); @@ -1596,6 +1616,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1611,6 +1632,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU 1 - PDU 3 -----------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -1641,6 +1663,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1666,6 +1689,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU 2 - PDU 4 -----------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; seqn++; pdu_timestamp = 9249 + ISO_INT_UNIT_US; @@ -1703,6 +1727,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -1755,6 +1780,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -1834,6 +1860,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1849,6 +1876,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* PDU 1 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -1876,6 +1904,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1891,6 +1920,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -1918,6 +1948,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1933,6 +1964,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -1960,6 +1992,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -1975,6 +2008,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* PDU 4 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -2005,6 +2039,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -2059,6 +2094,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -2138,6 +2174,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -2153,6 +2190,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* PDU 1 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 23; @@ -2183,6 +2221,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -2208,6 +2247,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; testdata_indx = testdata_size; testdata_size += 40; @@ -2242,6 +2282,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -2266,6 +2307,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written = 0; payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -2297,6 +2339,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -2312,6 +2355,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* PDU 4 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -2342,6 +2386,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_multi_split_on_border) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -2471,6 +2516,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_long_pdu_short_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[0], &rx_sdu_frag_buf[0], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ 20); /* Size */ /* SDU should be emitted */ @@ -2498,6 +2544,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_long_pdu_short_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[1], &rx_sdu_frag_buf[1], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + 20], /* PDU payload */ 20); /* Size */ /* SDU should be emitted */ @@ -2620,6 +2667,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_prem) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -2680,6 +2728,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_prem) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -2900,6 +2949,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -2978,6 +3028,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -2991,6 +3042,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err) FSM_TO_STR(ISOAL_CONTINUE)); /* PDU 2 Not transferred to ISO-AL ------------------------------------*/ + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -3029,6 +3081,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -3058,6 +3111,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err) /* PDU 4 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; seqn++; pdu_timestamp = 9249 + ISO_INT_UNIT_US; @@ -3093,6 +3147,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -3129,6 +3184,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -3208,6 +3264,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -3284,6 +3341,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) /* PDU 4 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; seqn++; pdu_timestamp = 9249 + ISO_INT_UNIT_US; @@ -3318,6 +3376,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -3336,6 +3395,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) /* PDU 5 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -3365,6 +3425,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -3409,6 +3470,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -3491,6 +3553,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -3583,6 +3646,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) /* PDU 4 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; seqn++; pdu_timestamp = 9249 + ISO_INT_UNIT_US; @@ -3617,6 +3681,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -3635,6 +3700,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) /* PDU 5 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -3664,6 +3730,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -3706,6 +3773,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -3785,6 +3853,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -3798,6 +3867,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -3829,6 +3899,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -4013,6 +4084,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_no_end) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -4471,6 +4543,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_leading) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -4778,6 +4851,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -4887,6 +4961,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error3) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -4966,6 +5041,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -4979,6 +5055,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error3) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -5008,6 +5085,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_padding_error3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -5201,6 +5279,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err_zero_length) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -5280,6 +5359,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err_zero_length) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -5292,6 +5372,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err_zero_length) FSM_TO_STR(ISOAL_CONTINUE)); /* PDU 2 Not transferred to ISO-AL ------------------------------------*/ + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -5328,6 +5409,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_seq_err_zero_length) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -5437,6 +5519,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_no_end) uint8_t iso_interval_int; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t pdu_timestamp; uint32_t sdu_timestamp; uint16_t testdata_indx; @@ -5516,6 +5599,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_no_end) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -5529,6 +5613,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_no_end) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -5558,6 +5643,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_no_end) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should be emitted */ @@ -5769,6 +5855,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_invalid_llid2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -5903,6 +5990,7 @@ ZTEST(test_rx_unframed, test_rx_unframed_dbl_pdu_invalid_llid2_pdu_err) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ /* SDU should not be emitted */ @@ -6073,6 +6161,7 @@ ZTEST(test_rx_framed, test_rx_framed_single_pdu_single_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6204,6 +6293,7 @@ ZTEST(test_rx_framed, test_rx_framed_single_pdu_single_sdu_ts_wrap1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6336,6 +6426,7 @@ ZTEST(test_rx_framed, test_rx_framed_single_pdu_single_sdu_ts_wrap2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6380,6 +6471,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu) uint16_t pdu_data_loc[5]; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint32_t sdu_timestamp; @@ -6464,6 +6556,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6479,6 +6572,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -6505,6 +6599,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6520,6 +6615,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -6549,6 +6645,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6594,6 +6691,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) uint32_t iso_interval_us; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint16_t testdata_indx; @@ -6681,6 +6779,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6697,6 +6796,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -6741,6 +6841,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[1], &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ 10); /* Size */ @@ -6758,6 +6859,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) collated_status); /* SDU status */ /* SDU 2 */ + sdu_written = 0; seqn++; /* A new SDU should be allocated */ ZASSERT_ISOAL_SDU_ALLOC_TEST(val, @@ -6767,6 +6869,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6783,6 +6886,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -6811,6 +6915,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6858,6 +6963,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) isoal_sdu_cnt_t seqn[3]; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint16_t testdata_indx; @@ -6947,6 +7053,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -6963,6 +7070,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -7021,6 +7129,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[1], &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ 10); /* Size */ @@ -7039,6 +7148,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) collated_status); /* SDU status */ /* SDU 2 */ + sdu_written = 0; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size[1], sdu_size[1]); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_VALID, ISOAL_SDU_STATUS_VALID); @@ -7071,6 +7181,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[2], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -7087,6 +7198,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -7116,6 +7228,7 @@ ZTEST(test_rx_framed, test_rx_framed_zero_length_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[2], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -7250,6 +7363,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_padding) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -7351,6 +7465,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_padding) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -7720,6 +7835,7 @@ ZTEST(test_rx_framed, test_rx_framed_padding_only) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[3], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -8281,6 +8397,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -8497,6 +8614,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err2) ZASSERT_ISOAL_SDU_WRITE_TEST_CALL_COUNT(1); ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -8634,6 +8752,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -8829,6 +8948,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -8937,6 +9057,7 @@ ZTEST(test_rx_framed, test_rx_framed_dbl_pdu_dbl_sdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9202,6 +9323,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9333,6 +9455,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9471,6 +9594,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9516,6 +9640,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err3) uint32_t iso_interval_us; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint32_t sdu_timestamp; @@ -9602,6 +9727,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9618,6 +9744,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err3) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -9644,6 +9771,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9710,6 +9838,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err3) isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf); + sdu_written = 0; payload_number++; sdu_timeoffset = get_next_time_offset(sdu_timeoffset, iso_interval_us, sdu_interval, false); @@ -9749,6 +9878,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9880,6 +10010,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -9994,6 +10125,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10125,6 +10257,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10239,6 +10372,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_single_sdu_pdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10280,6 +10414,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err1) uint32_t group_sync_delay; isoal_sdu_len_t sdu_size[2]; uint16_t total_sdu_size[2]; + uint16_t sdu_written = 0; uint8_t iso_interval_int; uint32_t sdu_timestamp[2]; uint16_t pdu_data_loc[5]; @@ -10449,6 +10584,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10465,6 +10601,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err1) /* PDU 3 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -10497,6 +10634,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10534,6 +10672,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err1) isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); isoal_test_init_rx_sdu_buffer(&rx_sdu_frag_buf[0]); + sdu_written = 0; payload_number++; pdu_timestamp = 9249 + iso_interval_us; sdu_timeoffset = get_next_time_offset(sdu_timeoffset, iso_interval_us, sdu_interval, true); @@ -10597,6 +10736,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10751,6 +10891,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -10967,6 +11108,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -11029,6 +11171,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) uint32_t iso_interval_us; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint16_t testdata_indx; @@ -11117,6 +11260,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -11133,6 +11277,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) /* PDU 1 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -11177,6 +11322,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[1], &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ 10); /* Size */ @@ -11195,6 +11341,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) collated_status); /* SDU status */ /* SDU 1 -------------------------------------------------------------*/ + sdu_written = 0; seqn++; /* A new SDU should be allocated */ ZASSERT_ISOAL_SDU_ALLOC_TEST(history[1], @@ -11204,6 +11351,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -11333,6 +11481,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) collated_status); /* SDU status */ /* SDU 3 -------------------------------------------------------------*/ + sdu_written = 0; seqn++; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size[0], sdu_size[0]); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_VALID, ISOAL_SDU_STATUS_VALID); @@ -11345,6 +11494,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_err3) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -11499,6 +11649,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -11692,6 +11843,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -11847,6 +11999,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12034,6 +12187,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_pdu_seq_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + 0, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12079,6 +12233,7 @@ ZTEST(test_rx_framed, test_rx_framed_single_invalid_pdu_single_sdu) uint16_t pdu_data_loc[5]; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint32_t sdu_timestamp; @@ -12182,18 +12337,23 @@ ZTEST(test_rx_framed, test_rx_framed_single_invalid_pdu_single_sdu) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[0], &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ 13); /* Size */ + sdu_written += 13; ZASSERT_ISOAL_SDU_WRITE_TEST(history[1], &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ 5); /* Size */ + sdu_written += 5; ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12240,6 +12400,7 @@ ZTEST(test_rx_framed, test_rx_framed_single_invalid_pdu_single_sdu_hdr_err) uint16_t pdu_data_loc[5]; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint32_t sdu_timestamp; @@ -12360,30 +12521,39 @@ ZTEST(test_rx_framed, test_rx_framed_single_invalid_pdu_single_sdu_hdr_err) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(history[0], &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ 3); /* Size */ + sdu_written += 3; ZASSERT_ISOAL_SDU_WRITE_TEST(history[1], &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ 4); /* Size */ + sdu_written += 4; ZASSERT_ISOAL_SDU_WRITE_TEST(history[2], &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ 4); /* Size */ + sdu_written += 4; ZASSERT_ISOAL_SDU_WRITE_TEST(history[3], &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ 4); /* Size */ + sdu_written += 4; ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf, /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12445,6 +12615,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err1) isoal_sdu_cnt_t seqn[2]; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint16_t testdata_indx; @@ -12612,6 +12783,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[2]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12629,6 +12801,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err1) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -12660,6 +12833,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err1) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[1], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[3]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12727,6 +12901,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err2) uint32_t iso_interval_us; uint64_t payload_number; uint16_t total_sdu_size; + uint16_t sdu_written = 0; uint32_t sdu_timeoffset; uint32_t pdu_timestamp; uint16_t testdata_indx; @@ -12816,6 +12991,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[0]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ @@ -12833,6 +13009,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err2) /* PDU 2 -------------------------------------------------------------*/ isoal_test_init_rx_pdu_buffer(&rx_pdu_meta_buf); + sdu_written += (testdata_size - testdata_indx); payload_number++; testdata_indx = testdata_size; testdata_size += 10; @@ -12880,6 +13057,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[1]], /* PDU payload */ 10); /* Size */ @@ -13032,6 +13210,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err2) collated_status); /* SDU status */ /* SDU 3 -------------------------------------------------------------*/ + sdu_written = 0; seqn++; total_sdu_size = COLLATED_RX_SDU_INFO(sdu_size[0], sdu_size[0]); collated_status = COLLATED_RX_SDU_INFO(ISOAL_SDU_STATUS_VALID, ISOAL_SDU_STATUS_VALID); @@ -13044,6 +13223,7 @@ ZTEST(test_rx_framed, test_rx_framed_trppl_pdu_dbl_sdu_seg_err2) /* SDU payload should be written */ ZASSERT_ISOAL_SDU_WRITE_TEST(val, &rx_sdu_frag_buf[0], /* SDU buffer */ + sdu_written, /* SDU written */ &rx_pdu_meta_buf.pdu[3 + pdu_data_loc[4]], /* PDU payload */ (testdata_size - testdata_indx)); /* Size */ diff --git a/tests/bsim/bluetooth/ll/bis/src/main.c b/tests/bsim/bluetooth/ll/bis/src/main.c index c9d698634abbe2..77bd1d5421d4fb 100644 --- a/tests/bsim/bluetooth/ll/bis/src/main.c +++ b/tests/bsim/bluetooth/ll/bis/src/main.c @@ -124,10 +124,11 @@ static isoal_status_t test_sink_sdu_emit(const struct isoal_sink *si } static isoal_status_t test_sink_sdu_write(void *dbuf, + const size_t sdu_written, const uint8_t *pdu_payload, const size_t consume_len) { - memcpy(dbuf, pdu_payload, consume_len); + memcpy((uint8_t *)dbuf + sdu_written, pdu_payload, consume_len); return ISOAL_STATUS_OK; } From 0a121a9e10e9a44ee47aee7bfb0170b43776d324 Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0687/1389] drivers: flash: stm32: select extended operations correctly Select that the STM32 driver has extended operations feature when the FLASH_STM32_BLOCK_REGISTERS is set. It allows using only block registers extended operation. Signed-off-by: Dawid Niedzwiecki --- drivers/flash/Kconfig.stm32 | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 1ba8c33a7ec62e..4fd5bd4a3e2fe5 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -64,6 +64,7 @@ config FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW config FLASH_STM32_BLOCK_REGISTERS bool "Extended operation for blocking option and control registers" + select FLASH_HAS_EX_OP default n help Enables flash extended operations that can be used to disable access From 26e1e38c6c4885af735d9e1339844002ec67aaa9 Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0688/1389] tests: flash: stm32: add block registers tests Add a test of FLASH_STM32_EX_OP_BLOCK_OPTION_REG and FLASH_STM32_EX_OP_BLOCK_CONTROL_REG extended operations for stm32f4. It verifies that the Option Byte and Control registers are blocked correctly. The registers can be unlock after reboot, so it is needed to separate this test from other tests. Signed-off-by: Dawid Niedzwiecki --- tests/drivers/flash/stm32/prj.conf | 1 - tests/drivers/flash/stm32/src/main.c | 68 +++++++++++++++++++++++++ tests/drivers/flash/stm32/testcase.yaml | 8 +++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/tests/drivers/flash/stm32/prj.conf b/tests/drivers/flash/stm32/prj.conf index 15aa2063b47d61..7f73471f71810b 100644 --- a/tests/drivers/flash/stm32/prj.conf +++ b/tests/drivers/flash/stm32/prj.conf @@ -3,6 +3,5 @@ CONFIG_ZTEST=y CONFIG_FLASH=y CONFIG_FLASH_EX_OP_ENABLED=y -CONFIG_FLASH_STM32_BLOCK_REGISTERS=y CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/drivers/flash/stm32/src/main.c b/tests/drivers/flash/stm32/src/main.c index d4d0bf1c201e8a..ea45ecb846333c 100644 --- a/tests/drivers/flash/stm32/src/main.c +++ b/tests/drivers/flash/stm32/src/main.c @@ -16,6 +16,7 @@ #define TEST_AREA_SIZE FIXED_PARTITION_SIZE(TEST_AREA) #define TEST_AREA_MAX (TEST_AREA_OFFSET + TEST_AREA_SIZE) #define TEST_AREA_DEVICE FIXED_PARTITION_DEVICE(TEST_AREA) +#define TEST_AREA_DEVICE_REG DT_REG_ADDR(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_AREA))) #define EXPECTED_SIZE 512 @@ -179,4 +180,71 @@ ZTEST(flash_stm32, test_stm32_readout_protection_disabled) } #endif +#ifdef CONFIG_FLASH_STM32_BLOCK_REGISTERS + +#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) || defined(CONFIG_FLASH_STM32_READOUT_PROTECTION) +#error Block Register tests unable to run other tests, because of locked registers. +#endif + +int flash_stm32_option_bytes_lock(const struct device *dev, bool enable); + +static bool flash_opt_locked(void) +{ + FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG; + + return regs->OPTCR & FLASH_OPTCR_OPTLOCK; +} + +static void flash_cr_unlock(void) +{ + FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG; + + regs->KEYR = FLASH_KEY1; + regs->KEYR = FLASH_KEY2; +} + +static bool flash_cr_locked(void) +{ + FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG; + + return regs->CR & FLASH_CR_LOCK; +} + +ZTEST(flash_stm32, test_stm32_block_registers) +{ + /* Test OPT lock. */ + TC_PRINT("Unlocking OPT\n"); + flash_stm32_option_bytes_lock(flash_dev, false); + zassert_false(flash_opt_locked(), "Unable to unlock OPT"); + + TC_PRINT("Blocking OPT\n"); + flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_OPTION_REG, (uintptr_t)NULL, NULL); + + zassert_true(flash_opt_locked(), "Blocking OPT didn't lock OPT"); + TC_PRINT("Try to unlock blocked OPT\n"); + __set_FAULTMASK(1); + flash_stm32_option_bytes_lock(flash_dev, false); + /* Clear Bus Fault pending bit */ + SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk; + __set_FAULTMASK(0); + zassert_true(flash_opt_locked(), "OPT unlocked after being blocked"); + + /* Test CR lock. */ + zassert_true(flash_cr_locked(), "CR should be locked by default"); + TC_PRINT("Unlocking CR\n"); + flash_cr_unlock(); + zassert_false(flash_cr_locked(), "Unable to unlock CR"); + TC_PRINT("Blocking CR\n"); + flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_CONTROL_REG, (uintptr_t)NULL, NULL); + zassert_true(flash_cr_locked(), "Blocking CR didn't lock CR"); + __set_FAULTMASK(1); + TC_PRINT("Try to unlock blocked CR\n"); + flash_cr_unlock(); + /* Clear Bus Fault pending bit */ + SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk; + __set_FAULTMASK(0); + zassert_true(flash_cr_locked(), "CR unlocked after being blocked"); +} +#endif + ZTEST_SUITE(flash_stm32, NULL, flash_stm32_setup, NULL, NULL, NULL); diff --git a/tests/drivers/flash/stm32/testcase.yaml b/tests/drivers/flash/stm32/testcase.yaml index fe13b3444fd4f2..c65df8bdffbdc8 100644 --- a/tests/drivers/flash/stm32/testcase.yaml +++ b/tests/drivers/flash/stm32/testcase.yaml @@ -12,6 +12,14 @@ tests: - CONFIG_FLASH_STM32_READOUT_PROTECTION=y filter: dt_compat_enabled("st,stm32f4-flash-controller") and dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") + drivers.flash.stm32.f4.block_registers: + platform_allow: + - nucleo_f429zi + - google_dragonclaw + extra_configs: + - CONFIG_FLASH_STM32_BLOCK_REGISTERS=y + filter: dt_compat_enabled("st,stm32f4-flash-controller") and + dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") drivers.flash.stm32.l4: platform_allow: - nucleo_l452re/stm32l452xx/p From cfe796adce0688aab984548d1cf7cd69150398d5 Mon Sep 17 00:00:00 2001 From: Benjamin Perseghetti Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0689/1389] drivers: pwm: pwm_mcux: make thread safe with mutex. Fixes a bug where more than one thread trying to access different PWM devices can cause erroneous behavior. Co-authored-by: James Goppert Signed-off-by: Benjamin Perseghetti --- drivers/pwm/pwm_mcux.c | 54 +++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/pwm/pwm_mcux.c b/drivers/pwm/pwm_mcux.c index d753682f46e466..617ac3e4b7f7cb 100644 --- a/drivers/pwm/pwm_mcux.c +++ b/drivers/pwm/pwm_mcux.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -35,9 +36,10 @@ struct pwm_mcux_config { struct pwm_mcux_data { uint32_t period_cycles[CHANNEL_COUNT]; pwm_signal_param_t channel[CHANNEL_COUNT]; + struct k_mutex lock; }; -static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, +static int mcux_pwm_set_cycles_internal(const struct device *dev, uint32_t channel, uint32_t period_cycles, uint32_t pulse_cycles, pwm_flags_t flags) { @@ -45,24 +47,6 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, struct pwm_mcux_data *data = dev->data; pwm_level_select_t level; - if (channel >= CHANNEL_COUNT) { - LOG_ERR("Invalid channel"); - return -EINVAL; - } - - if (period_cycles == 0) { - LOG_ERR("Channel can not be set to inactive level"); - return -ENOTSUP; - } - - if (period_cycles > UINT16_MAX) { - /* 16-bit resolution */ - LOG_ERR("Too long period (%u), adjust pwm prescaler!", - period_cycles); - /* TODO: dynamically adjust prescaler */ - return -EINVAL; - } - if (flags & PWM_POLARITY_INVERTED) { level = kPWM_LowTrue; } else { @@ -158,6 +142,36 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, return 0; } +static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + struct pwm_mcux_data *data = dev->data; + int result; + + if (channel >= CHANNEL_COUNT) { + LOG_ERR("Invalid channel"); + return -EINVAL; + } + + if (period_cycles == 0) { + LOG_ERR("Channel can not be set to inactive level"); + return -ENOTSUP; + } + + if (period_cycles > UINT16_MAX) { + /* 16-bit resolution */ + LOG_ERR("Too long period (%u), adjust pwm prescaler!", + period_cycles); + /* TODO: dynamically adjust prescaler */ + return -EINVAL; + } + k_mutex_lock(&data->lock, K_FOREVER); + result = mcux_pwm_set_cycles_internal(dev, channel, period_cycles, pulse_cycles, flags); + k_mutex_unlock(&data->lock); + return result; +} + static int mcux_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles) { @@ -181,6 +195,8 @@ static int pwm_mcux_init(const struct device *dev) status_t status; int i, err; + k_mutex_init(&data->lock); + if (!device_is_ready(config->clock_dev)) { LOG_ERR("clock control device not ready"); return -ENODEV; From c612f36399f59665471e17f617498f96b9c39d1c Mon Sep 17 00:00:00 2001 From: Kamil Paszkiet Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0690/1389] twister: add --report-summary switch Added a switch that show failed/error report from the last run. Default shows all items found. However, you can specify the number of items (e.g. --report-summary 15). It also works well with the --outdir switch Signed-off-by: Kamil Paszkiet --- .../pylib/twister/twisterlib/environment.py | 6 + scripts/pylib/twister/twisterlib/reports.py | 23 ++- scripts/pylib/twister/twisterlib/testplan.py | 145 ++++++++++-------- .../pylib/twister/twisterlib/twister_main.py | 9 +- 4 files changed, 113 insertions(+), 70 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 09ddaa973f8182..ea1eb1856db174 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -602,6 +602,12 @@ def add_parse_arguments(parser = None): help="""Create a report with a custom name. """) + parser.add_argument( + "--report-summary", action="store", nargs='?', type=int, const=0, + help="Show failed/error report from latest run. Default shows all items found. " + "However, you can specify the number of items (e.g. --report-summary 15). " + "It also works well with the --outdir switch.") + parser.add_argument( "--report-suffix", help="""Add a suffix to all generated file names, for example to add a diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index 254f2497d74343..c02bda79c4eaf3 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -26,6 +26,7 @@ def __init__(self, plan, env) -> None: self.env = env self.timestamp = datetime.now().isoformat() self.outdir = os.path.abspath(env.options.outdir) + self.instance_fail_count = plan.instance_fail_count @staticmethod def process_log(log_file): @@ -432,20 +433,36 @@ def footprint_reports(self, report, show_footprint, all_deltas, (report if not last_metrics else "the last twister run."))) def synopsis(self): + if self.env.options.report_summary == 0: + count = self.instance_fail_count + log_txt = f"The following issues were found (showing the all {count} items):" + elif self.env.options.report_summary: + count = self.env.options.report_summary + log_txt = f"The following issues were found " + if count > self.instance_fail_count: + log_txt += f"(presenting {self.instance_fail_count} out of the {count} items requested):" + else: + log_txt += f"(showing the {count} of {self.instance_fail_count} items):" + else: + count = 10 + log_txt = f"The following issues were found (showing the top {count} items):" cnt = 0 example_instance = None detailed_test_id = self.env.options.detailed_test_id for instance in self.instances.values(): if instance.status not in ["passed", "filtered", "skipped"]: - cnt = cnt + 1 + cnt += 1 if cnt == 1: logger.info("-+" * 40) - logger.info("The following issues were found (showing the top 10 items):") + logger.info(log_txt) logger.info(f"{cnt}) {instance.testsuite.name} on {instance.platform.name} {instance.status} ({instance.reason})") example_instance = instance - if cnt == 10: + if cnt == count: break + if cnt == 0 and self.env.options.report_summary is not None: + logger.info("-+" * 40) + logger.info(f"No errors/fails found") if cnt and example_instance: logger.info("") diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index d27e7196843f04..83c5d6b06fdad7 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -17,6 +17,7 @@ import shutil import random import snippets +from colorama import Fore from pathlib import Path from argparse import Namespace @@ -107,6 +108,7 @@ def __init__(self, env=None): self.default_platforms = [] self.load_errors = 0 self.instances = dict() + self.instance_fail_count = 0 self.warnings = 0 self.scenarios = [] @@ -217,7 +219,7 @@ def load(self): else: last_run = os.path.join(self.options.outdir, "twister.json") - if self.options.only_failed: + if self.options.only_failed or self.options.report_summary is not None: self.load_from_file(last_run) self.selected_platforms = set(p.platform.name for p in self.instances.values()) elif self.options.load_tests: @@ -581,72 +583,83 @@ def handle_quarantined_tests(self, instance: TestInstance, plat: Platform): instance.add_filter("Not under quarantine", Filters.QUARANTINE) def load_from_file(self, file, filter_platform=[]): - with open(file, "r") as json_test_plan: - jtp = json.load(json_test_plan) - instance_list = [] - for ts in jtp.get("testsuites", []): - logger.debug(f"loading {ts['name']}...") - testsuite = ts["name"] - - platform = self.get_platform(ts["platform"]) - if filter_platform and platform.name not in filter_platform: - continue - instance = TestInstance(self.testsuites[testsuite], platform, self.env.outdir) - if ts.get("run_id"): - instance.run_id = ts.get("run_id") - - if self.options.device_testing: - tfilter = 'runnable' - else: - tfilter = 'buildable' - instance.run = instance.check_runnable( - self.options.enable_slow, - tfilter, - self.options.fixture, - self.hwm - ) + try: + with open(file, "r") as json_test_plan: + jtp = json.load(json_test_plan) + instance_list = [] + for ts in jtp.get("testsuites", []): + logger.debug(f"loading {ts['name']}...") + testsuite = ts["name"] + + platform = self.get_platform(ts["platform"]) + if filter_platform and platform.name not in filter_platform: + continue + instance = TestInstance(self.testsuites[testsuite], platform, self.env.outdir) + if ts.get("run_id"): + instance.run_id = ts.get("run_id") - instance.metrics['handler_time'] = ts.get('execution_time', 0) - instance.metrics['used_ram'] = ts.get("used_ram", 0) - instance.metrics['used_rom'] = ts.get("used_rom",0) - instance.metrics['available_ram'] = ts.get('available_ram', 0) - instance.metrics['available_rom'] = ts.get('available_rom', 0) - - status = ts.get('status', None) - reason = ts.get("reason", "Unknown") - if status in ["error", "failed"]: - instance.status = None - instance.reason = None - instance.retries += 1 - # test marked as passed (built only) but can run when - # --test-only is used. Reset status to capture new results. - elif status == 'passed' and instance.run and self.options.test_only: - instance.status = None - instance.reason = None - else: - instance.status = status - instance.reason = reason - - self.handle_quarantined_tests(instance, platform) - - for tc in ts.get('testcases', []): - identifier = tc['identifier'] - tc_status = tc.get('status', None) - tc_reason = None - # we set reason only if status is valid, it might have been - # reset above... - if instance.status: - tc_reason = tc.get('reason') - if tc_status: - case = instance.set_case_status_by_name(identifier, tc_status, tc_reason) - case.duration = tc.get('execution_time', 0) - if tc.get('log'): - case.output = tc.get('log') - - - instance.create_overlay(platform, self.options.enable_asan, self.options.enable_ubsan, self.options.enable_coverage, self.options.coverage_platform) - instance_list.append(instance) - self.add_instances(instance_list) + if self.options.device_testing: + tfilter = 'runnable' + else: + tfilter = 'buildable' + instance.run = instance.check_runnable( + self.options.enable_slow, + tfilter, + self.options.fixture, + self.hwm + ) + + instance.metrics['handler_time'] = ts.get('execution_time', 0) + instance.metrics['used_ram'] = ts.get("used_ram", 0) + instance.metrics['used_rom'] = ts.get("used_rom",0) + instance.metrics['available_ram'] = ts.get('available_ram', 0) + instance.metrics['available_rom'] = ts.get('available_rom', 0) + + status = ts.get('status', None) + reason = ts.get("reason", "Unknown") + if status in ["error", "failed"]: + if self.options.report_summary is not None: + if status == "error": status = "ERROR" + elif status == "failed": status = "FAILED" + instance.status = Fore.RED + status + Fore.RESET + instance.reason = reason + self.instance_fail_count += 1 + else: + instance.status = None + instance.reason = None + instance.retries += 1 + # test marked as passed (built only) but can run when + # --test-only is used. Reset status to capture new results. + elif status == 'passed' and instance.run and self.options.test_only: + instance.status = None + instance.reason = None + else: + instance.status = status + instance.reason = reason + + self.handle_quarantined_tests(instance, platform) + + for tc in ts.get('testcases', []): + identifier = tc['identifier'] + tc_status = tc.get('status', None) + tc_reason = None + # we set reason only if status is valid, it might have been + # reset above... + if instance.status: + tc_reason = tc.get('reason') + if tc_status: + case = instance.set_case_status_by_name(identifier, tc_status, tc_reason) + case.duration = tc.get('execution_time', 0) + if tc.get('log'): + case.output = tc.get('log') + + + instance.create_overlay(platform, self.options.enable_asan, self.options.enable_ubsan, self.options.enable_coverage, self.options.coverage_platform) + instance_list.append(instance) + self.add_instances(instance_list) + except FileNotFoundError as e: + logger.error(f"{e}") + return 1 def apply_filters(self, **kwargs): diff --git a/scripts/pylib/twister/twisterlib/twister_main.py b/scripts/pylib/twister/twisterlib/twister_main.py index 30656544b94faa..f61880c1b0528e 100644 --- a/scripts/pylib/twister/twisterlib/twister_main.py +++ b/scripts/pylib/twister/twisterlib/twister_main.py @@ -73,7 +73,7 @@ def main(options): previous_results = None # Cleanup - if options.no_clean or options.only_failed or options.test_only: + if options.no_clean or options.only_failed or options.test_only or options.report_summary is not None: if os.path.exists(options.outdir): print("Keeping artifacts untouched") elif options.last_metrics: @@ -160,6 +160,13 @@ def main(options): report.json_report(options.save_tests) return 0 + if options.report_summary is not None: + if options.report_summary < 0: + logger.error("The report summary value cannot be less than 0") + return 1 + report.synopsis() + return 0 + if options.device_testing and not options.build_only: print("\nDevice testing on:") hwm.dump(filtered=tplan.selected_platforms) From 5a204cec01f2943393d16ce5a203093bbe230b79 Mon Sep 17 00:00:00 2001 From: Kamil Paszkiet Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0691/1389] scripts: tests: Blackbox test expansion - report summary add test for report summary switch Signed-off-by: Kamil Paszkiet --- scripts/tests/twister/test_testplan.py | 3 +- .../agnostic/group1/subgroup1/CMakeLists.txt | 8 ++ .../agnostic/group1/subgroup1/prj.conf | 1 + .../agnostic/group1/subgroup1/src/main.c | 26 +++++++ .../agnostic/group1/subgroup1/test_data.yaml | 11 +++ .../agnostic/group1/subgroup2/CMakeLists.txt | 8 ++ .../agnostic/group1/subgroup2/prj.conf | 1 + .../agnostic/group1/subgroup2/src/main.c | 22 ++++++ .../agnostic/group1/subgroup2/test_data.yaml | 11 +++ .../agnostic/group1/subgroup3/CMakeLists.txt | 8 ++ .../agnostic/group1/subgroup3/prj.conf | 1 + .../agnostic/group1/subgroup3/src/main.c | 23 ++++++ .../agnostic/group1/subgroup3/test_data.yaml | 11 +++ .../agnostic/group1/subgroup4/CMakeLists.txt | 8 ++ .../agnostic/group1/subgroup4/prj.conf | 1 + .../agnostic/group1/subgroup4/src/main.c | 23 ++++++ .../agnostic/group1/subgroup4/test_data.yaml | 11 +++ scripts/tests/twister_blackbox/test_report.py | 75 ++++++++++++++++++- 18 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c create mode 100644 scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml diff --git a/scripts/tests/twister/test_testplan.py b/scripts/tests/twister/test_testplan.py index 7f93629922365b..daa732db522a05 100644 --- a/scripts/tests/twister/test_testplan.py +++ b/scripts/tests/twister/test_testplan.py @@ -709,6 +709,7 @@ def test_testplan_load( testplan.testsuites['ts1'].name = 'ts1' testplan.testsuites['ts2'].name = 'ts2' testplan.options = mock.Mock( + report_summary=None, outdir=tmp_path, report_suffix=report_suffix, only_failed=only_failed, @@ -1451,7 +1452,7 @@ def get_platform(name): ts5.name = 'TestSuite 5' testplan = TestPlan(env=mock.Mock(outdir=os.path.join('out', 'dir'))) - testplan.options = mock.Mock(device_testing=device_testing, test_only=True) + testplan.options = mock.Mock(device_testing=device_testing, test_only=True, report_summary=None) testplan.testsuites = { 'TestSuite 1': ts1, 'TestSuite 2': ts2, diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt new file mode 100644 index 00000000000000..635c696edf9d52 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf new file mode 100644 index 00000000000000..9467c2926896dd --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c new file mode 100644 index 00000000000000..3c250486af6590 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_1_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_1_tests, test_assert) +{ + zassert_true(1, "1 was false"); + zassert_false(0, "0 was true"); + zassert_is_null(NULL, "NULL was not NULL"); + zassert_not_null("foo", "\"foo\" was NULL"); + zassert_equal(1, 1, "1 was not equal to 1"); + zassert_equal_ptr(NULL, NULL, "NULL was not equal to NULL"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml new file mode 100644 index 00000000000000..e42250e6b248c4 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup1: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt new file mode 100644 index 00000000000000..635c696edf9d52 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf new file mode 100644 index 00000000000000..9467c2926896dd --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c new file mode 100644 index 00000000000000..d896f500c9e454 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_2_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_2_tests, test_assert) +{ + zassert_true(0, "1 was false"); + zassert_false(1, "0 was true"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml new file mode 100644 index 00000000000000..b2813ad46e12c2 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup2: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt new file mode 100644 index 00000000000000..635c696edf9d52 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf new file mode 100644 index 00000000000000..9467c2926896dd --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c new file mode 100644 index 00000000000000..04b4de0e0867e0 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_2_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_2_tests, test_assert) +{ + dummy + zassert_true(0, "1 was false"); + zassert_false(1, "0 was true"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml new file mode 100644 index 00000000000000..c5c9486c735cbb --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup3: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt new file mode 100644 index 00000000000000..635c696edf9d52 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf new file mode 100644 index 00000000000000..9467c2926896dd --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c new file mode 100644 index 00000000000000..04b4de0e0867e0 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_2_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_2_tests, test_assert) +{ + dummy + zassert_true(0, "1 was false"); + zassert_false(1, "0 was true"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml new file mode 100644 index 00000000000000..a4957e6f5ebb34 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup4: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_report.py b/scripts/tests/twister_blackbox/test_report.py index 80f8f722a3eb26..e116bea3da1eb5 100644 --- a/scripts/tests/twister_blackbox/test_report.py +++ b/scripts/tests/twister_blackbox/test_report.py @@ -13,10 +13,12 @@ import pytest import shutil import sys +import re from lxml import etree -from conftest import TEST_DATA, ZEPHYR_BASE, testsuite_filename_mock +# pylint: disable=no-name-in-module +from conftest import TEST_DATA, ZEPHYR_BASE, testsuite_filename_mock, clear_log_in_test from twisterlib.testplan import TestPlan @@ -106,6 +108,15 @@ class TestReport: "TEST_LOG_FILE.log" ), ] + TESTDATA_7 = [ + ( + os.path.join(TEST_DATA, 'tests', 'one_fail_two_error_one_pass'), + ['qemu_x86'], + [r'one_fail_two_error_one_pass.agnostic.group1.subgroup2 on qemu_x86 FAILED \(Failed\)', + r'one_fail_two_error_one_pass.agnostic.group1.subgroup3 on qemu_x86 ERROR \(Build failure\)', + r'one_fail_two_error_one_pass.agnostic.group1.subgroup4 on qemu_x86 ERROR \(Build failure\)'], + ) + ] @classmethod def setup_class(cls): @@ -397,3 +408,65 @@ def test_enable_size_report(self, out_path): if ts['name'] == expected_rel_path and not 'reason' in ts ] ) + + @pytest.mark.parametrize( + 'test_path, test_platforms, expected_content', + TESTDATA_7, + ids=[ + 'Report summary test' + ] + ) + + def test_report_summary(self, out_path, capfd, test_path, test_platforms, expected_content): + args = ['-i', '--outdir', out_path, '-T', test_path] + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + assert str(sys_exit.value) == '1' + + capfd.readouterr() + + clear_log_in_test() + + args += ['--report-summary'] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + for line in expected_content: + result = re.search(line, err) + assert result, f'missing information in log: {line}' + + capfd.readouterr() + + clear_log_in_test() + + args = ['-i', '--outdir', out_path, '-T', test_path] + \ + ['--report-summary', '2'] + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + lines=0 + for line in expected_content: + result = re.search(line, err) + if result: lines += 1 + assert lines == 2, f'too many or too few lines' From 45c89b6d3a7dbeeeaefe8e0e3714c60d973acc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:39:02 +0200 Subject: [PATCH 0692/1389] drivers: esp32: i2c: configure clock frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be able to configure the clock frequency during runtime using `i2c_configure()` and be able to use `i2c_get_config()` of the i2c api for the esp32. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_esp32.c | 81 ++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/drivers/i2c/i2c_esp32.c b/drivers/i2c/i2c_esp32.c index fdb78a2c6ed32b..c6554afa53903f 100644 --- a/drivers/i2c/i2c_esp32.c +++ b/drivers/i2c/i2c_esp32.c @@ -91,7 +91,6 @@ struct i2c_esp32_config { int irq_source; - const uint32_t default_config; const uint32_t bitrate; const uint32_t scl_timeout; }; @@ -262,14 +261,17 @@ static int i2c_esp32_recover(const struct device *dev) return 0; } -static void IRAM_ATTR i2c_esp32_configure_timeout(const struct device *dev) +static void IRAM_ATTR i2c_esp32_configure_bitrate(const struct device *dev, uint32_t bitrate) { const struct i2c_esp32_config *config = dev->config; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; + i2c_clock_source_t sclk = i2c_get_clk_src(bitrate); + uint32_t clk_freq_mhz = i2c_get_src_clk_freq(sclk); + + i2c_hal_set_bus_timing(&data->hal, bitrate, sclk, clk_freq_mhz); + if (config->scl_timeout > 0) { - i2c_clock_source_t sclk = i2c_get_clk_src(config->bitrate); - uint32_t clk_freq_mhz = i2c_get_src_clk_freq(sclk); uint32_t timeout_cycles = MIN(I2C_LL_MAX_TIMEOUT, clk_freq_mhz / MHZ(1) * config->scl_timeout); i2c_ll_set_tout(data->hal.dev, timeout_cycles); @@ -281,20 +283,15 @@ static void IRAM_ATTR i2c_esp32_configure_timeout(const struct device *dev) */ i2c_ll_set_tout(data->hal.dev, I2C_LL_MAX_TIMEOUT); } + + i2c_ll_update(data->hal.dev); } -static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) +static void i2c_esp32_configure_data_mode(const struct device *dev) { const struct i2c_esp32_config *config = dev->config; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; - if (!(dev_config & I2C_MODE_CONTROLLER)) { - LOG_ERR("Only I2C Master mode supported."); - return -ENOTSUP; - } - - data->dev_config = dev_config; - i2c_trans_mode_t tx_mode = I2C_DATA_MODE_MSB_FIRST; i2c_trans_mode_t rx_mode = I2C_DATA_MODE_MSB_FIRST; @@ -306,21 +303,59 @@ static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) rx_mode = I2C_DATA_MODE_LSB_FIRST; } - i2c_hal_master_init(&data->hal); i2c_ll_set_data_mode(data->hal.dev, tx_mode, rx_mode); i2c_ll_set_filter(data->hal.dev, I2C_FILTER_CYC_NUM_DEF); i2c_ll_update(data->hal.dev); - if (config->bitrate == 0) { +} + +static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) +{ + const struct i2c_esp32_config *config = dev->config; + struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; + uint32_t bitrate; + + if (!(dev_config & I2C_MODE_CONTROLLER)) { + LOG_ERR("Only I2C Master mode supported."); + return -ENOTSUP; + } + + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + bitrate = KHZ(100); + break; + case I2C_SPEED_FAST: + bitrate = KHZ(400); + break; + case I2C_SPEED_FAST_PLUS: + bitrate = MHZ(1); + break; + default: LOG_ERR("Error configuring I2C speed."); return -ENOTSUP; } - i2c_clock_source_t sclk = i2c_get_clk_src(config->bitrate); + k_sem_take(&data->transfer_sem, K_FOREVER); - i2c_hal_set_bus_timing(&data->hal, config->bitrate, sclk, i2c_get_src_clk_freq(sclk)); - i2c_esp32_configure_timeout(dev); - i2c_ll_update(data->hal.dev); + data->dev_config = dev_config; + + i2c_esp32_configure_bitrate(dev, bitrate); + + k_sem_give(&data->transfer_sem); + + return 0; +} + +static int i2c_esp32_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; + + if (data->dev_config == 0) { + LOG_ERR("I2C controller not configured"); + return -EIO; + } + + *config = data->dev_config; return 0; } @@ -694,6 +729,7 @@ static void IRAM_ATTR i2c_esp32_isr(void *arg) static const struct i2c_driver_api i2c_esp32_driver_api = { .configure = i2c_esp32_configure, + .get_config = i2c_esp32_get_config, .transfer = i2c_esp32_transfer, .recover_bus = i2c_esp32_recover }; @@ -701,9 +737,9 @@ static const struct i2c_driver_api i2c_esp32_driver_api = { static int IRAM_ATTR i2c_esp32_init(const struct device *dev) { const struct i2c_esp32_config *config = dev->config; -#ifndef SOC_I2C_SUPPORT_HW_CLR_BUS struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; +#ifndef SOC_I2C_SUPPORT_HW_CLR_BUS if (!gpio_is_ready_dt(&config->scl.gpio)) { LOG_ERR("SCL GPIO device is not ready"); return -EINVAL; @@ -730,7 +766,11 @@ static int IRAM_ATTR i2c_esp32_init(const struct device *dev) esp_intr_alloc(config->irq_source, 0, i2c_esp32_isr, (void *)dev, NULL); - return i2c_esp32_configure(dev, config->default_config); + i2c_hal_master_init(&data->hal); + + i2c_esp32_configure_data_mode(dev); + + return i2c_esp32_configure(dev, I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); } #define I2C(idx) DT_NODELABEL(i2c##idx) @@ -788,7 +828,6 @@ static int IRAM_ATTR i2c_esp32_init(const struct device *dev) .irq_source = ETS_I2C_EXT##idx##_INTR_SOURCE, \ .bitrate = I2C_FREQUENCY(idx), \ .scl_timeout = I2C_ESP32_TIMEOUT(idx), \ - .default_config = I2C_MODE_CONTROLLER, \ }; \ I2C_DEVICE_DT_DEFINE(I2C(idx), i2c_esp32_init, NULL, &i2c_esp32_data_##idx, \ &i2c_esp32_config_##idx, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ From 176dbfe5635e7c6e93544ef76306daffcbcfba26 Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0693/1389] dts: set the `riscv,isa` property for virt-based targets This commit makes the devicetrees of the targets that are based on the QEMU `virt` machine more consistent with the rest of the RISC-V targets in Zephyr by: * adding the `riscv,isa` property * adding a compatible string which uniquely identifies the `virt` core Signed-off-by: Filip Kokosinski --- boards/qemu/riscv32/qemu_riscv32.dts | 2 +- .../qemu_riscv32_qemu_virt_riscv32_smp.dts | 2 +- boards/qemu/riscv32e/qemu_riscv32e.dts | 2 +- boards/qemu/riscv64/qemu_riscv64.dts | 2 +- .../qemu_riscv64_qemu_virt_riscv64_smp.dts | 2 +- dts/bindings/cpu/qemu,riscv-virt.yaml | 9 ++++ dts/riscv/{virt.dtsi => qemu/virt-riscv.dtsi} | 16 +++---- dts/riscv/qemu/virt-riscv32.dtsi | 45 +++++++++++++++++++ dts/riscv/qemu/virt-riscv64.dtsi | 45 +++++++++++++++++++ 9 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 dts/bindings/cpu/qemu,riscv-virt.yaml rename dts/riscv/{virt.dtsi => qemu/virt-riscv.dtsi} (91%) create mode 100644 dts/riscv/qemu/virt-riscv32.dtsi create mode 100644 dts/riscv/qemu/virt-riscv64.dtsi diff --git a/boards/qemu/riscv32/qemu_riscv32.dts b/boards/qemu/riscv32/qemu_riscv32.dts index 6c820813021c6d..2c38ca1da1d7c1 100644 --- a/boards/qemu/riscv32/qemu_riscv32.dts +++ b/boards/qemu/riscv32/qemu_riscv32.dts @@ -2,7 +2,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts index 6c820813021c6d..2c38ca1da1d7c1 100644 --- a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts +++ b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts @@ -2,7 +2,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv32e/qemu_riscv32e.dts b/boards/qemu/riscv32e/qemu_riscv32e.dts index 7596ee0d6eb1d3..403d75cb742066 100644 --- a/boards/qemu/riscv32e/qemu_riscv32e.dts +++ b/boards/qemu/riscv32e/qemu_riscv32e.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv64/qemu_riscv64.dts b/boards/qemu/riscv64/qemu_riscv64.dts index fb96f6d3d38a0a..673d46680192f5 100644 --- a/boards/qemu/riscv64/qemu_riscv64.dts +++ b/boards/qemu/riscv64/qemu_riscv64.dts @@ -3,7 +3,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts b/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts index fb96f6d3d38a0a..673d46680192f5 100644 --- a/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts +++ b/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts @@ -3,7 +3,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/dts/bindings/cpu/qemu,riscv-virt.yaml b/dts/bindings/cpu/qemu,riscv-virt.yaml new file mode 100644 index 00000000000000..c4c5a8b174eca0 --- /dev/null +++ b/dts/bindings/cpu/qemu,riscv-virt.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +description: QEMU RISC-V virt machine CPU node + +compatible: "qemu,riscv-virt" + +include: riscv,cpus.yaml diff --git a/dts/riscv/virt.dtsi b/dts/riscv/qemu/virt-riscv.dtsi similarity index 91% rename from dts/riscv/virt.dtsi rename to dts/riscv/qemu/virt-riscv.dtsi index 20873731c6e9dd..8329a1ec62b8c8 100644 --- a/dts/riscv/virt.dtsi +++ b/dts/riscv/qemu/virt-riscv.dtsi @@ -41,7 +41,7 @@ device_type = "cpu"; reg = < 0x00 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic0: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -55,7 +55,7 @@ device_type = "cpu"; reg = < 0x01 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic1: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -69,7 +69,7 @@ device_type = "cpu"; reg = < 0x02 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic2: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -83,7 +83,7 @@ device_type = "cpu"; reg = < 0x03 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic3: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -97,7 +97,7 @@ device_type = "cpu"; reg = < 0x04 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic4: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -111,7 +111,7 @@ device_type = "cpu"; reg = < 0x05 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic5: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -125,7 +125,7 @@ device_type = "cpu"; reg = < 0x06 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic6: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -139,7 +139,7 @@ device_type = "cpu"; reg = < 0x07 >; status = "okay"; - compatible = "riscv"; + compatible = "qemu,riscv-virt", "riscv"; hlic7: interrupt-controller { compatible = "riscv,cpu-intc"; diff --git a/dts/riscv/qemu/virt-riscv32.dtsi b/dts/riscv/qemu/virt-riscv32.dtsi new file mode 100644 index 00000000000000..25d769d5183a95 --- /dev/null +++ b/dts/riscv/qemu/virt-riscv32.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + cpus { + cpu@0 { + riscv,isa = "rv32gc"; + }; + + cpu@1 { + riscv,isa = "rv32gc"; + }; + + cpu@2 { + riscv,isa = "rv32gc"; + }; + + cpu@3 { + riscv,isa = "rv32gc"; + }; + + cpu@4 { + riscv,isa = "rv32gc"; + }; + + cpu@5 { + riscv,isa = "rv32gc"; + }; + + cpu@6 { + riscv,isa = "rv32gc"; + }; + + cpu@7 { + riscv,isa = "rv32gc"; + }; + }; +}; diff --git a/dts/riscv/qemu/virt-riscv64.dtsi b/dts/riscv/qemu/virt-riscv64.dtsi new file mode 100644 index 00000000000000..936f0a18815261 --- /dev/null +++ b/dts/riscv/qemu/virt-riscv64.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + cpus { + cpu@0 { + riscv,isa = "rv64gc"; + }; + + cpu@1 { + riscv,isa = "rv64gc"; + }; + + cpu@2 { + riscv,isa = "rv64gc"; + }; + + cpu@3 { + riscv,isa = "rv64gc"; + }; + + cpu@4 { + riscv,isa = "rv64gc"; + }; + + cpu@5 { + riscv,isa = "rv64gc"; + }; + + cpu@6 { + riscv,isa = "rv64gc"; + }; + + cpu@7 { + riscv,isa = "rv64gc"; + }; + }; +}; From a5be740ef2d8d30a104e9e19bcb7207c8b54b057 Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0694/1389] drivers/console/xtensa_sim_console: force `\r\n` byte sequence Force `\r\n` byte sequence for newline for the Xtensa simulator console driver. This effectively mirrors the behavior of the UART console driver. Signed-off-by: Filip Kokosinski --- drivers/console/xtensa_sim_console.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/console/xtensa_sim_console.c b/drivers/console/xtensa_sim_console.c index 316162ddc0c1af..1d52f93af73e23 100644 --- a/drivers/console/xtensa_sim_console.c +++ b/drivers/console/xtensa_sim_console.c @@ -25,6 +25,14 @@ int arch_printk_char_out(int c) register int ret_err __asm__ ("a3"); buf[0] = (char)c; + + if (buf[0] == '\n') { + buf[1] = buf[0]; + buf[0] = '\r'; + a3++; + a5++; + } + __asm__ volatile ("simcall" : "=a" (ret_val), "=a" (ret_err) : "a" (a2), "a" (a3), "a" (a4), "a" (a5) From 46cd097a2e2150ee6580ef00defc6d77f9e175a0 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0695/1389] tests: arch arm: runtime nmi testing with dcache for ARM V7 For ARMV7 devices, use preferably the sys_cache_data_flush_all function to flush the data cache Signed-off-by: Francois Ramu --- tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c b/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c index 79a4bbedca3c0c..87e4237d96136a 100644 --- a/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c +++ b/tests/arch/arm/arm_runtime_nmi/src/arm_runtime_nmi.c @@ -12,6 +12,7 @@ #include #include #include +#include /* on v8m arch the nmi pend bit is renamed to pend nmi map it to old name */ #ifndef SCB_ICSR_NMIPENDSET_Msk @@ -67,7 +68,7 @@ ZTEST(arm_runtime_nmi_fn, test_arm_runtime_nmi) #ifdef ARM_CACHEL1_ARMV7_H /* Flush Data Cache now if enabled */ if (IS_ENABLED(CONFIG_DCACHE)) { - SCB_CleanDCache(); + sys_cache_data_flush_all(); } #endif /* ARM_CACHEL1_ARMV7_H */ zassert_true(nmi_triggered, "Isr not triggered!\n"); From 1ef5094b91398b805019ba655828959a91f90389 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0696/1389] shell: devmem: correct number of `mand` and `opt` of `cmd_dump` According to the `SHELL_CMD_ARG` macro, the `mand` argument of `cmd_dump` should be 5, including the command name itself, `dump`. Meanwhile, the `opt` should be 2, as this value describes the optional field, which is [-w ]. Signed-off-by: Pisit Sawangvonganan --- subsys/shell/modules/devmem_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/shell/modules/devmem_service.c b/subsys/shell/modules/devmem_service.c index e5a7a06f35b82a..503ab57b2f579d 100644 --- a/subsys/shell/modules/devmem_service.c +++ b/subsys/shell/modules/devmem_service.c @@ -349,7 +349,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_devmem, SHELL_CMD_ARG(dump, NULL, "Usage:\n" "devmem dump -a
-s [-w ]\n", - cmd_dump, 4, 6), + cmd_dump, 5, 2), SHELL_CMD_ARG(load, NULL, "Usage:\n" "devmem load [options] [address]\n" From e1f1baa861c2786173f28ce9fe3d76da2d400991 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0697/1389] shell: devmem: address `cmd_dump` multiple call problem Call `getopt_init()` to reset `state->optind` instead of directly setting `optind = 1`. The `getopt()` function uses `getopt_state` from `getopt_state_get` for state handling, so `getopt_init()` should be called to correctly run the command again. Signed-off-by: Pisit Sawangvonganan --- lib/posix/options/getopt/getopt.h | 2 +- subsys/shell/modules/devmem_service.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/posix/options/getopt/getopt.h b/lib/posix/options/getopt/getopt.h index 4dfcc8b5f57b11..3ae474f4304fcb 100644 --- a/lib/posix/options/getopt/getopt.h +++ b/lib/posix/options/getopt/getopt.h @@ -48,7 +48,7 @@ struct option { int val; }; -/* Function intializes getopt_state structure for current thread */ +/* Function initializes getopt_state structure for current thread */ void getopt_init(void); /* Function returns getopt_state structure for the current thread. */ diff --git a/subsys/shell/modules/devmem_service.c b/subsys/shell/modules/devmem_service.c index 503ab57b2f579d..8b649e8093b868 100644 --- a/subsys/shell/modules/devmem_service.c +++ b/subsys/shell/modules/devmem_service.c @@ -19,6 +19,10 @@ #include #include +#ifndef CONFIG_NATIVE_LIBC +extern void getopt_init(void); +#endif + static inline bool is_ascii(uint8_t data) { return (data >= 0x30 && data <= 0x39) || (data >= 0x61 && data <= 0x66) || @@ -101,6 +105,9 @@ static int cmd_dump(const struct shell *sh, size_t argc, char **argv) mem_addr_t addr = -1; optind = 1; +#ifndef CONFIG_NATIVE_LIBC + getopt_init(); +#endif while ((rv = getopt(argc, argv, "a:s:w:")) != -1) { switch (rv) { case 'a': From 0d81d224b2abaf4bd5a8c4c635eb57f1dc673f9d Mon Sep 17 00:00:00 2001 From: Rafal Dyla Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0698/1389] manifest: Adding nRF Services library Adding nRF Services library to the hal-nordic repo Signed-off-by: Rafal Dyla --- .../nrf54h20dk_nrf54h20-memory_map.dtsi | 2 +- .../nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 6 + .../nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts | 8 + modules/hal_nordic/CMakeLists.txt | 3 +- modules/hal_nordic/Kconfig | 1 + modules/hal_nordic/nrfs/CMakeLists.txt | 41 ++ modules/hal_nordic/nrfs/Kconfig | 116 ++++++ modules/hal_nordic/nrfs/backends/Kconfig | 28 ++ .../nrfs/backends/nrfs_backend_ipc_service.c | 226 +++++++++++ .../nrfs/backends/nrfs_backend_ipc_service.h | 93 +++++ modules/hal_nordic/nrfs/dvfs/CMakeLists.txt | 5 + modules/hal_nordic/nrfs/dvfs/Kconfig | 40 ++ modules/hal_nordic/nrfs/dvfs/ld_dvfs.c | 354 ++++++++++++++++++ modules/hal_nordic/nrfs/dvfs/ld_dvfs.h | 66 ++++ .../hal_nordic/nrfs/dvfs/ld_dvfs_handler.c | 292 +++++++++++++++ .../hal_nordic/nrfs/dvfs/ld_dvfs_handler.h | 33 ++ modules/hal_nordic/nrfs/nrfs_config.h | 47 +++ soc/nordic/nrf54h/Kconfig | 9 + 18 files changed, 1368 insertions(+), 2 deletions(-) create mode 100644 modules/hal_nordic/nrfs/CMakeLists.txt create mode 100644 modules/hal_nordic/nrfs/Kconfig create mode 100644 modules/hal_nordic/nrfs/backends/Kconfig create mode 100644 modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c create mode 100644 modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h create mode 100644 modules/hal_nordic/nrfs/dvfs/CMakeLists.txt create mode 100644 modules/hal_nordic/nrfs/dvfs/Kconfig create mode 100644 modules/hal_nordic/nrfs/dvfs/ld_dvfs.c create mode 100644 modules/hal_nordic/nrfs/dvfs/ld_dvfs.h create mode 100644 modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c create mode 100644 modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h create mode 100644 modules/hal_nordic/nrfs/nrfs_config.h diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 91899e2cf86b68..5ea59e94697135 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -72,7 +72,7 @@ shared_ram20_region: memory@2f88f000 { compatible = "nordic,owned-memory"; reg = <0x2f88f000 DT_SIZE_K(4)>; - status = "disabled"; + status = "okay"; perm-read; perm-write; #address-cells = <1>; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 476c076fae115f..6e694191477968 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -38,6 +38,7 @@ sw1 = &button1; sw2 = &button2; sw3 = &button3; + ipc-to-cpusys = &cpuapp_cpusys_ipc; }; buttons { @@ -117,6 +118,10 @@ status = "okay"; }; +&cpusys_vevif { + status = "okay"; +}; + &cpusec_cpuapp_ipc { mbox-names = "tx", "rx"; tx-region = <&cpuapp_cpusec_ipc_shm>; @@ -133,6 +138,7 @@ ipc0: &cpuapp_cpurad_ipc { }; &cpuapp_cpusys_ipc { + status = "okay"; mbox-names = "rx", "tx"; tx-region = <&cpuapp_cpusys_ipc_shm>; rx-region = <&cpusys_cpuapp_ipc_shm>; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index 20109b66180e6f..f8aff548436c8f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -29,6 +29,9 @@ zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; }; + aliases { + ipc-to-cpusys = &cpurad_cpusys_ipc; + }; }; &shared_ram3x_region { @@ -51,6 +54,10 @@ status = "okay"; }; +&cpusys_vevif { + status = "okay"; +}; + &cpusec_cpurad_ipc { mbox-names = "tx", "rx"; tx-region = <&cpurad_cpusec_ipc_shm>; @@ -67,6 +74,7 @@ ipc0: &cpuapp_cpurad_ipc { }; &cpurad_cpusys_ipc { + status = "okay"; mbox-names = "rx", "tx"; tx-region = <&cpurad_cpusys_ipc_shm>; rx-region = <&cpusys_cpurad_ipc_shm>; diff --git a/modules/hal_nordic/CMakeLists.txt b/modules/hal_nordic/CMakeLists.txt index c4a7134935cddc..3ee6356cc97c79 100644 --- a/modules/hal_nordic/CMakeLists.txt +++ b/modules/hal_nordic/CMakeLists.txt @@ -6,12 +6,13 @@ if (CONFIG_NRF_802154_RADIO_DRIVER OR CONFIG_NRF_802154_SERIALIZATION) endif (CONFIG_NRF_802154_RADIO_DRIVER OR CONFIG_NRF_802154_SERIALIZATION) add_subdirectory_ifdef(CONFIG_HAS_NRFX nrfx) +add_subdirectory_ifdef(CONFIG_HAS_NRFS nrfs) if(CONFIG_NRF_REGTOOL_GENERATE_UICR) list(APPEND nrf_regtool_components GENERATE:UICR) endif() if(DEFINED nrf_regtool_components) - find_package(nrf-regtool 5.1.0 + find_package(nrf-regtool 5.2.0 COMPONENTS ${nrf_regtool_components} PATHS ${CMAKE_CURRENT_LIST_DIR}/nrf-regtool NO_CMAKE_PATH diff --git a/modules/hal_nordic/Kconfig b/modules/hal_nordic/Kconfig index c9cc93e93293cc..a7d55e4620aa5d 100644 --- a/modules/hal_nordic/Kconfig +++ b/modules/hal_nordic/Kconfig @@ -235,5 +235,6 @@ endif # NRF_802154_RADIO_DRIVER || NRF_802154_SERIALIZATION endmenu # HAS_NORDIC_DRIVERS +rsource "nrfs/Kconfig" rsource "nrfx/Kconfig" rsource "Kconfig.nrf_regtool" diff --git a/modules/hal_nordic/nrfs/CMakeLists.txt b/modules/hal_nordic/nrfs/CMakeLists.txt new file mode 100644 index 00000000000000..c601b8a4233c96 --- /dev/null +++ b/modules/hal_nordic/nrfs/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + + +if(CONFIG_NRFS) + zephyr_library() + if(NOT DEFINED NRFS_DIR) + set(NRFS_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/nrfs CACHE PATH "nrfs directory") + endif() + + set(INC_DIR ${NRFS_DIR}/include) + set(SRC_DIR ${NRFS_DIR}/src) + set(HELPERS_DIR ${NRFS_DIR}/helpers) + + zephyr_include_directories(${INC_DIR}) + zephyr_include_directories(${INC_DIR}/services) + zephyr_include_directories(${HELPERS_DIR}) + zephyr_include_directories(.) + zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backends) + zephyr_include_directories_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN ${CMAKE_CURRENT_SOURCE_DIR}/dvfs) + + zephyr_library_sources(${HELPERS_DIR}/dvfs_oppoint.c) + + if(CONFIG_NRFS_LOCAL_DOMAIN) + zephyr_library_sources_ifdef(CONFIG_NRFS_CLOCK_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_clock.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_DIAG_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_diag.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_DVFS_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_dvfs.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_MRAM_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_mram.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_PMIC_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_pmic.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_RESET_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_reset.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_TEMP_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_temp.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_VBUS_DETECTOR_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_usb.c) + zephyr_library_sources(${SRC_DIR}/internal/nrfs_dispatcher.c) + add_subdirectory_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN dvfs) + + if(CONFIG_NRFS_DIAG_SERVICE_ENABLED) + message(WARNING "This service is for Nordic Semiconductor INTERNAL purposes ONLY. Use it with caution due to risk of hardware damage!") + endif() + endif() + zephyr_library_sources_ifdef(CONFIG_NRFS_LOCAL_DOMAIN backends/nrfs_backend_ipc_service.c) +endif() diff --git a/modules/hal_nordic/nrfs/Kconfig b/modules/hal_nordic/nrfs/Kconfig new file mode 100644 index 00000000000000..b4f6715fdd2d8f --- /dev/null +++ b/modules/hal_nordic/nrfs/Kconfig @@ -0,0 +1,116 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config HAS_NRFS + bool + +menu "nRF Services" + depends on HAS_NRFS + +config NRFS_HAS_CLOCK_SERVICE + bool + +config NRFS_HAS_CONST_LATENCY_SERVICE + bool + +config NRFS_HAS_DIAG_SERVICE + bool + +config NRFS_HAS_DVFS_SERVICE + bool + +config NRFS_HAS_MRAM_SERVICE + bool + +config NRFS_HAS_PMIC_SERVICE + bool + +config NRFS_HAS_RESET_SERVICE + bool + +config NRFS_HAS_TEMP_SERVICE + bool + +config NRFS_HAS_VBUS_DETECTOR_SERVICE + bool + +config NRFS + bool "nRF Services Support" + select NRFS_LOCAL_DOMAIN if (SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD) + depends on HAS_NRFS + help + This option enables the nRF Services library. + +if NRFS + +config NRFS_LOCAL_DOMAIN + bool "nRF Services Local Domain Support" + depends on $(dt_alias_enabled,ipc-to-cpusys) + select IPC_SERVICE + select MBOX + select EVENTS + select REBOOT + help + This option enables the nRF Services Local Domain libraries. + +config NRFS_DVFS_LOCAL_DOMAIN + bool "Local domain that supports DVFS" + depends on NRFS_LOCAL_DOMAIN + depends on NRFS_DVFS_SERVICE_ENABLED + default y if NRFS_DVFS_SERVICE_ENABLED + +menu "Enabled Services" + +module = NRFS +module-str = nRF-Services +source "subsys/logging/Kconfig.template.log_config" + +config NRFS_RESET_SERVICE_ENABLED + bool "Reset service" + depends on NRFS_HAS_RESET_SERVICE + +config NRFS_MRAM_SERVICE_ENABLED + bool "MRAM latency service" + depends on NRFS_HAS_MRAM_SERVICE + +config NRFS_TEMP_SERVICE_ENABLED + bool "Temperature service" + depends on NRFS_HAS_TEMP_SERVICE + default y + +config NRFS_VBUS_DETECTOR_SERVICE_ENABLED + bool "VBUS detector for the USB peripheral" + depends on NRFS_HAS_VBUS_DETECTOR_SERVICE + default y + +config NRFS_CONST_LATENCY_SERVICE_ENABLED + bool "DPPI constant latency service" + depends on NRFS_HAS_CONST_LATENCY_SERVICE + default y + +config NRFS_PMIC_SERVICE_ENABLED + bool "PMIC service" + depends on NRFS_HAS_PMIC_SERVICE + +config NRFS_DVFS_SERVICE_ENABLED + bool "DVFS service" + depends on NRFS_HAS_DVFS_SERVICE + default y if SOC_NRF54H20_CPUAPP + +config NRFS_DIAG_SERVICE_ENABLED + bool "System Diagnostics service (only for development purposes)" + depends on NRFS_HAS_DIAG_SERVICE + +config NRFS_CLOCK_SERVICE_ENABLED + bool "Clock service" + depends on NRFS_HAS_CLOCK_SERVICE + default y +endmenu + +rsource "backends/Kconfig" +if NRFS_DVFS_LOCAL_DOMAIN +rsource "dvfs/Kconfig" +endif # NRFS_DVFS_LOCAL_DOMAIN + +endif # NRFS +endmenu diff --git a/modules/hal_nordic/nrfs/backends/Kconfig b/modules/hal_nordic/nrfs/backends/Kconfig new file mode 100644 index 00000000000000..2dc97ea63ceb90 --- /dev/null +++ b/modules/hal_nordic/nrfs/backends/Kconfig @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + + +menu "NRFS backend settings" + +module = NRFS_BACKEND +module-str = NRFS backend +source "subsys/logging/Kconfig.template.log_config" + +config NRFS_BACKEND_IPC_SERVICE_INIT_PRIO + int "Initialization priority for NRFS IPC backend" + default 51 + help + This should be higher than priority of other drivers/subsystems + used by NRFS backend. For example MBOX_INIT_PRIORITY which is 50. + +config NRFS_MAX_BACKEND_PACKET_SIZE + int "Maximum IPC data packet size in bytes" + range 8 128 + default 32 + +config NRFS_BACKEND_TX_MSG_QUEUE_SIZE + int "Size of TX buffer message queue size" + range 1 16 + default 8 + +endmenu diff --git a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c new file mode 100644 index 00000000000000..172b5957b23920 --- /dev/null +++ b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrfs_backend_ipc_service.h" + +#include +#include + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(NRFS_BACKEND, CONFIG_NRFS_BACKEND_LOG_LEVEL); + +#define MAX_PACKET_DATA_SIZE (CONFIG_NRFS_MAX_BACKEND_PACKET_SIZE) + +K_MSGQ_DEFINE(ipc_transmit_msgq, sizeof(struct ipc_data_packet), + CONFIG_NRFS_BACKEND_TX_MSG_QUEUE_SIZE, 4); + +static struct k_work backend_send_work; + +static struct ipc_data_packet rx_data; +static struct ipc_data_packet tx_data; + +static void ipc_sysctrl_ept_bound(void *priv); +static void ipc_sysctrl_ept_recv(const void *data, size_t size, void *priv); + +static K_EVENT_DEFINE(ipc_connected_event); + +#define IPC_INIT_DONE_EVENT (0x01) + +struct ipc_channel_config { + const struct device *ipc_instance; + struct ipc_ept_cfg *endpoint_config; + struct ipc_ept ipc_ept; + atomic_t status; + bool enabled; +}; + +static struct ipc_ept_cfg ipc_sysctrl_ept_cfg = { + .name = "ipc_to_sysctrl", + .cb = { + .bound = ipc_sysctrl_ept_bound, + .received = ipc_sysctrl_ept_recv, + }, +}; + +static struct ipc_channel_config ipc_cpusys_channel_config = { + .ipc_instance = DEVICE_DT_GET(DT_ALIAS(ipc_to_cpusys)), + .endpoint_config = &ipc_sysctrl_ept_cfg, + .status = ATOMIC_INIT(NOT_CONNECTED), + .enabled = true +}; + +/** + * @brief nrfs backend error handler + * + * @param error_id The id of an error to handle. + * @param error additional error code if needed, if not needed use 0. + * @param fatal true if fatal error and needs special handling + */ +__weak void nrfs_backend_error_handler(enum nrfs_backend_error error_id, int error, bool fatal) +{ + switch (error_id) { + case NRFS_ERROR_EPT_RECEIVE_DATA_TOO_LONG: + LOG_ERR("Received data is too long. Config error."); + break; + + case NRFS_ERROR_NO_DATA_RECEIVED: + LOG_ERR("No data in received message!"); + break; + + case NRFS_ERROR_IPC_OPEN_INSTANCE: + LOG_ERR("IPC open instance failure with error: %d", error); + break; + + case NRFS_ERROR_IPC_REGISTER_ENDPOINT: + LOG_ERR("IPC register endpoint failure with error: %d", error); + break; + + default: + LOG_ERR("Undefined error id: %d, error cause: %d", error_id, error); + break; + } + + if (fatal) { + nrfs_backend_fatal_error_handler(error_id); + } +} + +static void ipc_sysctrl_ept_bound(void *priv) +{ + LOG_INF("Bound to sysctrl."); + k_event_post(&ipc_connected_event, IPC_INIT_DONE_EVENT); + atomic_set(&ipc_cpusys_channel_config.status, CONNECTED); +} + +static void ipc_sysctrl_ept_recv(const void *data, size_t size, void *priv) +{ + __ASSERT(size <= MAX_PACKET_DATA_SIZE, "Received data is too long. Config error."); + if (size <= MAX_PACKET_DATA_SIZE) { + rx_data.channel_id = IPC_CPUSYS_CHANNEL_ID; + rx_data.size = size; + if (data) { + memcpy(rx_data.data, (uint8_t *)data, size); + nrfs_dispatcher_notify(&rx_data.data, rx_data.size); + } else { + nrfs_backend_error_handler(NRFS_ERROR_NO_DATA_RECEIVED, 0, false); + } + } else { + nrfs_backend_error_handler(NRFS_ERROR_EPT_RECEIVE_DATA_TOO_LONG, 0, true); + } +} + +static void nrfs_backend_send_work(struct k_work *item) +{ + static struct ipc_data_packet data_to_send; + + LOG_DBG("Sending data from workqueue"); + while (k_msgq_get(&ipc_transmit_msgq, &data_to_send, K_NO_WAIT) == 0) { + ipc_service_send(&ipc_cpusys_channel_config.ipc_ept, &tx_data.data, tx_data.size); + } +} + +/** + * @brief Initialize ipc channel + * + * @return -EINVAL when instance configuration is invalid. + * @return -EIO when no backend is registered. + * @return -EALREADY when the instance is already opened (or being opened). + * @return -EBUSY when the instance is busy. + * @return 0 on success + */ +static int ipc_channel_init(void) +{ + struct ipc_channel_config *ch_cfg; + int ret = 0; + + k_work_init(&backend_send_work, nrfs_backend_send_work); + ch_cfg = &ipc_cpusys_channel_config; + + ret = ipc_service_open_instance(ch_cfg->ipc_instance); + if ((ret < 0) && (ret != -EALREADY)) { + nrfs_backend_error_handler(NRFS_ERROR_IPC_OPEN_INSTANCE, ret, false); + return ret; + } + + LOG_INF("ipc_service_open_instance() done."); + + ret = ipc_service_register_endpoint(ch_cfg->ipc_instance, + &ch_cfg->ipc_ept, + ch_cfg->endpoint_config); + if (ret < 0) { + nrfs_backend_error_handler(NRFS_ERROR_IPC_REGISTER_ENDPOINT, ret, false); + return ret; + } + + LOG_INF("ipc_service_register_endpoint() done."); + + return ret; +} + +nrfs_err_t nrfs_backend_send(void *message, size_t size) +{ + return nrfs_backend_send_ex(message, size, K_NO_WAIT, false); +} + +nrfs_err_t nrfs_backend_send_ex(void *message, size_t size, k_timeout_t timeout, bool high_prio) +{ + if (atomic_get(&ipc_cpusys_channel_config.status) != CONNECTED) { + LOG_WRN("Backend not yet connected to sysctrl"); + return NRFS_ERR_INVALID_STATE; + } + + if (size <= MAX_PACKET_DATA_SIZE) { + int err; + + tx_data.channel_id = IPC_CPUSYS_CHANNEL_ID; + tx_data.size = size; + memcpy(tx_data.data, (uint8_t *)message, size); + + err = k_msgq_put(&ipc_transmit_msgq, &tx_data, timeout); + if (err) { + return NRFS_ERR_IPC; + } + + err = k_work_submit(&backend_send_work); + + return err >= 0 ? 0 : NRFS_ERR_IPC; + } + + LOG_ERR("Trying to send %d bytes where max is %d.", size, MAX_PACKET_DATA_SIZE); + + return NRFS_ERR_IPC; +} + +bool nrfs_backend_connected(void) +{ + return atomic_get(&ipc_cpusys_channel_config.status) == CONNECTED; +} + +int nrfs_backend_wait_for_connection(k_timeout_t timeout) +{ + uint32_t events; + + if (nrfs_backend_connected()) { + return 0; + } + + events = k_event_wait(&ipc_connected_event, IPC_INIT_DONE_EVENT, false, timeout); + + return (events == IPC_INIT_DONE_EVENT ? 0 : (-EAGAIN)); +} + +__weak void nrfs_backend_fatal_error_handler(enum nrfs_backend_error error_id) +{ + LOG_ERR("Fatal error: %d rebooting...", error_id); + sys_reboot(SYS_REBOOT_WARM); +} + +SYS_INIT(ipc_channel_init, POST_KERNEL, CONFIG_NRFS_BACKEND_IPC_SERVICE_INIT_PRIO); diff --git a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h new file mode 100644 index 00000000000000..572c05e864c786 --- /dev/null +++ b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_BACKEND_IPC_SERVICE_H +#define NRFS_BACKEND_IPC_SERVICE_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct __packed ipc_data_packet { + uint16_t channel_id; + uint16_t size; + uint8_t data[CONFIG_NRFS_MAX_BACKEND_PACKET_SIZE]; +}; + +enum ipc_channel_status { + NOT_CONNECTED = 0, + CONNECTED = 1 +}; + +enum nrfs_backend_error { + NRFS_ERROR_EPT_RECEIVE_QUEUE_ERROR = 0, + NRFS_ERROR_EPT_RECEIVE_DATA_TOO_LONG, + NRFS_ERROR_IPC_CHANNEL_INIT, + NRFS_ERROR_SEND_DATA, + NRFS_ERROR_NO_DATA_RECEIVED, + NRFS_ERROR_IPC_OPEN_INSTANCE, + NRFS_ERROR_IPC_REGISTER_ENDPOINT, + NRFS_ERROR_BACKEND_NOT_CONNECTED, + NRFS_ERROR_COUNT +}; + +#define IPC_CPUSYS_CHANNEL_ID 0x5C + +/** + * @brief function to check if backend is connected to sysctrl + * + * @return true Backend connected. + * @return false Backend not connected. + */ +bool nrfs_backend_connected(void); + +/** + * @brief this function will block until connection or timeout expires + * + * @param timeout + * + * @return 0 Connection done. + * @return -EAGAIN Waiting period timed out. + */ +int nrfs_backend_wait_for_connection(k_timeout_t timeout); + +/** + * @brief Extended function for sending a message over the chosen transport backend. + * + * This function is used by services to send requests to the System Controller. + * + * @param[in] message Pointer to the message payload. + * @param[in] size Message payload size. + * @param[in] timeout Non-negative waiting period to add the message, + * or one of the special values K_NO_WAIT and K_FOREVER. + * @param[in] high_prio True if message should be sent with higher priority. + * + * @retval NRFS_SUCCESS Message sent successfully. + * @retval NRFS_ERR_IPC Backend returned error during message sending. + */ +nrfs_err_t nrfs_backend_send_ex(void *message, size_t size, k_timeout_t timeout, bool high_prio); + +/** + * @brief Fatal error handler for unrecoverable errors + * + * This is weak function so it can be overridden if needed. + * Error is considered fatal when there is no option to send message to sysctrl + * even after retry. Communication with sysctrl is crucial for system to work properly. + * + * @param error_id parameter to identify error. + */ +void nrfs_backend_fatal_error_handler(enum nrfs_backend_error error_id); + +#ifdef __cplusplus +} +#endif + +#endif /* NRFS_BACKEND_IPC_SERVICE_H */ diff --git a/modules/hal_nordic/nrfs/dvfs/CMakeLists.txt b/modules/hal_nordic/nrfs/dvfs/CMakeLists.txt new file mode 100644 index 00000000000000..4512a91b36aff0 --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_sources_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN ld_dvfs.c + ld_dvfs_handler.c) diff --git a/modules/hal_nordic/nrfs/dvfs/Kconfig b/modules/hal_nordic/nrfs/dvfs/Kconfig new file mode 100644 index 00000000000000..0a6078a0db04ea --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/Kconfig @@ -0,0 +1,40 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +menu "Local domain DVFS library" + +module = LOCAL_DOMAIN_DVFS_LIB +module-str = Local domain DVFS library +source "subsys/logging/Kconfig.template.log_config" + +config NRFS_LOCAL_DOMAIN_DVFS_TEST + bool "Local domain DVFS test" + help + Disable hw registers interaction for testing. + +config NRFS_LOCAL_DOMAIN_DVFS_SCALE_DOWN_AFTER_INIT + bool "Local domain scale down after init" + help + Request lowest oppoint after DVFS initialization. + +config NRFS_LOCAL_DOMAIN_DOWNSCALE_SAFETY_TIMEOUT_US + int "Voltage downscale procedure safety timeout in us" + range 1 10000000 + default 1000000 if (NRFS_LOCAL_DOMAIN_DVFS_TEST || LOG) + default 1500 + +config NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_STACK_SIZE + int "Stack size used for DVFS handling task" + range 256 2048 + default 1024 if LOG + default 512 + +config NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_PRIORITY + int "Priority of DVFS handling task" + range -16 NUM_PREEMPT_PRIORITIES + default 0 + +endmenu diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs.c b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.c new file mode 100644 index 00000000000000..883161e9f92361 --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ld_dvfs.h" + +#include +#include + +#include +#include +LOG_MODULE_REGISTER(LD_DVFS_LIB, CONFIG_LOCAL_DOMAIN_DVFS_LIB_LOG_LEVEL); + +#define TRANSIENT_ZBB_ABB_SLOT 0 +#define CURR_TARG_ABB_SLOT 1 +#define LD_ABB_CLR_ZBB 0 +/* TODO: this values needs to be provided by HW team */ +/* for now reset value will be used */ +#define LD_ABB_CTRL4_NORMAL_OPERATION 0x10800UL +#define LD_ABB_CTRL4_TRANSITION_OPERATION 0x10800UL + +/* + * wait max 500ms with 10us intervals for hsfll freq change event + */ +#define HSFLL_FREQ_CHANGE_MAX_DELAY_MS 500UL +#define HSFLL_FREQ_CHANGE_CHECK_INTERVAL_US 10 +#define HSFLL_FREQ_CHANGE_CHECK_MAX_ATTEMPTS \ + ((HSFLL_FREQ_CHANGE_MAX_DELAY_MS) * (USEC_PER_MSEC) / (HSFLL_FREQ_CHANGE_CHECK_INTERVAL_US)) + +#define ABB_STATUS_CHANGE_MAX_DELAY_MS 5000UL +#define ABB_STATUS_CHANGE_CHECK_INTERVAL_US 10 +#define ABB_STATUS_CHANGE_CHECK_MAX_ATTEMPTS \ + ((ABB_STATUS_CHANGE_MAX_DELAY_MS) * (USEC_PER_MSEC) / (ABB_STATUS_CHANGE_CHECK_INTERVAL_US)) + +void ld_dvfs_init(void) +{ +#if defined(NRF_SECURE) + + const struct dvfs_oppoint_data *opp_data = get_dvfs_oppoint_data(DVFS_FREQ_HIGH); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("REGW: NRF_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + /*For app core.*/ + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); +#else + /* TODO: Change to NRFX Hal function when available. */ + NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; +#endif +#endif +} + +void ld_dvfs_clear_zbb(void) +{ +#if defined(NRF_SECURE) +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("REGW: NRF_ABB->CONFIG.CTRL1.MODE 0x%x, V: 0x%x", + (uint32_t)&NRF_ABB->CONFIG.CTRL1, + LD_ABB_CLR_ZBB); +#else + /* TODO: Change to NRFX Hal function when available. */ + NRF_ABB->CONFIG.CTRL1 &= ~(ABB_CONFIG_CTRL1_MODE_Msk); + NRF_APPLICATION_ABB->CONFIG.CTRL1 &= ~(ABB_CONFIG_CTRL1_MODE_Msk); +#endif +#endif +} + +#if defined(NRF_SECURE) + +#define DOWNSCALE_SAFETY_TIMEOUT (K_USEC(CONFIG_NRFS_LOCAL_DOMAIN_DOWNSCALE_SAFETY_TIMEOUT_US)) + +atomic_t increased_power_consumption; + +/** + * @brief Secure domain needs to check if downscale is done in defined time + * window. This is needed to avoid battery drain if dvfs procedure + * takes to much time (some failure?). + */ +__weak void ld_dvfs_secure_downscale_timeout(struct k_timer *timer) +{ + ARG_UNUSED(timer); + + LOG_ERR("Downscale timeout expired, reset board."); + atomic_set(&increased_power_consumption, 0); +} + +K_TIMER_DEFINE(dvfs_downscale_secure_timer, ld_dvfs_secure_downscale_timeout, NULL); + +/** + * @brief Secure domain starts increased power consumption, needed by dvfs sequence. + * This function can be reimplemented in other module if needed. + */ +__weak void ld_dvfs_secure_start_increased_power_consumption(void) +{ + LOG_INF("Start increased power consumption for DVFS sequence and start safety timer."); + k_timer_start(&dvfs_downscale_secure_timer, DOWNSCALE_SAFETY_TIMEOUT, K_NO_WAIT); + atomic_set(&increased_power_consumption, 1); + + volatile uint8_t idle_counter = 0; + + while (atomic_get(&increased_power_consumption)) { + if (idle_counter < 100) { + k_yield(); + idle_counter++; + } else { + idle_counter = 0; + k_usleep(1); + } + } +} + +/** + * @brief Secure domain stops increased power consumption at the end of downscale. + * This function can be reimplemented in other module if needed. + */ +__weak void ld_dvfs_secure_stop_increased_power_consumption(void) +{ + LOG_INF("Stop increased power consumption for DVFS sequence."); + k_timer_stop(&dvfs_downscale_secure_timer); + atomic_set(&increased_power_consumption, 0); +} + +#endif + +void ld_dvfs_configure_abb_for_transition(enum dvfs_frequency_setting transient_opp, + enum dvfs_frequency_setting curr_targ_opp) +{ +#if defined(NRF_SECURE) + const struct dvfs_oppoint_data *opp_data = get_dvfs_oppoint_data(transient_opp); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("transient_opp: %d, curr_targ_opp: %d", transient_opp, curr_targ_opp); + LOG_DBG("REGW: NRF_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + /* For app core.*/ + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_pvtmoncycles); +#else + + NRF_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_ringo; + NRF_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_lockrange; + NRF_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_APPLICATION_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_ringo; + NRF_APPLICATION_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_lockrange; + NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_pvtmoncycles; +#endif + opp_data = get_dvfs_oppoint_data(curr_targ_opp); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("REGW: NRF_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + LOG_DBG("REGW: TODO: NRF_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_TRANSITION_OPERATION); + + /* For app core */ + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + LOG_DBG("REGW: TODO: NRF_APPLICATION_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_APPLICATION_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_TRANSITION_OPERATION); +#else + NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_TRANSITION_OPERATION; + + NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_APPLICATION_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_TRANSITION_OPERATION; + +#endif +#endif +} + +int32_t ld_dvfs_configure_hsfll(enum dvfs_frequency_setting oppoint) +{ + nrf_hsfll_trim_t hsfll_trim = {}; + + if (oppoint >= DVFS_FREQ_COUNT) { + LOG_ERR("Not valid oppoint %d", oppoint); + return -EINVAL; + } + + uint8_t freq_trim = get_dvfs_oppoint_data(oppoint)->new_f_trim_entry; + +#ifdef CONFIG_SOC_NRF54H20_CPUAPP + hsfll_trim.vsup = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.VSUP; + hsfll_trim.coarse = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.COARSE[freq_trim]; + hsfll_trim.fine = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.FINE[freq_trim]; +#else + hsfll_trim.vsup = NRF_FICR->TRIM.SECURE.HSFLL.TRIM.VSUP; + hsfll_trim.coarse = NRF_FICR->TRIM.SECURE.HSFLL.TRIM.COARSE[freq_trim]; + hsfll_trim.fine = NRF_FICR->TRIM.SECURE.HSFLL.TRIM.FINE[freq_trim]; +#endif + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s oppoint: %d", __func__, oppoint); + LOG_DBG("REGW: NRF_HSFLL->MIRROR 0x%x, V: 0x%x", (uint32_t)&NRF_HSFLL->MIRROR, 1); + LOG_DBG("REGW: NRF_HSFLL->TRIM.COARSE 0x%x, V: 0x%x", + (uint32_t)&NRF_HSFLL->TRIM.COARSE, + hsfll_trim.coarse); + LOG_DBG("REGW: NRF_HSFLL->TRIM.FINE 0x%x, V: 0x%x", + (uint32_t)&NRF_HSFLL->TRIM.FINE, + hsfll_trim.fine); + LOG_DBG("REGW: NRF_HSFLL->MIRROR 0x%x, V: 0x%x", (uint32_t)&NRF_HSFLL->MIRROR, 0); + + LOG_DBG("REGW: NRF_HSFLL->CLOCKCTRL.MULT 0x%x, V: 0x%x", + (uint32_t)&NRF_HSFLL->CLOCKCTRL.MULT, + get_dvfs_oppoint_data(oppoint)->new_f_mult); + + LOG_DBG("REGW: NRF_HSFLL->NRF_HSFLL_TASK_FREQ_CHANGE 0x%x, V: 0x%x", + (uint32_t)NRF_HSFLL + NRF_HSFLL_TASK_FREQ_CHANGE, + 0x1); + return 0; +#else + + nrf_hsfll_trim_set(NRF_HSFLL, &hsfll_trim); + nrf_barrier_w(); + + nrf_hsfll_clkctrl_mult_set(NRF_HSFLL, get_dvfs_oppoint_data(oppoint)->new_f_mult); + nrf_hsfll_task_trigger(NRF_HSFLL, NRF_HSFLL_TASK_FREQ_CHANGE); + /* Trigger hsfll task one more time, SEE PAC-4078 */ + nrf_hsfll_task_trigger(NRF_HSFLL, NRF_HSFLL_TASK_FREQ_CHANGE); + + bool hsfll_freq_changed = false; + + NRFX_WAIT_FOR(nrf_hsfll_event_check(NRF_HSFLL, NRF_HSFLL_EVENT_FREQ_CHANGED), + HSFLL_FREQ_CHANGE_CHECK_MAX_ATTEMPTS, + HSFLL_FREQ_CHANGE_CHECK_INTERVAL_US, + hsfll_freq_changed); + + if (hsfll_freq_changed) { + return 0; + } + + return -ETIMEDOUT; +#endif +} + +void ld_dvfs_scaling_background_process(bool downscaling) +{ +#if defined(NRF_SECURE) + if (NRF_DOMAIN == NRF_DOMAIN_SECURE) { + if (downscaling) { + ld_dvfs_secure_start_increased_power_consumption(); + } + } +#endif +} + +void ld_dvfs_scaling_finish(bool downscaling) +{ +#if defined(NRF_SECURE) +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("REGW: NRF_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_NORMAL_OPERATION); + LOG_DBG("REGW: NRF_APPLICATION_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_APPLICATION_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_NORMAL_OPERATION); +#else + NRF_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_NORMAL_OPERATION; + NRF_APPLICATION_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_NORMAL_OPERATION; +#endif + + if (NRF_DOMAIN == NRF_DOMAIN_SECURE) { + if (downscaling) { + ld_dvfs_secure_stop_increased_power_consumption(); + } + } +#endif +} diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs.h b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.h new file mode 100644 index 00000000000000..947a9b5a1afd29 --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef LD_DVFS_H +#define LD_DVFS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for initializing the Dynamic Voltage and Frequency Scaling service + * from LD perspective.. + * + */ +void ld_dvfs_init(void); + +/** + * @brief Function for clearing the zero bias + * + */ +void ld_dvfs_clear_zbb(void); + +/** + * @brief Configure ABB registers to transition process. + * + * @param transient_opp current operation point + * @param curr_targ_opp target operation point + */ +void ld_dvfs_configure_abb_for_transition(enum dvfs_frequency_setting transient_opp, + enum dvfs_frequency_setting curr_targ_opp); + +/** + * @brief Configure hsfll depending on selected oppoint + * + * @param enum oppoint target operation point + * @return 0 value indicates no error. + * @return -EINVAL invalid oppoint or domain. + * @return -ETIMEDOUT frequency change took more than HSFLL_FREQ_CHANGE_MAX_DELAY_MS + */ +int32_t ld_dvfs_configure_hsfll(enum dvfs_frequency_setting oppoint); + +/** + * @brief Background process during scaling. + * + * @param downscaling indicates if down-scaling is running + */ +void ld_dvfs_scaling_background_process(bool downscaling); + +/** + * @brief Last step for local domain in downscale procedure + * + * @param downscaling indicates if down-scaling is running + */ +void ld_dvfs_scaling_finish(bool downscaling); + +#ifdef __cplusplus +} +#endif + +#endif /* LD_DVFS_H */ diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c new file mode 100644 index 00000000000000..20e879c4f737ea --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ld_dvfs_handler.h" +#include "ld_dvfs.h" + +#include +#include +#include + +#include +#include +LOG_MODULE_DECLARE(LD_DVFS_LIB, CONFIG_LOCAL_DOMAIN_DVFS_LIB_LOG_LEVEL); + +static K_SEM_DEFINE(dvfs_service_sync_sem, 0, 1); +static K_SEM_DEFINE(dvfs_service_idle_sem, 0, 1); + +#define DVFS_SERV_HDL_INIT_DONE_BIT_POS (0) +#define DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS (1) + +static atomic_t dvfs_service_handler_state_bits; +static enum dvfs_frequency_setting current_freq_setting; + +static void dvfs_service_handler_set_state_bit(uint32_t bit_pos) +{ + atomic_set_bit(&dvfs_service_handler_state_bits, bit_pos); +} + +static void dvfs_service_handler_clear_state_bit(uint32_t bit_pos) +{ + atomic_clear_bit(&dvfs_service_handler_state_bits, bit_pos); +} + +static bool dvfs_service_handler_get_state_bit(uint32_t bit_pos) +{ + return atomic_test_bit(&dvfs_service_handler_state_bits, bit_pos); +} + +static bool dvfs_service_handler_init_done(void) +{ + return dvfs_service_handler_get_state_bit(DVFS_SERV_HDL_INIT_DONE_BIT_POS); +} + +static bool dvfs_service_handler_freq_change_in_progress(void) +{ + return dvfs_service_handler_get_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); +} + +static void dvfs_service_handler_nrfs_error_check(nrfs_err_t err) +{ + if (err != NRFS_SUCCESS) { + LOG_ERR("Failed with nrfs error: %d", err); + } +} + +static void dvfs_service_handler_error(int err) +{ + if (err != 0) { + LOG_ERR("Failed with error: %d", err); + } +} + +static uint32_t *get_next_context(void) +{ + static uint32_t ctx; + + ctx++; + return &ctx; +} + +static bool dvfs_service_handler_freq_setting_allowed(enum dvfs_frequency_setting freq_setting) +{ + if (freq_setting == DVFS_FREQ_HIGH || freq_setting == DVFS_FREQ_MEDLOW || + freq_setting == DVFS_FREQ_LOW) { + return true; + } + + return false; +} + +static enum dvfs_frequency_setting dvfs_service_handler_get_current_oppoint(void) +{ + LOG_INF("Current LD freq setting: %d", current_freq_setting); + return current_freq_setting; +} + +/* Function to check if current operation is down-scaling */ +static bool dvfs_service_handler_is_downscaling(enum dvfs_frequency_setting target_freq_setting) +{ + if (dvfs_service_handler_freq_setting_allowed(target_freq_setting)) { + LOG_DBG("Checking if downscaling %s", + (dvfs_service_handler_get_current_oppoint() < target_freq_setting) ? "YES" : + "NO"); + return dvfs_service_handler_get_current_oppoint() < target_freq_setting; + } + + return false; +} + +/* Function handling steps for scaling preparation. */ +static void dvfs_service_handler_prepare_to_scale(enum dvfs_frequency_setting oppoint_freq) +{ + LOG_INF("Prepare to scale, oppoint freq %d", oppoint_freq); + enum dvfs_frequency_setting new_oppoint = oppoint_freq; + enum dvfs_frequency_setting current_oppoint = dvfs_service_handler_get_current_oppoint(); + + if (new_oppoint == current_oppoint) { + LOG_INF("New oppoint is same as previous, no change"); + } else { + ld_dvfs_configure_abb_for_transition(current_oppoint, new_oppoint); + + if (dvfs_service_handler_is_downscaling(new_oppoint)) { + int32_t err = ld_dvfs_configure_hsfll(new_oppoint); + + if (err != 0) { + dvfs_service_handler_error(err); + } + } + } +} + +/* Do background job during scaling process (e.g. increased power consumption during down-scale). */ +static void dvfs_service_handler_scaling_background_job(enum dvfs_frequency_setting oppoint_freq) +{ + LOG_INF("Perform scaling background job if needed."); + if (dvfs_service_handler_is_downscaling(oppoint_freq)) { + k_sem_give(&dvfs_service_idle_sem); + } +} + +/* Perform scaling finnish procedure. */ +static void dvfs_service_handler_scaling_finish(enum dvfs_frequency_setting oppoint_freq) +{ + LOG_INF("Scaling finnish oppoint freq %d", oppoint_freq); + ld_dvfs_scaling_finish(dvfs_service_handler_is_downscaling(oppoint_freq)); + if (!dvfs_service_handler_is_downscaling(oppoint_freq)) { + int32_t err = ld_dvfs_configure_hsfll(oppoint_freq); + + if (err != 0) { + dvfs_service_handler_error(err); + } + } + current_freq_setting = oppoint_freq; +} + +/* Function to set hsfll to highest frequency when switched to ABB. */ +static void dvfs_service_handler_set_initial_hsfll_config(void) +{ + int32_t err = ld_dvfs_configure_hsfll(DVFS_FREQ_HIGH); + + current_freq_setting = DVFS_FREQ_HIGH; + if (err != 0) { + dvfs_service_handler_error(err); + } +} + +/* DVFS event handler callback function.*/ +static void nrfs_dvfs_evt_handler(nrfs_dvfs_evt_t const *p_evt, void *context) +{ + LOG_INF("%s", __func__); + switch (p_evt->type) { + case NRFS_DVFS_EVT_INIT_PREPARATION: + LOG_INF("DVFS handler EVT_INIT_PREPARATION"); +#if defined(NRF_SECURE) + ld_dvfs_clear_zbb(); + dvfs_service_handler_nrfs_error_check( + nrfs_dvfs_init_complete_request(get_next_context())); + LOG_INF("DVFS handler EVT_INIT_PREPARATION handled"); +#else + LOG_ERR("DVFS handler - unexpected EVT_INIT_PREPARATION"); +#endif + break; + case NRFS_DVFS_EVT_INIT_DONE: + LOG_INF("DVFS handler EVT_INIT_DONE"); + dvfs_service_handler_set_initial_hsfll_config(); + dvfs_service_handler_set_state_bit(DVFS_SERV_HDL_INIT_DONE_BIT_POS); + k_sem_give(&dvfs_service_sync_sem); + LOG_INF("DVFS handler EVT_INIT_DONE handled"); + break; + case NRFS_DVFS_EVT_OPPOINT_REQ_CONFIRMED: + /* Optional confirmation from sysctrl, wait for oppoint.*/ + LOG_INF("DVFS handler EVT_OPPOINT_REQ_CONFIRMED"); + break; + case NRFS_DVFS_EVT_OPPOINT_SCALING_PREPARE: + /*Target oppoint will be received here.*/ + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_PREPARE"); +#if !defined(NRF_SECURE) + if (dvfs_service_handler_is_downscaling(p_evt->freq)) { +#endif + dvfs_service_handler_prepare_to_scale(p_evt->freq); + dvfs_service_handler_nrfs_error_check( + nrfs_dvfs_ready_to_scale(get_next_context())); + dvfs_service_handler_scaling_background_job(p_evt->freq); + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_PREPARE handled"); +#if !defined(NRF_SECURE) + current_freq_setting = p_evt->freq; + } else { + LOG_ERR("DVFS handler - unexpected EVT_OPPOINT_SCALING_PREPARE"); + } +#endif + break; + case NRFS_DVFS_EVT_OPPOINT_SCALING_DONE: + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_DONE"); + dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); + dvfs_service_handler_scaling_finish(p_evt->freq); + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_DONE handled"); + break; + case NRFS_DVFS_EVT_REJECT: + LOG_ERR("DVFS handler - request rejected"); + break; + default: + LOG_ERR("DVFS handler - unexpected event: 0x%x", p_evt->type); + break; + } +} + +/* Task to handle dvfs init procedure. */ +static void dvfs_service_handler_task(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + LOG_INF("Trim ABB for default voltage."); + ld_dvfs_init(); + + LOG_INF("Waiting for backend init"); + /* Wait for ipc initialization */ + nrfs_backend_wait_for_connection(K_FOREVER); + + nrfs_err_t status; + + LOG_INF("nrfs_dvfs_init"); + status = nrfs_dvfs_init(nrfs_dvfs_evt_handler); + dvfs_service_handler_nrfs_error_check(status); + + LOG_INF("nrfs_dvfs_init_prepare_request"); + status = nrfs_dvfs_init_prepare_request(get_next_context()); + dvfs_service_handler_nrfs_error_check(status); + + /* Wait for init*/ + k_sem_take(&dvfs_service_sync_sem, K_FOREVER); + + LOG_INF("DVFS init done."); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_SCALE_DOWN_AFTER_INIT) + LOG_INF("Requesting lowest frequency oppoint."); + dvfs_service_handler_change_freq_setting(DVFS_FREQ_LOW); +#endif + + while (1) { + k_sem_take(&dvfs_service_idle_sem, K_FOREVER); + /* perform background processing */ + ld_dvfs_scaling_background_process(true); + } +} + +K_THREAD_DEFINE(dvfs_service_handler_task_id, + CONFIG_NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_STACK_SIZE, + dvfs_service_handler_task, + NULL, + NULL, + NULL, + CONFIG_NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_PRIORITY, + 0, + 0); + +int32_t dvfs_service_handler_change_freq_setting(enum dvfs_frequency_setting freq_setting) +{ + if (!dvfs_service_handler_init_done()) { + LOG_INF("Init not done!"); + return -EAGAIN; + } + + if (dvfs_service_handler_freq_change_in_progress()) { + LOG_INF("Frequency change in progress."); + return -EBUSY; + } + + if (!dvfs_service_handler_freq_setting_allowed(freq_setting)) { + return -ENXIO; + } + + nrfs_err_t status = nrfs_dvfs_oppoint_request(freq_setting, get_next_context()); + + dvfs_service_handler_nrfs_error_check(status); + + return status; +} diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h new file mode 100644 index 00000000000000..b15e630eb2c89f --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef LD_DVFS_HANDLER_H +#define LD_DVFS_HANDLER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function to request LD frequency change. + * + * @param frequency requested frequency setting from enum dvfs_frequency_setting. + * @return EBUSY Frequency change in progress. + * @return EAGAIN DVFS init in progress. + * @return ENXIO Not supported frequency settings. + * @return NRFS_SUCCESS Request sent successfully. + * @return NRFS_ERR_INVALID_STATE Service is uninitialized. + * @return NRFS_ERR_IPC Backend returned error during request sending. + */ +int32_t dvfs_service_handler_change_freq_setting(enum dvfs_frequency_setting freq_setting); + +#ifdef __cplusplus +} +#endif + +#endif /* LD_DVFS_HANDLER_H */ diff --git a/modules/hal_nordic/nrfs/nrfs_config.h b/modules/hal_nordic/nrfs/nrfs_config.h new file mode 100644 index 00000000000000..20cf6cece0e3e7 --- /dev/null +++ b/modules/hal_nordic/nrfs/nrfs_config.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_CONFIG_H +#define NRFS_CONFIG_H + + +#ifdef CONFIG_NRFS_TEMP_SERVICE_ENABLED +#define NRFS_TEMP_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_MRAM_SERVICE_ENABLED +#define NRFS_MRAM_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_RESET_SERVICE_ENABLED +#define NRFS_RESET_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_VBUS_DETECTOR_SERVICE_ENABLED +#define NRFS_VBUS_DETECTOR_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_PMIC_SERVICE_ENABLED +#define NRFS_PMIC_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_DVFS_SERVICE_ENABLED +#define NRFS_DVFS_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_DIAG_SERVICE_ENABLED +#define NRFS_DIAG_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_CLOCK_SERVICE_ENABLED +#define NRFS_CLOCK_SERVICE_ENABLED +#endif + +#ifdef CONFIG_SOC_POSIX +#define NRFS_UNIT_TESTS_ENABLED +#endif + +#endif /* NRFS_CONFIG_H */ diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index 1be3e6bc40ea8c..a7eb08d9c9fcf5 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -4,6 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 config SOC_SERIES_NRF54HX + select HAS_NRFS select HAS_NRFX select HAS_NORDIC_DRIVERS @@ -18,6 +19,11 @@ config SOC_NRF54H20_CPUAPP select CPU_HAS_FPU select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE + select NRFS_HAS_CLOCK_SERVICE + select NRFS_HAS_DVFS_SERVICE + select NRFS_HAS_MRAM_SERVICE + select NRFS_HAS_TEMP_SERVICE + select NRFS_HAS_VBUS_DETECTOR_SERVICE config SOC_NRF54H20_CPURAD select ARM @@ -30,6 +36,9 @@ config SOC_NRF54H20_CPURAD select CPU_HAS_FPU select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE + select NRFS_HAS_CLOCK_SERVICE + select NRFS_HAS_MRAM_SERVICE + select NRFS_HAS_TEMP_SERVICE config SOC_NRF54H20_CPUPPR depends on RISCV_CORE_NORDIC_VPR From fb3f8ca8b1361473bf5194e68f6df8e9f01d0881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0699/1389] drivers: sensor: Add driver for nRF temperature sensor accessed via nrfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add driver, together with the corresponding dts binding and node in the nRF54H20 SoC definiton, for the nRF temperature sensor that cannot be accessed directly but only through nRF Services (nrfs) layer. Signed-off-by: Andrzej Głąbek --- drivers/sensor/nordic/CMakeLists.txt | 2 +- drivers/sensor/nordic/Kconfig | 2 +- drivers/sensor/nordic/nrf5/Kconfig | 20 -- .../nordic/{nrf5 => temp}/CMakeLists.txt | 3 + drivers/sensor/nordic/temp/Kconfig | 38 +++ .../sensor/nordic/{nrf5 => temp}/temp_nrf5.c | 0 drivers/sensor/nordic/temp/temp_nrfs.c | 312 ++++++++++++++++++ dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml | 9 + dts/common/nordic/nrf54h20.dtsi | 5 + 9 files changed, 369 insertions(+), 22 deletions(-) delete mode 100644 drivers/sensor/nordic/nrf5/Kconfig rename drivers/sensor/nordic/{nrf5 => temp}/CMakeLists.txt (66%) create mode 100644 drivers/sensor/nordic/temp/Kconfig rename drivers/sensor/nordic/{nrf5 => temp}/temp_nrf5.c (100%) create mode 100644 drivers/sensor/nordic/temp/temp_nrfs.c create mode 100644 dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml diff --git a/drivers/sensor/nordic/CMakeLists.txt b/drivers/sensor/nordic/CMakeLists.txt index 0169664e6aa0aa..89265c0e59d3b9 100644 --- a/drivers/sensor/nordic/CMakeLists.txt +++ b/drivers/sensor/nordic/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +add_subdirectory(temp) add_subdirectory_ifdef(CONFIG_NPM1300_CHARGER npm1300_charger) add_subdirectory_ifdef(CONFIG_QDEC_NRFX qdec_nrfx) -add_subdirectory_ifdef(CONFIG_TEMP_NRF5 nrf5) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/nordic/Kconfig b/drivers/sensor/nordic/Kconfig index 42678ed2fcc009..27f1cfedf59af5 100644 --- a/drivers/sensor/nordic/Kconfig +++ b/drivers/sensor/nordic/Kconfig @@ -3,6 +3,6 @@ # zephyr-keep-sorted-start source "drivers/sensor/nordic/npm1300_charger/Kconfig" -source "drivers/sensor/nordic/nrf5/Kconfig" source "drivers/sensor/nordic/qdec_nrfx/Kconfig" +source "drivers/sensor/nordic/temp/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/nordic/nrf5/Kconfig b/drivers/sensor/nordic/nrf5/Kconfig deleted file mode 100644 index aa0e3d6fc0fdd4..00000000000000 --- a/drivers/sensor/nordic/nrf5/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -# nRF5 temperature sensor configuration options - -# Copyright (c) 2016 ARM Ltd. -# SPDX-License-Identifier: Apache-2.0 - -config TEMP_NRF5_FORCE_ALT - bool - depends on SOC_COMPATIBLE_NRF - help - This option can be enabled to force an alternative implementation - of the temperature sensor driver. - -config TEMP_NRF5 - bool "nRF5 Temperature Sensor" - default y - depends on DT_HAS_NORDIC_NRF_TEMP_ENABLED - depends on HAS_HW_NRF_TEMP - depends on MULTITHREADING || TEMP_NRF5_FORCE_ALT - help - Enable driver for nRF5 temperature sensor. diff --git a/drivers/sensor/nordic/nrf5/CMakeLists.txt b/drivers/sensor/nordic/temp/CMakeLists.txt similarity index 66% rename from drivers/sensor/nordic/nrf5/CMakeLists.txt rename to drivers/sensor/nordic/temp/CMakeLists.txt index d57e18cdf1b631..e3f81b50ac438a 100644 --- a/drivers/sensor/nordic/nrf5/CMakeLists.txt +++ b/drivers/sensor/nordic/temp/CMakeLists.txt @@ -3,4 +3,7 @@ if(CONFIG_TEMP_NRF5 AND NOT CONFIG_TEMP_NRF5_FORCE_ALT) zephyr_library() zephyr_library_sources(temp_nrf5.c) +elseif(CONFIG_TEMP_NRFS) + zephyr_library() + zephyr_library_sources(temp_nrfs.c) endif() diff --git a/drivers/sensor/nordic/temp/Kconfig b/drivers/sensor/nordic/temp/Kconfig new file mode 100644 index 00000000000000..e32fb1b8fdd608 --- /dev/null +++ b/drivers/sensor/nordic/temp/Kconfig @@ -0,0 +1,38 @@ +# nRF temperature sensor configuration options + +# Copyright (c) 2016 ARM Ltd. +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config TEMP_NRF5_FORCE_ALT + bool + depends on SOC_COMPATIBLE_NRF + help + This option can be enabled to force an alternative implementation + of the temperature sensor driver. + +config TEMP_NRF5 + bool "nRF5 Temperature Sensor" + default y + depends on DT_HAS_NORDIC_NRF_TEMP_ENABLED + depends on MULTITHREADING || TEMP_NRF5_FORCE_ALT + help + Enable driver for nRF5 temperature sensor. + +config TEMP_NRFS + bool "nRF Temperature Sensor accessed via nrfs" + default y + depends on DT_HAS_NORDIC_NRF_TEMP_NRFS_ENABLED + depends on NRFS + help + Enable driver for nRF temperature sensor accessed through the nRF + Services (nrfs) layer. + +if TEMP_NRFS + +module = TEMP_NRFS +thread_priority = 10 +thread_stack_size = 1024 +source "drivers/sensor/Kconfig.trigger_template" + +endif # TEMP_NRFS diff --git a/drivers/sensor/nordic/nrf5/temp_nrf5.c b/drivers/sensor/nordic/temp/temp_nrf5.c similarity index 100% rename from drivers/sensor/nordic/nrf5/temp_nrf5.c rename to drivers/sensor/nordic/temp/temp_nrf5.c diff --git a/drivers/sensor/nordic/temp/temp_nrfs.c b/drivers/sensor/nordic/temp/temp_nrfs.c new file mode 100644 index 00000000000000..015e05918f04d9 --- /dev/null +++ b/drivers/sensor/nordic/temp/temp_nrfs.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrf_temp_nrfs + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(temp_nrfs, CONFIG_SENSOR_LOG_LEVEL); + +struct temp_nrfs_data { + struct k_sem measure_sem; + struct k_mutex mutex; + int32_t raw_temp; + +#ifdef CONFIG_TEMP_NRFS_TRIGGER + struct sensor_trigger trigger; + sensor_trigger_handler_t handler; + const struct device *dev; + struct sensor_value sampling_freq; + struct sensor_value up_threshold; + struct sensor_value low_threshold; +#endif +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TEMP_NRFS_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem event_sem; +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +}; + +#ifdef CONFIG_TEMP_NRFS_TRIGGER + +#define DEFAULT_SAMPLING_FREQ { 1, 0 } +#define DEFAULT_UP_THRESHOLD { 25, 0 } +#define DEFAULT_LOW_THRESHOLD { 0, 0 } + +static void temp_nrfs_handle_event(const struct device *dev) +{ + struct temp_nrfs_data *data = dev->data; + struct sensor_trigger trigger; + sensor_trigger_handler_t handler; + + k_mutex_lock(&data->mutex, K_FOREVER); + trigger = data->trigger; + handler = data->handler; + k_mutex_unlock(&data->mutex); + + if (handler) { + handler(dev, &trigger); + } +} + +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) +static void temp_nrfs_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct temp_nrfs_data *data = p1; + + while (1) { + k_sem_take(&data->event_sem, K_FOREVER); + temp_nrfs_handle_event(data->dev); + } +} +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) +static void temp_nrfs_work_handler(struct k_work *work) +{ + struct temp_nrfs_data *data = + CONTAINER_OF(work, struct temp_nrfs_data, work); + + temp_nrfs_handle_event(data->dev); +} +#endif + +static uint16_t to_measure_rate_ms(const struct sensor_value *freq_val) +{ + uint32_t measure_rate_ms = (MSEC_PER_SEC * 1000) / + (uint32_t)sensor_value_to_milli(freq_val); + + return (uint16_t)MIN(measure_rate_ms, UINT16_MAX); +} + +static int32_t to_raw_temp(const struct sensor_value *temp_val) +{ + int32_t temp_mul_100 = (int32_t)(sensor_value_to_milli(temp_val) / 10); + + return nrfs_temp_to_raw(temp_mul_100); +} + +static int api_sensor_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct temp_nrfs_data *data = dev->data; + nrfs_err_t err; + + if (trig->chan != SENSOR_CHAN_ALL && + trig->chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + switch (trig->type) { + case SENSOR_TRIG_THRESHOLD: + k_mutex_lock(&data->mutex, K_FOREVER); + data->trigger = *trig; + data->handler = handler; + k_mutex_unlock(&data->mutex); + + if (handler) { + err = nrfs_temp_subscribe( + to_measure_rate_ms(&data->sampling_freq), + to_raw_temp(&data->low_threshold), + to_raw_temp(&data->up_threshold), + data); + } else { + err = nrfs_temp_unsubscribe(); + } + + switch (err) { + case NRFS_SUCCESS: + break; + case NRFS_ERR_INVALID_STATE: + return -EAGAIN; + default: + return -EIO; + } + break; + + default: + return -ENOTSUP; + } + + return 0; +} + +static int api_sensor_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + struct temp_nrfs_data *data = dev->data; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + if (sensor_value_to_milli(val) <= 0) { + return -EINVAL; + } + data->sampling_freq = *val; + break; + case SENSOR_ATTR_UPPER_THRESH: + data->up_threshold = *val; + break; + case SENSOR_ATTR_LOWER_THRESH: + data->low_threshold = *val; + break; + default: + return -ENOTSUP; + } + return 0; +} + +#endif /* CONFIG_TEMP_NRFS_TRIGGER */ + +static void sensor_handler(nrfs_temp_evt_t const *p_evt, void *context) +{ + ARG_UNUSED(context); + + struct temp_nrfs_data *data = context; + + switch (p_evt->type) { + case NRFS_TEMP_EVT_MEASURE_DONE: + data->raw_temp = p_evt->raw_temp; + k_sem_give(&data->measure_sem); + break; + +#ifdef CONFIG_TEMP_NRFS_TRIGGER + case NRFS_TEMP_EVT_CHANGE: + data->raw_temp = p_evt->raw_temp; +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + k_sem_give(&data->event_sem); +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif + break; +#endif /* CONFIG_TEMP_NRFS_TRIGGER */ + + default: + LOG_DBG("Temperature handler - unsupported event: 0x%x", + p_evt->type); + break; + } +} + +static int api_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct temp_nrfs_data *data = dev->data; + int nrfs_rc; + int rc = 0; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + k_mutex_lock(&data->mutex, K_FOREVER); + nrfs_rc = nrfs_temp_measure_request(data); + switch (nrfs_rc) { + case NRFS_SUCCESS: + k_sem_take(&data->measure_sem, K_FOREVER); + LOG_DBG("Temperature sample: %d", data->raw_temp); + break; + case NRFS_ERR_INVALID_STATE: + LOG_DBG("Backend is not ready, try again."); + rc = -EAGAIN; + break; + default: + LOG_DBG("Measure request failed: %d", nrfs_rc); + rc = -EIO; + break; + } + k_mutex_unlock(&data->mutex); + + return rc; +} + +static int api_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct temp_nrfs_data *data = dev->data; + + if (chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + int32_t uval = nrfs_temp_from_raw(data->raw_temp); + + val->val1 = uval / 100; + val->val2 = (abs(uval) % 100) * 10000; + + LOG_DBG("Temperature: %d.%02u[C]", uval / 100, abs(uval) % 100); + + return 0; +} + +static int temp_nrfs_init(const struct device *dev) +{ + int rc; + + rc = nrfs_temp_init(sensor_handler); + if (rc < 0) { + return rc; + } + +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + struct temp_nrfs_data *data = dev->data; + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_TEMP_NRFS_THREAD_STACK_SIZE, + temp_nrfs_thread, + data, NULL, NULL, + K_PRIO_COOP(CONFIG_TEMP_NRFS_THREAD_PRIORITY), + 0, K_NO_WAIT); + k_thread_name_set(&data->thread, dev->name); +#endif + + return 0; +} + +static const struct sensor_driver_api temp_nrfs_drv_api = { +#ifdef CONFIG_TEMP_NRFS_TRIGGER + .attr_set = api_sensor_attr_set, + .trigger_set = api_sensor_trigger_set, +#endif + .sample_fetch = api_sample_fetch, + .channel_get = api_channel_get +}; + +static struct temp_nrfs_data temp_nrfs_drv_data = { + .mutex = Z_MUTEX_INITIALIZER(temp_nrfs_drv_data.mutex), + .measure_sem = Z_SEM_INITIALIZER(temp_nrfs_drv_data.measure_sem, 0, 1), +#ifdef CONFIG_TEMP_NRFS_TRIGGER + .dev = DEVICE_DT_INST_GET(0), + .sampling_freq = DEFAULT_SAMPLING_FREQ, + .up_threshold = DEFAULT_UP_THRESHOLD, + .low_threshold = DEFAULT_LOW_THRESHOLD, +#endif +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + .event_sem = Z_SEM_INITIALIZER(temp_nrfs_drv_data.event_sem, 0, 1), +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) + .work = Z_WORK_INITIALIZER(temp_nrfs_work_handler), +#endif +}; + +DEVICE_DT_INST_DEFINE(0, temp_nrfs_init, NULL, + &temp_nrfs_drv_data, NULL, + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, + &temp_nrfs_drv_api); diff --git a/dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml b/dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml new file mode 100644 index 00000000000000..2a77552b3bfef1 --- /dev/null +++ b/dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nRF family temperature sensor accessed via nRF Services (nrfs) + +compatible: "nordic,nrf-temp-nrfs" + +include: base.yaml diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 7436f9b936db57..a4b70ddcb3c80f 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -1076,4 +1076,9 @@ #address-cells = <1>; }; }; + + temp_nrfs: temp { + compatible = "nordic,nrf-temp-nrfs"; + status = "disabled"; + }; }; From 61eb00a3f68863a5f1788722535cf4fbee7eccb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0700/1389] tests: drivers: Add test for temperature sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a simple test intended primarily for checking the nRF temperature sensor in its nrfs variant but intentionally was made generic enough that it should be usable with other temperature sensors (after just providing an overlay) and could be helpful in development of new temperature sensor drivers, and possibly extended then if needed. Signed-off-by: Andrzej Głąbek --- .../drivers/sensor/temp_sensor/CMakeLists.txt | 10 ++ .../boards/nrf52840dk_nrf52840.overlay | 3 + .../boards/nrf54h20dk_nrf54h20_cpuapp.conf | 2 + .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 3 + tests/drivers/sensor/temp_sensor/prj.conf | 2 + tests/drivers/sensor/temp_sensor/src/main.c | 150 ++++++++++++++++++ .../drivers/sensor/temp_sensor/testcase.yaml | 9 ++ 7 files changed, 179 insertions(+) create mode 100644 tests/drivers/sensor/temp_sensor/CMakeLists.txt create mode 100644 tests/drivers/sensor/temp_sensor/boards/nrf52840dk_nrf52840.overlay create mode 100644 tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.conf create mode 100644 tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/sensor/temp_sensor/prj.conf create mode 100644 tests/drivers/sensor/temp_sensor/src/main.c create mode 100644 tests/drivers/sensor/temp_sensor/testcase.yaml diff --git a/tests/drivers/sensor/temp_sensor/CMakeLists.txt b/tests/drivers/sensor/temp_sensor/CMakeLists.txt new file mode 100644 index 00000000000000..6aed768ebdae1b --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(temp_sensor) + +FILE(GLOB app_sources src/*.c) + +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/sensor/temp_sensor/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/sensor/temp_sensor/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..435e4f4a6ccf81 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,3 @@ +temp_sensor: &temp { + status = "okay"; +}; diff --git a/tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000000..371797173d9791 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,2 @@ +CONFIG_NRFS=y +CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD=y diff --git a/tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..012c93a8fa81bc --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,3 @@ +temp_sensor: &temp_nrfs { + status = "okay"; +}; diff --git a/tests/drivers/sensor/temp_sensor/prj.conf b/tests/drivers/sensor/temp_sensor/prj.conf new file mode 100644 index 00000000000000..97305dd78ef975 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SENSOR=y diff --git a/tests/drivers/sensor/temp_sensor/src/main.c b/tests/drivers/sensor/temp_sensor/src/main.c new file mode 100644 index 00000000000000..ba4da1f417398b --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/src/main.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2024, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static const struct device *temp_dev = DEVICE_DT_GET(DT_NODELABEL(temp_sensor)); +static enum sensor_channel chan_to_use; /* this is filled by before() */ + +static volatile bool trigger_handler_called; + +ZTEST(temp_sensor, test_polling) +{ + int rc; + int cnt; + struct sensor_value val; + + cnt = 0; + while (1) { + int32_t temp_val; + + rc = sensor_sample_fetch_chan(temp_dev, chan_to_use); + zassert_ok(rc, "Cannot fetch chan sample: %d.", rc); + + rc = sensor_channel_get(temp_dev, chan_to_use, &val); + zassert_ok(rc, "Cannot read from channel %d: %d.", + chan_to_use, rc); + + temp_val = (val.val1 * 100) + (val.val2 / 10000); + TC_PRINT("Temperature: %d.%02u\n", + temp_val/100, abs(temp_val) % 100); + + ++cnt; + if (cnt >= 5) { + break; + } + + k_sleep(K_MSEC(500)); + } +} + +static void trigger_handler(const struct device *temp_dev, + const struct sensor_trigger *trig) +{ + ARG_UNUSED(temp_dev); + ARG_UNUSED(trig); + + trigger_handler_called = true; +} + +ZTEST(temp_sensor, test_trigger) +{ + int rc; + struct sensor_value val; + struct sensor_trigger trig = { .type = SENSOR_TRIG_THRESHOLD, + .chan = chan_to_use }; + + /* Check if the sensor allows setting a threshold trigger. + * If not, skip the test. + */ + rc = sensor_trigger_set(temp_dev, &trig, NULL); + if (rc == -ENOSYS || rc == -ENOTSUP) { + TC_PRINT("This sensor does not support threshold trigger.\n"); + ztest_test_skip(); + } + + rc = sensor_channel_get(temp_dev, chan_to_use, &val); + zassert_ok(rc, "Cannot read from channel %d: %d.", + chan_to_use, rc); + + /* Set the upper threshold somewhat below the temperature read above. */ + val.val1 -= 5; + rc = sensor_attr_set(temp_dev, chan_to_use, + SENSOR_ATTR_UPPER_THRESH, &val); + zassert_ok(rc, "Cannot set upper threshold: %d.", rc); + + /* And the lower threshold below the upper one. */ + val.val1 -= 1; + rc = sensor_attr_set(temp_dev, chan_to_use, + SENSOR_ATTR_LOWER_THRESH, &val); + zassert_ok(rc, "Cannot set lower threshold: %d.", rc); + + /* Set sampling frequency to 10 Hz, to expect a trigger after 100 ms. */ + val.val1 = 10; + val.val2 = 0; + rc = sensor_attr_set(temp_dev, chan_to_use, + SENSOR_ATTR_SAMPLING_FREQUENCY, &val); + zassert_ok(rc, "Cannot set sampling frequency: %d.", rc); + + trigger_handler_called = false; + + rc = sensor_trigger_set(temp_dev, &trig, trigger_handler); + zassert_ok(rc, "Cannot enable the trigger: %d.", rc); + + k_sleep(K_MSEC(300)); + zassert_true(trigger_handler_called); + + rc = sensor_trigger_set(temp_dev, &trig, NULL); + zassert_ok(rc, "Cannot disable the trigger: %d.", rc); + + trigger_handler_called = false; + + k_sleep(K_MSEC(300)); + zassert_false(trigger_handler_called); +} + +static void before(void *fixture) +{ + ARG_UNUSED(fixture); + + int rc; + int cnt; + struct sensor_value val; + + zassert_true(device_is_ready(temp_dev), + "Device %s is not ready.", temp_dev->name); + + cnt = 0; + /* Try to fetch a sample to check if the sensor is ready to work. + * Try several times if it appears to be needing a while for some + * initialization of communication etc. + */ + while (1) { + rc = sensor_sample_fetch(temp_dev); + if (rc != -EAGAIN && rc != -ENOTCONN) { + break; + } + + ++cnt; + zassert_false(cnt >= 3, "Cannot fetch a sample: %d.", rc); + + k_sleep(K_MSEC(1000)); + } + zassert_ok(rc, "Cannot fetch a sample: %d.", rc); + + /* Check if the sensor provides the die temperature. + * If not, switch to the ambient one. + */ + chan_to_use = SENSOR_CHAN_DIE_TEMP; + rc = sensor_channel_get(temp_dev, chan_to_use, &val); + if (rc == -ENOTSUP) { + chan_to_use = SENSOR_CHAN_AMBIENT_TEMP; + } +} + +ZTEST_SUITE(temp_sensor, NULL, NULL, before, NULL, NULL); diff --git a/tests/drivers/sensor/temp_sensor/testcase.yaml b/tests/drivers/sensor/temp_sensor/testcase.yaml new file mode 100644 index 00000000000000..1a12dcb270d819 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/testcase.yaml @@ -0,0 +1,9 @@ +tests: + drivers.sensor.temp_sensor: + tags: + - drivers + - sensors + filter: dt_nodelabel_enabled("temp_sensor") + integration_platforms: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp From e9b24b4d861f2cce9dcff72d8a845642ddbedede Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0701/1389] dts: bindings: introduce a new compatible for stm32 xSPI flash controller The new bindings for the stm32 xspi is for new stm32 devices with XSPI peripherals like the stm32h5 serie. This is close to the octo-spi. Adapt the flash controller constants to the XSPI model especially. This is done through a new xspi.h definition file. Signed-off-by: Francois Ramu --- .../flash_controller/st,stm32-xspi-nor.yaml | 53 +++++++++++++++++++ dts/bindings/xspi/st,stm32-xspi.yaml | 9 ++++ .../dt-bindings/flash_controller/xspi.h | 31 +++++++++++ 3 files changed, 93 insertions(+) create mode 100644 dts/bindings/flash_controller/st,stm32-xspi-nor.yaml create mode 100644 dts/bindings/xspi/st,stm32-xspi.yaml create mode 100644 include/zephyr/dt-bindings/flash_controller/xspi.h diff --git a/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml b/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml new file mode 100644 index 00000000000000..f2ade8c7689c8c --- /dev/null +++ b/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml @@ -0,0 +1,53 @@ +# Copyright (c) 2021 - 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 XSPI Flash controller supporting the JEDEC CFI interface + + Representation of a serial flash on a xspi bus: + + mx25lm51245: xspi-nor-flash@70000000 { + compatible = "st,stm32-xspi-nor"; + reg = <0x70000000 DT_SIZE_M(64)>; /* 512 Mbits */ + data-mode = ; /* access on 8 data lines */ + data-rate = ; /* access in DTR */ + ospi-max-frequency = ; + status = "okay"; + }; + +compatible: "st,stm32-xspi-nor" + +include: + - name: st,stm32-ospi-nor.yaml + property-blocklist: + - spi-bus-width + - data-rate +properties: + spi-bus-width: + type: int + required: true + description: | + The width of XSPI bus to which flash memory is connected. + + Possible values are : + - XSPI_SPI_MODE <1> = SPI mode on 1 data line + - XSPI_DUAL_MODE <2> = Dual mode on 2 data lines + - XSPI_QUAD_MODE <4> = Quad mode on 4 data lines + - XSPI_OCTO_MODE <8> = Octo mode on 8 data lines + enum: + - 1 + - 2 + - 4 + - 8 + data-rate: + type: int + required: true + description: | + The SPI data Rate is STR or DTR + + Possible values are : + - XSPI_STR_TRANSFER <1> = Single Rate Transfer + - XSPI_DTR_TRANSFER <2> = Dual Rate Transfer (only with XSPI_OCTO_MODE) + enum: + - 1 + - 2 diff --git a/dts/bindings/xspi/st,stm32-xspi.yaml b/dts/bindings/xspi/st,stm32-xspi.yaml new file mode 100644 index 00000000000000..388c3d20bca1ca --- /dev/null +++ b/dts/bindings/xspi/st,stm32-xspi.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 XSPI device representation. Enabling a stm32 xspi node in a board + +compatible: "st,stm32-xspi" + +include: st,stm32-ospi.yaml diff --git a/include/zephyr/dt-bindings/flash_controller/xspi.h b/include/zephyr/dt-bindings/flash_controller/xspi.h new file mode 100644 index 00000000000000..3e0610e80905d8 --- /dev/null +++ b/include/zephyr/dt-bindings/flash_controller/xspi.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_XSPI_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_XSPI_H_ + +/** + * @name XSPI definition for the xSPI peripherals + * Note that + * SPI mode inpossible in STR transfer rate only + */ + +/* XSPI mode operating on 1 line, 2 lines, 4 lines or 8 lines */ +/* 1 Cmd Line, 1 Address Line and 1 Data Line */ +#define XSPI_SPI_MODE 1 +/* 2 Cmd Lines, 2 Address Lines and 2 Data Lines */ +#define XSPI_DUAL_MODE 2 +/* 4 Cmd Lines, 4 Address Lines and 4 Data Lines */ +#define XSPI_QUAD_MODE 4 +/* 8 Cmd Lines, 8 Address Lines and 8 Data Lines */ +#define XSPI_OCTO_MODE 8 + +/* XSPI mode operating on Single or Double Transfer Rate */ +/* Single Transfer Rate */ +#define XSPI_STR_TRANSFER 1 +/* Double Transfer Rate */ +#define XSPI_DTR_TRANSFER 2 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_XSPI_H_ */ From 0f11ea90c4356e18a43607410bc6e88c83575983 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0702/1389] drivers: flash: stm32 flash driver for xspi instance Introduce a XSPI driver to cover the common XSPI peripherals of the stm32 mcu: X is for single or quad or octo or hexa SPI bus access to external memories DMA not supported in this version Signed-off-by: Francois Ramu --- drivers/flash/CMakeLists.txt | 1 + drivers/flash/Kconfig | 2 + drivers/flash/Kconfig.stm32_xspi | 18 + drivers/flash/flash_stm32_xspi.c | 2072 ++++++++++++++++++++++++++++++ drivers/flash/flash_stm32_xspi.h | 70 + 5 files changed, 2163 insertions(+) create mode 100644 drivers/flash/Kconfig.stm32_xspi create mode 100644 drivers/flash/flash_stm32_xspi.c create mode 100644 drivers/flash/flash_stm32_xspi.h diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index ac7564c4708ea2..54b9178c091831 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -42,6 +42,7 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_QSPI flash_npcx_fiu_qspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_NOR flash_npcx_fiu_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_OSPI flash_stm32_ospi.c) +zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_XSPI flash_stm32_xspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G flash_mcux_flexspi_mx25um51345g.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_NOR flash_mcux_flexspi_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH flash_mcux_flexspi_hyperflash.c) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 6a1f816aa55ac8..441a79868786f5 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -132,6 +132,8 @@ source "drivers/flash/Kconfig.stm32_qspi" source "drivers/flash/Kconfig.stm32_ospi" +source "drivers/flash/Kconfig.stm32_xspi" + source "drivers/flash/Kconfig.sam0" source "drivers/flash/Kconfig.sam" diff --git a/drivers/flash/Kconfig.stm32_xspi b/drivers/flash/Kconfig.stm32_xspi new file mode 100644 index 00000000000000..3bea03801f3e35 --- /dev/null +++ b/drivers/flash/Kconfig.stm32_xspi @@ -0,0 +1,18 @@ +# STM32 xSPI flash driver configuration options + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config FLASH_STM32_XSPI + bool "STM32 XSPI Flash driver" + default y + depends on DT_HAS_ST_STM32_XSPI_ENABLED && DT_HAS_ST_STM32_XSPI_NOR_ENABLED + select USE_STM32_HAL_XSPI + select USE_STM32_LL_DLYB + select FLASH_HAS_DRIVER_ENABLED + select FLASH_JESD216 + select FLASH_PAGE_LAYOUT + select FLASH_HAS_PAGE_LAYOUT + + help + Enable XSPI-NOR support on the STM32 family of processors. diff --git a/drivers/flash/flash_stm32_xspi.c b/drivers/flash/flash_stm32_xspi.c new file mode 100644 index 00000000000000..ae08e1d07cdc14 --- /dev/null +++ b/drivers/flash/flash_stm32_xspi.c @@ -0,0 +1,2072 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ************************************************************************** + * xSPI flash controller driver for stm32 serie with xSPI periherals + * This driver is based on the stm32Cube HAL XSPI driver + * with one xspi DTS NODE + * ************************************************************************** + */ +#define DT_DRV_COMPAT st_stm32_xspi_nor + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spi_nor.h" +#include "jesd216.h" + +#include +LOG_MODULE_REGISTER(flash_stm32_xspi, CONFIG_FLASH_LOG_LEVEL); + +#define STM32_XSPI_NODE DT_INST_PARENT(0) + +#define DT_XSPI_IO_PORT_PROP_OR(prop, default_value) \ + COND_CODE_1(DT_NODE_HAS_PROP(STM32_XSPI_NODE, prop), \ + (_CONCAT(HAL_XSPIM_, DT_STRING_TOKEN(STM32_XSPI_NODE, prop))), \ + ((default_value))) + +/* Get the base address of the flash from the DTS node */ +#define STM32_XSPI_BASE_ADDRESS DT_INST_REG_ADDR(0) + +#define STM32_XSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) + +#define STM32_XSPI_DLYB_BYPASSED DT_PROP(STM32_XSPI_NODE, dlyb_bypass) + +#include "flash_stm32_xspi.h" + +static inline void xspi_lock_thread(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + k_sem_take(&dev_data->sem, K_FOREVER); +} + +static inline void xspi_unlock_thread(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + k_sem_give(&dev_data->sem); +} + +static int xspi_send_cmd(const struct device *dev, XSPI_RegularCmdTypeDef *cmd) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + LOG_DBG("Instruction 0x%x", cmd->Instruction); + + dev_data->cmd_status = 0; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + LOG_DBG("CCR 0x%x", dev_data->hxspi.Instance->CCR); + + return dev_data->cmd_status; +} + +static int xspi_read_access(const struct device *dev, XSPI_RegularCmdTypeDef *cmd, + uint8_t *data, const size_t size) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + LOG_DBG("Instruction 0x%x", cmd->Instruction); + + cmd->DataLength = size; + + dev_data->cmd_status = 0; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_XSPI_Receive_IT(&dev_data->hxspi, data); + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + k_sem_take(&dev_data->sync, K_FOREVER); + + return dev_data->cmd_status; +} + +static int xspi_write_access(const struct device *dev, XSPI_RegularCmdTypeDef *cmd, + const uint8_t *data, const size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + LOG_DBG("Instruction 0x%x", cmd->Instruction); + + cmd->DataLength = size; + + dev_data->cmd_status = 0; + + /* in OPI/STR the 3-byte AddressWidth is not supported by the NOR flash */ + if ((dev_cfg->data_mode == XSPI_OCTO_MODE) && + (cmd->AddressWidth != HAL_XSPI_ADDRESS_32_BITS)) { + LOG_ERR("XSPI wr in OPI/STR mode is for 32bit address only"); + return -EIO; + } + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_XSPI_Transmit_IT(&dev_data->hxspi, (uint8_t *)data); + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to write data", hal_ret); + return -EIO; + } + + k_sem_take(&dev_data->sync, K_FOREVER); + + return dev_data->cmd_status; +} + +/* + * Gives a XSPI_RegularCmdTypeDef with all parameters set + * except Instruction, Address, DummyCycles, NbData + */ +static XSPI_RegularCmdTypeDef xspi_prepare_cmd(const uint8_t transfer_mode, + const uint8_t transfer_rate) +{ + XSPI_RegularCmdTypeDef cmd_tmp = { + .OperationType = HAL_XSPI_OPTYPE_COMMON_CFG, + .InstructionWidth = ((transfer_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_INSTRUCTION_16_BITS + : HAL_XSPI_INSTRUCTION_8_BITS), + .InstructionDTRMode = ((transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_INSTRUCTION_DTR_ENABLE + : HAL_XSPI_INSTRUCTION_DTR_DISABLE), + .AddressDTRMode = ((transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_ADDRESS_DTR_ENABLE + : HAL_XSPI_ADDRESS_DTR_DISABLE), + /* AddressWidth must be set to 32bits for init and mem config phase */ + .AddressWidth = HAL_XSPI_ADDRESS_32_BITS, + .AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE, + .DataDTRMode = ((transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_DATA_DTR_ENABLE + : HAL_XSPI_DATA_DTR_DISABLE), + .DQSMode = (transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_DQS_ENABLE + : HAL_XSPI_DQS_DISABLE, + .SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD, + }; + + switch (transfer_mode) { + case XSPI_OCTO_MODE: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_8_LINES; + cmd_tmp.DataMode = HAL_XSPI_DATA_8_LINES; + break; + } + case XSPI_QUAD_MODE: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_4_LINES; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_4_LINES; + cmd_tmp.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + case XSPI_DUAL_MODE: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_2_LINES; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_2_LINES; + cmd_tmp.DataMode = HAL_XSPI_DATA_2_LINES; + break; + } + default: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd_tmp.DataMode = HAL_XSPI_DATA_1_LINE; + break; + } + } + + return cmd_tmp; +} + +static uint32_t stm32_xspi_hal_address_size(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + if (dev_data->address_width == 4U) { + return HAL_XSPI_ADDRESS_32_BITS; + } + + return HAL_XSPI_ADDRESS_24_BITS; +} + +#if defined(CONFIG_FLASH_JESD216_API) +/* + * Read the JEDEC ID data from the external Flash at init + * and store in the jedec_id Table of the flash_stm32_xspi_data + * The JEDEC ID is not given by a DTS property + */ +static int stm32_xspi_read_jedec_id(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + /* This is a SPI/STR command to issue to the external Flash device */ + XSPI_RegularCmdTypeDef cmd = xspi_prepare_cmd(XSPI_SPI_MODE, XSPI_STR_TRANSFER); + + cmd.Instruction = JESD216_CMD_READ_ID; + cmd.AddressWidth = stm32_xspi_hal_address_size(dev); + cmd.AddressMode = HAL_XSPI_ADDRESS_NONE; + cmd.DataLength = JESD216_READ_ID_LEN; /* 3 bytes in the READ ID */ + + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, &cmd, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + + /* Place the received data directly into the jedec Table */ + hal_ret = HAL_XSPI_Receive(&dev_data->hxspi, dev_data->jedec_id, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + LOG_DBG("Jedec ID = [%02x %02x %02x]", + dev_data->jedec_id[0], dev_data->jedec_id[1], dev_data->jedec_id[2]); + + dev_data->cmd_status = 0; + + return 0; +} + +/* + * Read Serial Flash ID : + * just gives the values received by the external Flash + */ +static int xspi_read_jedec_id(const struct device *dev, uint8_t *id) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + /* Take jedec Id values from the table (issued from the octoFlash) */ + memcpy(id, dev_data->jedec_id, JESD216_READ_ID_LEN); + + LOG_INF("Manuf ID = %02x Memory Type = %02x Memory Density = %02x", + id[0], id[1], id[2]); + + return 0; +} +#endif /* CONFIG_FLASH_JESD216_API */ + +/* + * Read Serial Flash Discovery Parameter from the external Flash at init : + * perform a read access over SPI bus for SDFP (DataMode is already set) + * The SFDP table is not given by a DTS property + */ +static int stm32_xspi_read_sfdp(const struct device *dev, off_t addr, + void *data, + size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + + XSPI_RegularCmdTypeDef cmd = xspi_prepare_cmd(dev_cfg->data_mode, + dev_cfg->data_rate); + if (dev_cfg->data_mode == XSPI_OCTO_MODE) { + cmd.Instruction = JESD216_OCMD_READ_SFDP; + cmd.DummyCycles = 20U; + cmd.AddressWidth = HAL_XSPI_ADDRESS_32_BITS; + } else { + cmd.Instruction = JESD216_CMD_READ_SFDP; + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.DataMode = HAL_XSPI_DATA_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd.DummyCycles = 8U; + cmd.AddressWidth = HAL_XSPI_ADDRESS_24_BITS; + } + cmd.Address = addr; + cmd.DataLength = size; + + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, &cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_XSPI_Receive(&dev_data->hxspi, (uint8_t *)data, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + dev_data->cmd_status = 0; + + return 0; +} + +/* + * Read Serial Flash Discovery Parameter : + * perform a read access over SPI bus for SDFP (DataMode is already set) + */ +static int xspi_read_sfdp(const struct device *dev, off_t addr, void *data, + size_t size) +{ + LOG_INF("Read SFDP from externalFlash"); + /* Get the SFDP from the external Flash (no sfdp-bfp table in the DeviceTree) */ + if (stm32_xspi_read_sfdp(dev, addr, data, size) == 0) { + /* If valid, then ignore any table from the DTS */ + return 0; + } + LOG_INF("Error reading SFDP from external Flash and none in the DTS"); + return -EINVAL; +} + +static bool xspi_address_is_valid(const struct device *dev, off_t addr, + size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + size_t flash_size = dev_cfg->flash_size; + + return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size); +} + +static int stm32_xspi_wait_auto_polling(const struct device *dev, + XSPI_AutoPollingTypeDef *s_config, uint32_t timeout_ms) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + dev_data->cmd_status = 0; + + if (HAL_XSPI_AutoPolling_IT(&dev_data->hxspi, s_config) != HAL_OK) { + LOG_ERR("XSPI AutoPoll failed"); + return -EIO; + } + + if (k_sem_take(&dev_data->sync, K_MSEC(timeout_ms)) != 0) { + LOG_ERR("XSPI AutoPoll wait failed"); + HAL_XSPI_Abort(&dev_data->hxspi); + k_sem_reset(&dev_data->sync); + return -EIO; + } + + /* HAL_XSPI_AutoPolling_IT enables transfer error interrupt which sets + * cmd_status. + */ + return dev_data->cmd_status; +} + +/* + * This function Polls the WEL (write enable latch) bit to become to 0 + * When the Chip Erase Cycle is completed, the Write Enable Latch (WEL) bit is cleared. + * in nor_mode SPI/OPI XSPI_SPI_MODE or XSPI_OCTO_MODE + * and nor_rate transfer STR/DTR XSPI_STR_TRANSFER or XSPI_DTR_TRANSFER + */ +static int stm32_xspi_mem_erased(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + uint8_t nor_mode = dev_cfg->data_mode; + uint8_t nor_rate = dev_cfg->data_rate; + + XSPI_AutoPollingTypeDef s_config = {0}; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Configure automatic polling mode command to wait for memory ready */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_RDSR; + s_command.DummyCycles = (nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL; + } else { + s_command.Instruction = SPI_NOR_CMD_RDSR; + /* force 1-line InstructionMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = HAL_XSPI_ADDRESS_NONE; + /* force 1-line DataMode for any non-OSPI transfer */ + s_command.DataMode = HAL_XSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + } + s_command.DataLength = ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + s_command.Address = 0U; + + /* Set the mask to 0x02 to mask all Status REG bits except WEL */ + /* Set the match to 0x00 to check if the WEL bit is Reset */ + s_config.MatchValue = SPI_NOR_WEL_MATCH; + s_config.MatchMask = SPI_NOR_WEL_MASK; /* Write Enable Latch */ + + s_config.MatchMode = HAL_XSPI_MATCH_MODE_AND; + s_config.IntervalTime = SPI_NOR_AUTO_POLLING_INTERVAL; + s_config.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI AutoPoll command (WEL) failed"); + return -EIO; + } + + /* Start Automatic-Polling mode to wait until the memory is totally erased */ + return stm32_xspi_wait_auto_polling(dev, + &s_config, STM32_XSPI_BULK_ERASE_MAX_TIME); +} + +/* + * This function Polls the WIP(Write In Progress) bit to become to 0 + * in nor_mode SPI/OPI XSPI_SPI_MODE or XSPI_OCTO_MODE + * and nor_rate transfer STR/DTR XSPI_STR_TRANSFER or XSPI_DTR_TRANSFER + */ +static int stm32_xspi_mem_ready(const struct device *dev, uint8_t nor_mode, + uint8_t nor_rate) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + XSPI_AutoPollingTypeDef s_config = {0}; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Configure automatic polling mode command to wait for memory ready */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_RDSR; + s_command.DummyCycles = (nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL; + } else { + s_command.Instruction = SPI_NOR_CMD_RDSR; + /* force 1-line InstructionMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = HAL_XSPI_ADDRESS_NONE; + /* force 1-line DataMode for any non-OSPI transfer */ + s_command.DataMode = HAL_XSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + } + s_command.DataLength = ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + s_command.Address = 0U; + + /* Set the mask to 0x01 to mask all Status REG bits except WIP */ + /* Set the match to 0x00 to check if the WIP bit is Reset */ + s_config.MatchValue = SPI_NOR_MEM_RDY_MATCH; + s_config.MatchMask = SPI_NOR_MEM_RDY_MASK; /* Write in progress */ + s_config.MatchMode = HAL_XSPI_MATCH_MODE_AND; + s_config.IntervalTime = SPI_NOR_AUTO_POLLING_INTERVAL; + s_config.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI AutoPoll command failed"); + return -EIO; + } + + /* Start Automatic-Polling mode to wait until the memory is ready WIP=0 */ + return stm32_xspi_wait_auto_polling(dev, &s_config, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); +} + +/* Enables writing to the memory sending a Write Enable and wait it is effective */ +static int stm32_xspi_write_enable(const struct device *dev, + uint8_t nor_mode, uint8_t nor_rate) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + XSPI_AutoPollingTypeDef s_config = {0}; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the write enable command */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_WREN; + } else { + s_command.Instruction = SPI_NOR_CMD_WREN; + /* force 1-line InstructionMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + } + s_command.AddressMode = HAL_XSPI_ADDRESS_NONE; + s_command.DataMode = HAL_XSPI_DATA_NONE; + s_command.DummyCycles = 0U; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI flash write enable cmd failed"); + return -EIO; + } + + /* New command to Configure automatic polling mode to wait for write enabling */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_RDSR; + s_command.AddressMode = HAL_XSPI_ADDRESS_8_LINES; + s_command.DataMode = HAL_XSPI_DATA_8_LINES; + s_command.DummyCycles = (nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL; + } else { + s_command.Instruction = SPI_NOR_CMD_RDSR; + /* force 1-line DataMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + s_command.DataMode = HAL_XSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + + /* DummyCycles remains 0 */ + } + s_command.DataLength = (nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U; + s_command.Address = 0U; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI config auto polling cmd failed"); + return -EIO; + } + + s_config.MatchValue = SPI_NOR_WREN_MATCH; + s_config.MatchMask = SPI_NOR_WREN_MASK; + s_config.MatchMode = HAL_XSPI_MATCH_MODE_AND; + s_config.IntervalTime = SPI_NOR_AUTO_POLLING_INTERVAL; + s_config.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE; + + return stm32_xspi_wait_auto_polling(dev, &s_config, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); +} + +/* Write Flash configuration register 2 with new dummy cycles */ +static int stm32_xspi_write_cfg2reg_dummy(XSPI_HandleTypeDef *hxspi, + uint8_t nor_mode, uint8_t nor_rate) +{ + uint8_t transmit_data = SPI_NOR_CR2_DUMMY_CYCLES_66MHZ; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the writing of configuration register 2 */ + s_command.Instruction = (nor_mode == XSPI_SPI_MODE) + ? SPI_NOR_CMD_WR_CFGREG2 + : SPI_NOR_OCMD_WR_CFGREG2; + s_command.Address = SPI_NOR_REG2_ADDR3; + s_command.DummyCycles = 0U; + s_command.DataLength = (nor_mode == XSPI_SPI_MODE) ? 1U + : ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + + if (HAL_XSPI_Command(hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI transmit cmd"); + return -EIO; + } + + if (HAL_XSPI_Transmit(hxspi, &transmit_data, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI transmit "); + return -EIO; + } + + return 0; +} + +/* Write Flash configuration register 2 with new single or octal SPI protocol */ +static int stm32_xspi_write_cfg2reg_io(XSPI_HandleTypeDef *hxspi, + uint8_t nor_mode, uint8_t nor_rate, uint8_t op_enable) +{ + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the writing of configuration register 2 */ + s_command.Instruction = (nor_mode == XSPI_SPI_MODE) + ? SPI_NOR_CMD_WR_CFGREG2 + : SPI_NOR_OCMD_WR_CFGREG2; + s_command.Address = SPI_NOR_REG2_ADDR1; + s_command.DummyCycles = 0U; + s_command.DataLength = (nor_mode == XSPI_SPI_MODE) ? 1U + : ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + + if (HAL_XSPI_Command(hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + if (HAL_XSPI_Transmit(hxspi, &op_enable, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + return 0; +} + +/* Read Flash configuration register 2 with new single or octal SPI protocol */ +static int stm32_xspi_read_cfg2reg(XSPI_HandleTypeDef *hxspi, + uint8_t nor_mode, uint8_t nor_rate, uint8_t *value) +{ + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the writing of configuration register 2 */ + s_command.Instruction = (nor_mode == XSPI_SPI_MODE) + ? SPI_NOR_CMD_RD_CFGREG2 + : SPI_NOR_OCMD_RD_CFGREG2; + s_command.Address = SPI_NOR_REG2_ADDR1; + s_command.DummyCycles = (nor_mode == XSPI_SPI_MODE) + ? 0U + : ((nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL); + s_command.DataLength = (nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U; + + if (HAL_XSPI_Command(hxspi, &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + if (HAL_XSPI_Receive(hxspi, value, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + return 0; +} + +/* Set the NOR Flash to desired Interface mode : SPI/OSPI and STR/DTR according to the DTS */ +static int stm32_xspi_config_mem(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + uint8_t reg[2]; + + /* Going to set the SPI mode and STR transfer rate : done */ + if ((dev_cfg->data_mode != XSPI_OCTO_MODE) + && (dev_cfg->data_rate == XSPI_STR_TRANSFER)) { + LOG_INF("OSPI flash config is SPI|DUAL|QUAD / STR"); + return 0; + } + + /* Going to set the XPI mode (STR or DTR transfer rate) */ + LOG_DBG("XSPI configuring Octo SPI mode"); + + if (stm32_xspi_write_enable(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("OSPI write Enable failed"); + return -EIO; + } + + /* Write Configuration register 2 (with new dummy cycles) */ + if (stm32_xspi_write_cfg2reg_dummy(&dev_data->hxspi, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI write CFGR2 failed"); + return -EIO; + } + if (stm32_xspi_mem_ready(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI autopolling failed"); + return -EIO; + } + if (stm32_xspi_write_enable(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI write Enable 2 failed"); + return -EIO; + } + + /* Write Configuration register 2 (with Octal I/O SPI protocol : choose STR or DTR) */ + uint8_t mode_enable = ((dev_cfg->data_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_CR2_DTR_OPI_EN + : SPI_NOR_CR2_STR_OPI_EN); + if (stm32_xspi_write_cfg2reg_io(&dev_data->hxspi, + XSPI_SPI_MODE, XSPI_STR_TRANSFER, mode_enable) != 0) { + LOG_ERR("XSPI write CFGR2 failed"); + return -EIO; + } + + /* Wait that the configuration is effective and check that memory is ready */ + k_busy_wait(STM32_XSPI_WRITE_REG_MAX_TIME * USEC_PER_MSEC); + + /* Reconfigure the memory type of the peripheral */ + dev_data->hxspi.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX; + dev_data->hxspi.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE; + if (HAL_XSPI_Init(&dev_data->hxspi) != HAL_OK) { + LOG_ERR("XSPI mem type MACRONIX failed"); + return -EIO; + } + + if (dev_cfg->data_rate == XSPI_STR_TRANSFER) { + if (stm32_xspi_mem_ready(dev, + XSPI_OCTO_MODE, XSPI_STR_TRANSFER) != 0) { + /* Check Flash busy ? */ + LOG_ERR("XSPI flash busy failed"); + return -EIO; + } + + if (stm32_xspi_read_cfg2reg(&dev_data->hxspi, + XSPI_OCTO_MODE, XSPI_STR_TRANSFER, reg) != 0) { + /* Check the configuration has been correctly done on SPI_NOR_REG2_ADDR1 */ + LOG_ERR("XSPI flash config read failed"); + return -EIO; + } + + LOG_INF("XSPI flash config is OCTO / STR"); + } + + if (dev_cfg->data_rate == XSPI_DTR_TRANSFER) { + if (stm32_xspi_mem_ready(dev, + XSPI_OCTO_MODE, XSPI_DTR_TRANSFER) != 0) { + /* Check Flash busy ? */ + LOG_ERR("XSPI flash busy failed"); + return -EIO; + } + + LOG_INF("XSPI flash config is OCTO / DTR"); + } + + return 0; +} + +/* gpio or send the different reset command to the NOR flash in SPI/OSPI and STR/DTR */ +static int stm32_xspi_mem_reset(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + +#if STM32_XSPI_RESET_GPIO + /* Generate RESETn pulse for the flash memory */ + gpio_pin_configure_dt(&dev_cfg->reset, GPIO_OUTPUT_ACTIVE); + k_msleep(DT_INST_PROP(0, reset_gpios_duration)); + gpio_pin_set_dt(&dev_cfg->reset, 0); +#else + + /* Reset command sent sucessively for each mode SPI/OPS & STR/DTR */ + XSPI_RegularCmdTypeDef s_command = { + .OperationType = HAL_XSPI_OPTYPE_COMMON_CFG, + .AddressMode = HAL_XSPI_ADDRESS_NONE, + .InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE, + .InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE, + .Instruction = SPI_NOR_CMD_RESET_EN, + .InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS, + .AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE, + .DataLength = HAL_XSPI_DATA_NONE, + .DummyCycles = 0U, + .DQSMode = HAL_XSPI_DQS_DISABLE, + .SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD, + }; + + /* Reset enable in SPI mode and STR transfer mode */ + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset enable (SPI/STR) failed"); + return -EIO; + } + + /* Reset memory in SPI mode and STR transfer mode */ + s_command.Instruction = SPI_NOR_CMD_RESET_MEM; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset memory (SPI/STR) failed"); + return -EIO; + } + + /* Reset enable in OPI mode and STR transfer mode */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES; + s_command.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE; + s_command.Instruction = SPI_NOR_OCMD_RESET_EN; + s_command.InstructionWidth = HAL_XSPI_INSTRUCTION_16_BITS; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset enable (OCTO/STR) failed"); + return -EIO; + } + + /* Reset memory in OPI mode and STR transfer mode */ + s_command.Instruction = SPI_NOR_OCMD_RESET_MEM; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset memory (OCTO/STR) failed"); + return -EIO; + } + + /* Reset enable in OPI mode and DTR transfer mode */ + s_command.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_ENABLE; + s_command.Instruction = SPI_NOR_OCMD_RESET_EN; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset enable (OCTO/DTR) failed"); + return -EIO; + } + + /* Reset memory in OPI mode and DTR transfer mode */ + s_command.Instruction = SPI_NOR_OCMD_RESET_MEM; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset memory (OCTO/DTR) failed"); + return -EIO; + } + +#endif /* STM32_XSPI_RESET_GPIO */ + /* Wait after SWreset CMD, in case SWReset occurred during erase operation */ + k_busy_wait(STM32_XSPI_RESET_MAX_TIME * USEC_PER_MSEC); + + return 0; +} + +/* + * Function to erase the flash : chip or sector with possible OCTO/SPI and STR/DTR + * to erase the complete chip (using dedicated command) : + * set size >= flash size + * set addr = 0 + */ +static int flash_stm32_xspi_erase(const struct device *dev, off_t addr, + size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + int ret = 0; + + /* Ignore zero size erase */ + if (size == 0) { + return 0; + } + + /* Maximise erase size : means the complete chip */ + if (size > dev_cfg->flash_size) { + size = dev_cfg->flash_size; + } + + if (!xspi_address_is_valid(dev, addr, size)) { + LOG_ERR("Error: address or size exceeds expected values: " + "addr 0x%lx, size %zu", (long)addr, size); + return -EINVAL; + } + + if (((size % SPI_NOR_SECTOR_SIZE) != 0) && (size < dev_cfg->flash_size)) { + LOG_ERR("Error: wrong sector size 0x%x", size); + return -ENOTSUP; + } + + XSPI_RegularCmdTypeDef cmd_erase = { + .OperationType = HAL_XSPI_OPTYPE_COMMON_CFG, + .AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE, + .DataMode = HAL_XSPI_DATA_NONE, + .DummyCycles = 0U, + .DQSMode = HAL_XSPI_DQS_DISABLE, + .SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD, + }; + + xspi_lock_thread(dev); + + if (stm32_xspi_mem_ready(dev, + dev_cfg->data_mode, dev_cfg->data_rate) != 0) { + xspi_unlock_thread(dev); + LOG_ERR("Erase failed : flash busy"); + return -EBUSY; + } + + cmd_erase.InstructionMode = (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_INSTRUCTION_8_LINES + : HAL_XSPI_INSTRUCTION_1_LINE; + cmd_erase.InstructionDTRMode = (dev_cfg->data_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_INSTRUCTION_DTR_ENABLE + : HAL_XSPI_INSTRUCTION_DTR_DISABLE; + cmd_erase.InstructionWidth = (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_INSTRUCTION_16_BITS + : HAL_XSPI_INSTRUCTION_8_BITS; + + while ((size > 0) && (ret == 0)) { + + ret = stm32_xspi_write_enable(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("Erase failed : write enable"); + break; + } + + if (size == dev_cfg->flash_size) { + /* Chip erase */ + LOG_DBG("Chip Erase"); + + cmd_erase.Address = 0; + cmd_erase.Instruction = (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? SPI_NOR_OCMD_BULKE + : SPI_NOR_CMD_BULKE; + cmd_erase.AddressMode = HAL_XSPI_ADDRESS_NONE; + /* Full chip erase (Bulk) command */ + xspi_send_cmd(dev, &cmd_erase); + + size -= dev_cfg->flash_size; + /* Chip (Bulk) erase started, wait until WEL becomes 0 */ + ret = stm32_xspi_mem_erased(dev); + if (ret != 0) { + LOG_ERR("Chip Erase failed"); + break; + } + } else { + /* Sector or Block erase depending on the size */ + LOG_DBG("Sector/Block Erase"); + + cmd_erase.AddressMode = + (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_ADDRESS_8_LINES + : HAL_XSPI_ADDRESS_1_LINE; + cmd_erase.AddressDTRMode = + (dev_cfg->data_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_ADDRESS_DTR_ENABLE + : HAL_XSPI_ADDRESS_DTR_DISABLE; + cmd_erase.AddressWidth = stm32_xspi_hal_address_size(dev); + cmd_erase.Address = addr; + + const struct jesd216_erase_type *erase_types = + dev_data->erase_types; + const struct jesd216_erase_type *bet = NULL; + + for (uint8_t ei = 0; + ei < JESD216_NUM_ERASE_TYPES; ++ei) { + const struct jesd216_erase_type *etp = + &erase_types[ei]; + + if ((etp->exp != 0) + && SPI_NOR_IS_ALIGNED(addr, etp->exp) + && (size >= BIT(etp->exp)) + && ((bet == NULL) + || (etp->exp > bet->exp))) { + bet = etp; + cmd_erase.Instruction = bet->cmd; + } else if (bet == NULL) { + /* Use the default sector erase cmd */ + if (dev_cfg->data_mode == XSPI_OCTO_MODE) { + cmd_erase.Instruction = SPI_NOR_OCMD_SE; + } else { + cmd_erase.Instruction = + (stm32_xspi_hal_address_size(dev) == + HAL_XSPI_ADDRESS_32_BITS) + ? SPI_NOR_CMD_SE_4B + : SPI_NOR_CMD_SE; + } + } + /* Avoid using wrong erase type, + * if zero entries are found in erase_types + */ + bet = NULL; + } + LOG_DBG("Sector/Block Erase addr 0x%x, asize 0x%x amode 0x%x instr 0x%x", + cmd_erase.Address, cmd_erase.AddressWidth, + cmd_erase.AddressMode, cmd_erase.Instruction); + + xspi_send_cmd(dev, &cmd_erase); + + if (bet != NULL) { + addr += BIT(bet->exp); + size -= BIT(bet->exp); + } else { + addr += SPI_NOR_SECTOR_SIZE; + size -= SPI_NOR_SECTOR_SIZE; + } + + ret = stm32_xspi_mem_ready(dev, dev_cfg->data_mode, + dev_cfg->data_rate); + } + + } + + xspi_unlock_thread(dev); + + return ret; +} + +/* Function to read the flash with possible OCTO/SPI and STR/DTR */ +static int flash_stm32_xspi_read(const struct device *dev, off_t addr, + void *data, size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + int ret; + + if (!xspi_address_is_valid(dev, addr, size)) { + LOG_ERR("Error: address or size exceeds expected values: " + "addr 0x%lx, size %zu", (long)addr, size); + return -EINVAL; + } + + /* Ignore zero size read */ + if (size == 0) { + return 0; + } + + XSPI_RegularCmdTypeDef cmd = xspi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); + + if (dev_cfg->data_mode != XSPI_OCTO_MODE) { + switch (dev_data->read_mode) { + case JESD216_MODE_112: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd.DataMode = HAL_XSPI_DATA_2_LINES; + break; + } + case JESD216_MODE_122: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_2_LINES; + cmd.DataMode = HAL_XSPI_DATA_2_LINES; + break; + } + case JESD216_MODE_114: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + case JESD216_MODE_144: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_4_LINES; + cmd.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + default: + /* use the mode from ospi_prepare_cmd */ + break; + } + } + + /* Instruction and DummyCycles are set below */ + cmd.Address = addr; /* AddressSize is 32bits in OPSI mode */ + cmd.AddressWidth = stm32_xspi_hal_address_size(dev); + /* DataSize is set by the read cmd */ + + /* Configure other parameters */ + if (dev_cfg->data_rate == XSPI_DTR_TRANSFER) { + /* DTR transfer rate (==> Octal mode) */ + cmd.Instruction = SPI_NOR_OCMD_DTR_RD; + cmd.DummyCycles = SPI_NOR_DUMMY_RD_OCTAL_DTR; + } else { + /* STR transfer rate */ + if (dev_cfg->data_mode == XSPI_OCTO_MODE) { + /* OPI and STR */ + cmd.Instruction = SPI_NOR_OCMD_RD; + cmd.DummyCycles = SPI_NOR_DUMMY_RD_OCTAL; + } else { + /* use SFDP:BFP read instruction */ + cmd.Instruction = dev_data->read_opcode; + cmd.DummyCycles = dev_data->read_dummy; + /* in SPI and STR : expecting SPI_NOR_CMD_READ_FAST_4B */ + } + } + + LOG_DBG("XSPI: read %zu data", size); + xspi_lock_thread(dev); + + ret = xspi_read_access(dev, &cmd, data, size); + + xspi_unlock_thread(dev); + + return ret; +} + +/* Function to write the flash (page program) : with possible OCTO/SPI and STR/DTR */ +static int flash_stm32_xspi_write(const struct device *dev, off_t addr, + const void *data, size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + size_t to_write; + int ret = 0; + + if (!xspi_address_is_valid(dev, addr, size)) { + LOG_ERR("Error: address or size exceeds expected values: " + "addr 0x%lx, size %zu", (long)addr, size); + return -EINVAL; + } + + /* Ignore zero size write */ + if (size == 0) { + return 0; + } + + /* page program for STR or DTR mode */ + XSPI_RegularCmdTypeDef cmd_pp = xspi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); + + /* using 32bits address also in SPI/STR mode */ + cmd_pp.Instruction = dev_data->write_opcode; + + if (dev_cfg->data_mode != XSPI_OCTO_MODE) { + switch (cmd_pp.Instruction) { + case SPI_NOR_CMD_PP_4B: + __fallthrough; + case SPI_NOR_CMD_PP: { + cmd_pp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_pp.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd_pp.DataMode = HAL_XSPI_DATA_1_LINE; + break; + } + case SPI_NOR_CMD_PP_1_1_4_4B: + __fallthrough; + case SPI_NOR_CMD_PP_1_1_4: { + cmd_pp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_pp.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd_pp.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + case SPI_NOR_CMD_PP_1_4_4_4B: + __fallthrough; + case SPI_NOR_CMD_PP_1_4_4: { + cmd_pp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_pp.AddressMode = HAL_XSPI_ADDRESS_4_LINES; + cmd_pp.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + default: + /* use the mode from ospi_prepare_cmd */ + break; + } + } + + cmd_pp.Address = addr; + cmd_pp.AddressWidth = stm32_xspi_hal_address_size(dev); + cmd_pp.DummyCycles = 0U; + + LOG_DBG("XSPI: write %zu data", size); + xspi_lock_thread(dev); + + ret = stm32_xspi_mem_ready(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + xspi_unlock_thread(dev); + LOG_ERR("XSPI: write not ready"); + return -EIO; + } + + while ((size > 0) && (ret == 0)) { + to_write = size; + ret = stm32_xspi_write_enable(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("XSPI: write not enabled"); + break; + } + /* Don't write more than a page. */ + if (to_write >= SPI_NOR_PAGE_SIZE) { + to_write = SPI_NOR_PAGE_SIZE; + } + + /* Don't write across a page boundary */ + if (((addr + to_write - 1U) / SPI_NOR_PAGE_SIZE) + != (addr / SPI_NOR_PAGE_SIZE)) { + to_write = SPI_NOR_PAGE_SIZE - + (addr % SPI_NOR_PAGE_SIZE); + } + cmd_pp.Address = addr; + + ret = xspi_write_access(dev, &cmd_pp, data, to_write); + if (ret != 0) { + LOG_ERR("XSPI: write not access"); + break; + } + + size -= to_write; + data = (const uint8_t *)data + to_write; + addr += to_write; + + /* Configure automatic polling mode to wait for end of program */ + ret = stm32_xspi_mem_ready(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("XSPI: write PP not ready"); + break; + } + } + + xspi_unlock_thread(dev); + + return ret; +} + +static const struct flash_parameters flash_stm32_xspi_parameters = { + .write_block_size = 1, + .erase_value = 0xff +}; + +static const struct flash_parameters * +flash_stm32_xspi_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &flash_stm32_xspi_parameters; +} + +static void flash_stm32_xspi_isr(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + HAL_XSPI_IRQHandler(&dev_data->hxspi); +} + +#if !defined(CONFIG_SOC_SERIES_STM32H7X) +/* weak function required for HAL compilation */ +__weak HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) +{ + return HAL_OK; +} + +/* weak function required for HAL compilation */ +__weak HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) +{ + return HAL_OK; +} +#endif /* !CONFIG_SOC_SERIES_STM32H7X */ + +/* + * Transfer Error callback. + */ +void HAL_XSPI_ErrorCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Error cb"); + + dev_data->cmd_status = -EIO; + + k_sem_give(&dev_data->sync); +} + +/* + * Command completed callback. + */ +void HAL_XSPI_CmdCpltCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Cmd Cplt cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Rx Transfer completed callback. + */ +void HAL_XSPI_RxCpltCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Rx Cplt cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Tx Transfer completed callback. + */ +void HAL_XSPI_TxCpltCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Tx Cplt cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Status Match callback. + */ +void HAL_XSPI_StatusMatchCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Status Match cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Timeout callback. + */ +void HAL_XSPI_TimeOutCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Timeout cb"); + + dev_data->cmd_status = -EIO; + + k_sem_give(&dev_data->sync); +} + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static void flash_stm32_xspi_pages_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + *layout = &dev_data->layout; + *layout_size = 1; +} +#endif + +static const struct flash_driver_api flash_stm32_xspi_driver_api = { + .read = flash_stm32_xspi_read, + .write = flash_stm32_xspi_write, + .erase = flash_stm32_xspi_erase, + .get_parameters = flash_stm32_xspi_get_parameters, +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + .page_layout = flash_stm32_xspi_pages_layout, +#endif +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = xspi_read_sfdp, + .read_jedec_id = xspi_read_jedec_id, +#endif /* CONFIG_FLASH_JESD216_API */ +}; + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static int setup_pages_layout(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *data = dev->data; + const size_t flash_size = dev_cfg->flash_size; + uint32_t layout_page_size = data->page_size; + uint8_t value = 0; + int rv = 0; + + /* Find the smallest erase size. */ + for (size_t i = 0; i < ARRAY_SIZE(data->erase_types); ++i) { + const struct jesd216_erase_type *etp = &data->erase_types[i]; + + if ((etp->cmd != 0) + && ((value == 0) || (etp->exp < value))) { + value = etp->exp; + } + } + + uint32_t erase_size = BIT(value); + + if (erase_size == 0) { + erase_size = SPI_NOR_SECTOR_SIZE; + } + + /* We need layout page size to be compatible with erase size */ + if ((layout_page_size % erase_size) != 0) { + LOG_DBG("layout page %u not compatible with erase size %u", + layout_page_size, erase_size); + LOG_DBG("erase size will be used as layout page size"); + layout_page_size = erase_size; + } + + /* Warn but accept layout page sizes that leave inaccessible + * space. + */ + if ((flash_size % layout_page_size) != 0) { + LOG_DBG("layout page %u wastes space with device size %zu", + layout_page_size, flash_size); + } + + data->layout.pages_size = layout_page_size; + data->layout.pages_count = flash_size / layout_page_size; + LOG_DBG("layout %u x %u By pages", data->layout.pages_count, + data->layout.pages_size); + + return rv; +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +static int stm32_xspi_read_status_register(const struct device *dev, uint8_t reg_num, uint8_t *reg) +{ + XSPI_RegularCmdTypeDef s_command = { + .InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE, + .DataMode = HAL_XSPI_DATA_1_LINE, + }; + + switch (reg_num) { + case 1U: + s_command.Instruction = SPI_NOR_CMD_RDSR; + break; + case 2U: + s_command.Instruction = SPI_NOR_CMD_RDSR2; + break; + case 3U: + s_command.Instruction = SPI_NOR_CMD_RDSR3; + break; + default: + return -EINVAL; + } + + return xspi_read_access(dev, &s_command, reg, sizeof(*reg)); +} + +static int stm32_xspi_write_status_register(const struct device *dev, uint8_t reg_num, uint8_t reg) +{ + struct flash_stm32_xspi_data *data = dev->data; + XSPI_RegularCmdTypeDef s_command = { + .Instruction = SPI_NOR_CMD_WRSR, + .InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE, + .DataMode = HAL_XSPI_DATA_1_LINE + }; + size_t size; + uint8_t regs[4] = { 0 }; + uint8_t *regs_p; + int ret; + + if (reg_num == 1U) { + size = 1U; + regs[0] = reg; + regs_p = ®s[0]; + /* 1 byte write clears SR2, write SR2 as well */ + if (data->qer_type == JESD216_DW15_QER_S2B1v1) { + ret = stm32_xspi_read_status_register(dev, 2, ®s[1]); + if (ret < 0) { + return ret; + } + size = 2U; + } + } else if (reg_num == 2U) { + s_command.Instruction = SPI_NOR_CMD_WRSR2; + size = 1U; + regs[1] = reg; + regs_p = ®s[1]; + /* if SR2 write needs SR1 */ + if ((data->qer_type == JESD216_DW15_QER_VAL_S2B1v1) || + (data->qer_type == JESD216_DW15_QER_VAL_S2B1v4) || + (data->qer_type == JESD216_DW15_QER_VAL_S2B1v5)) { + ret = stm32_xspi_read_status_register(dev, 1, ®s[0]); + if (ret < 0) { + return ret; + } + s_command.Instruction = SPI_NOR_CMD_WRSR; + size = 2U; + regs_p = ®s[0]; + } + } else if (reg_num == 3U) { + s_command.Instruction = SPI_NOR_CMD_WRSR3; + size = 1U; + regs[2] = reg; + regs_p = ®s[2]; + } else { + return -EINVAL; + } + + return xspi_write_access(dev, &s_command, regs_p, size); +} + +static int stm32_xspi_enable_qe(const struct device *dev) +{ + struct flash_stm32_xspi_data *data = dev->data; + uint8_t qe_reg_num; + uint8_t qe_bit; + uint8_t reg; + int ret; + + switch (data->qer_type) { + case JESD216_DW15_QER_NONE: + /* no QE bit, device detects reads based on opcode */ + return 0; + case JESD216_DW15_QER_S1B6: + qe_reg_num = 1U; + qe_bit = BIT(6U); + break; + case JESD216_DW15_QER_S2B7: + qe_reg_num = 2U; + qe_bit = BIT(7U); + break; + case JESD216_DW15_QER_S2B1v1: + __fallthrough; + case JESD216_DW15_QER_S2B1v4: + __fallthrough; + case JESD216_DW15_QER_S2B1v5: + __fallthrough; + case JESD216_DW15_QER_S2B1v6: + qe_reg_num = 2U; + qe_bit = BIT(1U); + break; + default: + return -ENOTSUP; + } + + ret = stm32_xspi_read_status_register(dev, qe_reg_num, ®); + if (ret < 0) { + return ret; + } + + /* exit early if QE bit is already set */ + if ((reg & qe_bit) != 0U) { + return 0; + } + + ret = stm32_xspi_write_enable(dev, XSPI_SPI_MODE, XSPI_STR_TRANSFER); + if (ret < 0) { + return ret; + } + + reg |= qe_bit; + + ret = stm32_xspi_write_status_register(dev, qe_reg_num, reg); + if (ret < 0) { + return ret; + } + + ret = stm32_xspi_mem_ready(dev, XSPI_SPI_MODE, XSPI_STR_TRANSFER); + if (ret < 0) { + return ret; + } + + /* validate that QE bit is set */ + ret = stm32_xspi_read_status_register(dev, qe_reg_num, ®); + if (ret < 0) { + return ret; + } + + if ((reg & qe_bit) == 0U) { + LOG_ERR("Status Register %u [0x%02x] not set", qe_reg_num, reg); + ret = -EIO; + } + + return ret; +} + +static void spi_nor_process_bfp_addrbytes(const struct device *dev, + const uint8_t jesd216_bfp_addrbytes) +{ + struct flash_stm32_xspi_data *data = dev->data; + + if ((jesd216_bfp_addrbytes == JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_4B) || + (jesd216_bfp_addrbytes == JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_3B4B)) { + data->address_width = 4U; + } else { + data->address_width = 3U; + } +} + +static inline uint8_t spi_nor_convert_read_to_4b(const uint8_t opcode) +{ + switch (opcode) { + case SPI_NOR_CMD_READ: + return SPI_NOR_CMD_READ_4B; + case SPI_NOR_CMD_DREAD: + return SPI_NOR_CMD_DREAD_4B; + case SPI_NOR_CMD_2READ: + return SPI_NOR_CMD_2READ_4B; + case SPI_NOR_CMD_QREAD: + return SPI_NOR_CMD_QREAD_4B; + case SPI_NOR_CMD_4READ: + return SPI_NOR_CMD_4READ_4B; + default: + /* use provided */ + return opcode; + } +} + +static inline uint8_t spi_nor_convert_write_to_4b(const uint8_t opcode) +{ + switch (opcode) { + case SPI_NOR_CMD_PP: + return SPI_NOR_CMD_PP_4B; + case SPI_NOR_CMD_PP_1_1_4: + return SPI_NOR_CMD_PP_1_1_4_4B; + case SPI_NOR_CMD_PP_1_4_4: + return SPI_NOR_CMD_PP_1_4_4_4B; + default: + /* use provided */ + return opcode; + } +} + +static int spi_nor_process_bfp(const struct device *dev, + const struct jesd216_param_header *php, + const struct jesd216_bfp *bfp) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *data = dev->data; + /* must be kept in data mode order, ignore 1-1-1 (always supported) */ + const enum jesd216_mode_type supported_read_modes[] = { JESD216_MODE_112, JESD216_MODE_122, + JESD216_MODE_114, + JESD216_MODE_144 }; + size_t supported_read_modes_max_idx; + struct jesd216_erase_type *etp = data->erase_types; + size_t idx; + const size_t flash_size = jesd216_bfp_density(bfp) / 8U; + struct jesd216_instr read_instr = { 0 }; + struct jesd216_bfp_dw15 dw15; + + if (flash_size != dev_cfg->flash_size) { + LOG_DBG("Unexpected flash size: %u", flash_size); + } + + LOG_DBG("%s: %u MiBy flash", dev->name, (uint32_t)(flash_size >> 20)); + + /* Copy over the erase types, preserving their order. (The + * Sector Map Parameter table references them by index.) + */ + memset(data->erase_types, 0, sizeof(data->erase_types)); + for (idx = 1U; idx <= ARRAY_SIZE(data->erase_types); ++idx) { + if (jesd216_bfp_erase(bfp, idx, etp) == 0) { + LOG_DBG("Erase %u with %02x", + (uint32_t)BIT(etp->exp), etp->cmd); + } + ++etp; + } + + spi_nor_process_bfp_addrbytes(dev, jesd216_bfp_addrbytes(bfp)); + LOG_DBG("Address width: %u Bytes", data->address_width); + + /* use PP opcode based on configured data mode if nothing is set in DTS */ + if (data->write_opcode == SPI_NOR_WRITEOC_NONE) { + switch (dev_cfg->data_mode) { + case XSPI_OCTO_MODE: + data->write_opcode = SPI_NOR_OCMD_PAGE_PRG; + break; + case XSPI_QUAD_MODE: + data->write_opcode = SPI_NOR_CMD_PP_1_4_4; + break; + case XSPI_DUAL_MODE: + data->write_opcode = SPI_NOR_CMD_PP_1_1_2; + break; + default: + data->write_opcode = SPI_NOR_CMD_PP; + break; + } + } + + if (dev_cfg->data_mode != XSPI_OCTO_MODE) { + /* determine supported read modes, begin from the slowest */ + data->read_mode = JESD216_MODE_111; + data->read_opcode = SPI_NOR_CMD_READ; + data->read_dummy = 0U; + + if (dev_cfg->data_mode != XSPI_SPI_MODE) { + if (dev_cfg->data_mode == XSPI_DUAL_MODE) { + /* the index of JESD216_MODE_114 in supported_read_modes */ + supported_read_modes_max_idx = 2U; + } else { + supported_read_modes_max_idx = ARRAY_SIZE(supported_read_modes); + } + + for (idx = 0U; idx < supported_read_modes_max_idx; ++idx) { + if (jesd216_bfp_read_support(php, bfp, supported_read_modes[idx], + &read_instr) < 0) { + /* not supported */ + continue; + } + + LOG_DBG("Supports read mode: %d, instr: 0x%X", + supported_read_modes[idx], read_instr.instr); + data->read_mode = supported_read_modes[idx]; + data->read_opcode = read_instr.instr; + data->read_dummy = + (read_instr.wait_states + read_instr.mode_clocks); + } + } + + /* convert 3-Byte opcodes to 4-Byte (if required) */ + if (IS_ENABLED(DT_INST_PROP(0, four_byte_opcodes))) { + if (data->address_width != 4U) { + LOG_DBG("4-Byte opcodes require 4-Byte address width"); + return -ENOTSUP; + } + data->read_opcode = spi_nor_convert_read_to_4b(data->read_opcode); + data->write_opcode = spi_nor_convert_write_to_4b(data->write_opcode); + } + + /* enable quad mode (if required) */ + if (dev_cfg->data_mode == XSPI_QUAD_MODE) { + if (jesd216_bfp_decode_dw15(php, bfp, &dw15) < 0) { + /* will use QER from DTS or default (refer to device data) */ + LOG_WRN("Unable to decode QE requirement [DW15]"); + } else { + /* bypass DTS QER value */ + data->qer_type = dw15.qer; + } + + LOG_DBG("QE requirement mode: %x", data->qer_type); + + if (stm32_xspi_enable_qe(dev) < 0) { + LOG_ERR("Failed to enable QUAD mode"); + return -EIO; + } + + LOG_DBG("QUAD mode enabled"); + } + } + + data->page_size = jesd216_bfp_page_size(php, bfp); + + LOG_DBG("Page size %u bytes", data->page_size); + LOG_DBG("Flash size %zu bytes", flash_size); + LOG_DBG("Using read mode: %d, instr: 0x%X, dummy cycles: %u", + data->read_mode, data->read_opcode, data->read_dummy); + LOG_DBG("Using write instr: 0x%X", data->write_opcode); + + return 0; +} + +static int flash_stm32_xspi_init(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + uint32_t ahb_clock_freq; + uint32_t prescaler = STM32_XSPI_CLOCK_PRESCALER_MIN; + int ret; + + /* The SPI/DTR is not a valid config of data_mode/data_rate according to the DTS */ + if ((dev_cfg->data_mode != XSPI_OCTO_MODE) + && (dev_cfg->data_rate == XSPI_DTR_TRANSFER)) { + /* already the right config, continue */ + LOG_ERR("XSPI mode SPI|DUAL|QUAD/DTR is not valid"); + return -ENOTSUP; + } + + /* Signals configuration */ + ret = pinctrl_apply_state(dev_cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("XSPI pinctrl setup failed (%d)", ret); + return ret; + } + + if (!device_is_ready(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE))) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + /* Clock configuration */ + if (clock_control_on(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken) != 0) { + LOG_ERR("Could not enable XSPI clock"); + return -EIO; + } + /* Alternate clock config for peripheral if any */ +#if DT_CLOCKS_HAS_NAME(STM32_XSPI_NODE, xspi_ker) + if (clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken_ker, + NULL) != 0) { + LOG_ERR("Could not select XSPI domain clock"); + return -EIO; + } + if (clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken_ker, + &ahb_clock_freq) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken_ker)"); + return -EIO; + } +#else + if (clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken, + &ahb_clock_freq) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken)"); + return -EIO; + } +#endif +#if DT_CLOCKS_HAS_NAME(STM32_XSPI_NODE, xspi_mgr) + if (clock_control_on(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken_mgr) != 0) { + LOG_ERR("Could not enable XSPI Manager clock"); + return -EIO; + } +#endif + + for (; prescaler <= STM32_XSPI_CLOCK_PRESCALER_MAX; prescaler++) { + uint32_t clk = STM32_XSPI_CLOCK_COMPUTE(ahb_clock_freq, prescaler); + + if (clk <= dev_cfg->max_frequency) { + break; + } + } + __ASSERT_NO_MSG(prescaler >= STM32_XSPI_CLOCK_PRESCALER_MIN && + prescaler <= STM32_XSPI_CLOCK_PRESCALER_MAX); + + /* Initialize XSPI HAL structure completely */ + dev_data->hxspi.Init.ClockPrescaler = prescaler; + /* The stm32 hal_xspi driver does not reduce DEVSIZE before writing the DCR1 */ + dev_data->hxspi.Init.MemorySize = find_lsb_set(dev_cfg->flash_size) - 2; +#if defined(XSPI_DCR2_WRAPSIZE) + dev_data->hxspi.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED; +#endif /* XSPI_DCR2_WRAPSIZE */ + /* STR mode else Macronix for DTR mode */ + if (dev_cfg->data_rate == XSPI_DTR_TRANSFER) { + dev_data->hxspi.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX; + dev_data->hxspi.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE; + } else { + + } +#if STM32_XSPI_DLYB_BYPASSED + dev_data->hxspi.Init.DelayBlockBypass = HAL_XSPI_DELAY_BLOCK_BYPASS; +#else + dev_data->hxspi.Init.DelayBlockBypass = HAL_XSPI_DELAY_BLOCK_ON; +#endif /* STM32_XSPI_DLYB_BYPASSED */ + + + if (HAL_XSPI_Init(&dev_data->hxspi) != HAL_OK) { + LOG_ERR("XSPI Init failed"); + return -EIO; + } + + LOG_DBG("XSPI Init'd"); + +#if defined(HAL_XSPIM_IOPORT_1) || defined(HAL_XSPIM_IOPORT_2) + /* XSPI I/O manager init Function */ + XSPIM_CfgTypeDef xspi_mgr_cfg; + + if (dev_data->hxspi.Instance == XSPI1) { + xspi_mgr_cfg.IOPort = HAL_XSPIM_IOPORT_1; + xspi_mgr_cfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1; + } else if (dev_data->hxspi.Instance == XSPI2) { + ospi_mgr_cfg.IOPort = HAL_XSPIM_IOPORT_2; + ospi_mgr_cfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS2; + } + ospi_mgr_cfg.Req2AckTime = 1; + + if (HAL_XSPIM_Config(&dev_data->hxspi, &xspi_mgr_cfg, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI M config failed"); + return -EIO; + } + +#endif /* XSPIM */ + +#if defined(DLYB_XSPI1) || defined(DLYB_XSPI2) || defined(DLYB_OCTOSPI1) || defined(DLYB_OCTOSPI2) + /* XSPI delay block init Function */ + HAL_XSPI_DLYB_CfgTypeDef xspi_delay_block_cfg = {0}; + + (void)HAL_XSPI_DLYB_GetClockPeriod(&dev_data->hxspi, &xspi_delay_block_cfg); + /* with DTR, set the PhaseSel/4 (empiric value from stm32Cube) */ + xspi_delay_block_cfg.PhaseSel /= 4; + + if (HAL_XSPI_DLYB_SetConfig(&dev_data->hxspi, &xspi_delay_block_cfg) != HAL_OK) { + LOG_ERR("XSPI DelayBlock failed"); + return -EIO; + } + + LOG_DBG("Delay Block Init"); + +#endif /* DLYB_ */ + + /* Initialize semaphores */ + k_sem_init(&dev_data->sem, 1, 1); + k_sem_init(&dev_data->sync, 0, 1); + + /* Run IRQ init */ + dev_cfg->irq_config(dev); + + /* Reset NOR flash memory : still with the SPI/STR config for the NOR */ + if (stm32_xspi_mem_reset(dev) != 0) { + LOG_ERR("XSPI reset failed"); + return -EIO; + } + + LOG_DBG("Reset Mem (SPI/STR)"); + + /* Check if memory is ready in the SPI/STR mode */ + if (stm32_xspi_mem_ready(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI memory not ready"); + return -EIO; + } + + LOG_DBG("Mem Ready (SPI/STR)"); + +#if defined(CONFIG_FLASH_JESD216_API) + /* Process with the RDID (jedec read ID) instruction at init and fill jedec_id Table */ + ret = stm32_xspi_read_jedec_id(dev); + if (ret != 0) { + LOG_ERR("Read ID failed: %d", ret); + return ret; + } +#endif /* CONFIG_FLASH_JESD216_API */ + + if (stm32_xspi_config_mem(dev) != 0) { + LOG_ERR("OSPI mode not config'd (%u rate %u)", + dev_cfg->data_mode, dev_cfg->data_rate); + return -EIO; + } + + /* Send the instruction to read the SFDP */ + const uint8_t decl_nph = 2; + union { + /* We only process BFP so use one parameter block */ + uint8_t raw[JESD216_SFDP_SIZE(decl_nph)]; + struct jesd216_sfdp_header sfdp; + } u; + const struct jesd216_sfdp_header *hp = &u.sfdp; + + ret = xspi_read_sfdp(dev, 0, u.raw, sizeof(u.raw)); + if (ret != 0) { + LOG_ERR("SFDP read failed: %d", ret); + return ret; + } + + uint32_t magic = jesd216_sfdp_magic(hp); + + if (magic != JESD216_SFDP_MAGIC) { + LOG_ERR("SFDP magic %08x invalid", magic); + return -EINVAL; + } + + LOG_DBG("%s: SFDP v %u.%u AP %x with %u PH", dev->name, + hp->rev_major, hp->rev_minor, hp->access, 1 + hp->nph); + + const struct jesd216_param_header *php = hp->phdr; + const struct jesd216_param_header *phpe = php + + MIN(decl_nph, 1 + hp->nph); + + while (php != phpe) { + uint16_t id = jesd216_param_id(php); + + LOG_DBG("PH%u: %04x rev %u.%u: %u DW @ %x", + (php - hp->phdr), id, php->rev_major, php->rev_minor, + php->len_dw, jesd216_param_addr(php)); + + if (id == JESD216_SFDP_PARAM_ID_BFP) { + union { + uint32_t dw[20]; + struct jesd216_bfp bfp; + } u2; + const struct jesd216_bfp *bfp = &u2.bfp; + + ret = xspi_read_sfdp(dev, jesd216_param_addr(php), + (uint8_t *)u2.dw, + MIN(sizeof(uint32_t) * php->len_dw, sizeof(u2.dw))); + if (ret == 0) { + ret = spi_nor_process_bfp(dev, php, bfp); + } + + if (ret != 0) { + LOG_ERR("SFDP BFP failed: %d", ret); + break; + } + } + if (id == JESD216_SFDP_PARAM_ID_4B_ADDR_INSTR) { + + if (dev_data->address_width == 4U) { + /* + * Check table 4 byte address instruction table to get supported + * erase opcodes when running in 4 byte address mode + */ + union { + uint32_t dw[2]; + struct { + uint32_t dummy; + uint8_t type[4]; + } types; + } u2; + ret = xspi_read_sfdp(dev, jesd216_param_addr(php), + (uint8_t *)u2.dw, + MIN(sizeof(uint32_t) * php->len_dw, sizeof(u2.dw))); + if (ret != 0) { + break; + } + for (uint8_t ei = 0; ei < JESD216_NUM_ERASE_TYPES; ++ei) { + struct jesd216_erase_type *etp = &dev_data->erase_types[ei]; + const uint8_t cmd = u2.types.type[ei]; + /* 0xff means not supported */ + if (cmd == 0xff) { + etp->exp = 0; + etp->cmd = 0; + } else { + etp->cmd = cmd; + }; + } + } + } + ++php; + } + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + ret = setup_pages_layout(dev); + if (ret != 0) { + LOG_ERR("layout setup failed: %d", ret); + return -ENODEV; + } +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + + LOG_INF("NOR external-flash at 0x%lx (0x%x bytes)", + (long)(STM32_XSPI_BASE_ADDRESS), + dev_cfg->flash_size); + + return 0; +} + +#define XSPI_FLASH_MODULE(drv_id, flash_id) \ + (DT_DRV_INST(drv_id), xspi_nor_flash_##flash_id) + +#define DT_WRITEOC_PROP_OR(inst, default_value) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, writeoc), \ + (_CONCAT(SPI_NOR_CMD_, DT_STRING_TOKEN(DT_DRV_INST(inst), writeoc))), \ + ((default_value))) + +#define DT_QER_PROP_OR(inst, default_value) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, quad_enable_requirements), \ + (_CONCAT(JESD216_DW15_QER_VAL_, \ + DT_STRING_TOKEN(DT_DRV_INST(inst), quad_enable_requirements))), \ + ((default_value))) + +static void flash_stm32_xspi_irq_config_func(const struct device *dev); + +PINCTRL_DT_DEFINE(STM32_XSPI_NODE); + +static const struct flash_stm32_xspi_config flash_stm32_xspi_cfg = { + .pclken = {.bus = DT_CLOCKS_CELL_BY_NAME(STM32_XSPI_NODE, xspix, bus), + .enr = DT_CLOCKS_CELL_BY_NAME(STM32_XSPI_NODE, xspix, bits)}, +#if DT_CLOCKS_HAS_NAME(STM32_XSPI_NODE, xspi_ker) + .pclken_ker = {.bus = DT_CLOCKS_CELL_BY_NAME(STM32_XSPI_NODE, xspi_ker, bus), + .enr = DT_CLOCKS_CELL_BY_NAME(STM32_XSPI_NODE, xspi_ker, bits)}, +#endif +#if DT_CLOCKS_HAS_NAME(STM32_XSPI_NODE, xspi_mgr) + .pclken_mgr = {.bus = DT_CLOCKS_CELL_BY_NAME(STM32_XSPI_NODE, xspi_mgr, bus), + .enr = DT_CLOCKS_CELL_BY_NAME(STM32_XSPI_NODE, xspi_mgr, bits)}, +#endif + .irq_config = flash_stm32_xspi_irq_config_func, + .flash_size = DT_INST_REG_ADDR_BY_IDX(0, 1), + .max_frequency = DT_INST_PROP(0, ospi_max_frequency), + .data_mode = DT_INST_PROP(0, spi_bus_width), /* SPI or OPI */ + .data_rate = DT_INST_PROP(0, data_rate), /* DTR or STR */ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(STM32_XSPI_NODE), +#if STM32_XSPI_RESET_GPIO + .reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios), +#endif /* STM32_XSPI_RESET_GPIO */ +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_ospi_nor), sfdp_bfp) + .sfdp_bfp = DT_INST_PROP(0, sfdp_bfp), +#endif /* sfdp_bfp */ +}; + +static struct flash_stm32_xspi_data flash_stm32_xspi_dev_data = { + .hxspi = { + .Instance = (XSPI_TypeDef *)DT_REG_ADDR(STM32_XSPI_NODE), + .Init = { + .FifoThresholdByte = STM32_XSPI_FIFO_THRESHOLD, + .SampleShifting = (DT_PROP(STM32_XSPI_NODE, ssht_enable) + ? HAL_XSPI_SAMPLE_SHIFT_HALFCYCLE + : HAL_XSPI_SAMPLE_SHIFT_NONE), + .ChipSelectHighTimeCycle = 1, + .ClockMode = HAL_XSPI_CLOCK_MODE_0, + .ChipSelectBoundary = 0, + .MemoryMode = HAL_XSPI_SINGLE_MEM, + .FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE, +#if defined(OCTOSPI_DCR4_REFRESH) + .Refresh = 0, +#endif /* OCTOSPI_DCR4_REFRESH */ + }, + }, + .qer_type = DT_QER_PROP_OR(0, JESD216_DW15_QER_VAL_S1B6), + .write_opcode = DT_WRITEOC_PROP_OR(0, SPI_NOR_WRITEOC_NONE), + .page_size = SPI_NOR_PAGE_SIZE, /* by default, to be updated by sfdp */ +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_ospi_nor), jedec_id) + .jedec_id = DT_INST_PROP(0, jedec_id), +#endif /* jedec_id */ +}; + +DEVICE_DT_INST_DEFINE(0, &flash_stm32_xspi_init, NULL, + &flash_stm32_xspi_dev_data, &flash_stm32_xspi_cfg, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &flash_stm32_xspi_driver_api); + +static void flash_stm32_xspi_irq_config_func(const struct device *dev) +{ + IRQ_CONNECT(DT_IRQN(STM32_XSPI_NODE), DT_IRQ(STM32_XSPI_NODE, priority), + flash_stm32_xspi_isr, DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_IRQN(STM32_XSPI_NODE)); +} diff --git a/drivers/flash/flash_stm32_xspi.h b/drivers/flash/flash_stm32_xspi.h new file mode 100644 index 00000000000000..d940cc93343b39 --- /dev/null +++ b/drivers/flash/flash_stm32_xspi.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_FLASH_XSPI_STM32_H_ +#define ZEPHYR_DRIVERS_FLASH_XSPI_STM32_H_ + +#define STM32_XSPI_FIFO_THRESHOLD 4U + +/* Valid range is [0, 255] */ +#define STM32_XSPI_CLOCK_PRESCALER_MIN 0U +#define STM32_XSPI_CLOCK_PRESCALER_MAX 255U +#define STM32_XSPI_CLOCK_COMPUTE(bus_freq, prescaler) ((bus_freq) / ((prescaler) + 1U)) + +/* Max Time value during reset or erase operation */ +#define STM32_XSPI_RESET_MAX_TIME 100U +#define STM32_XSPI_BULK_ERASE_MAX_TIME 460000U +#define STM32_XSPI_SECTOR_ERASE_MAX_TIME 1000U +#define STM32_XSPI_SUBSECTOR_4K_ERASE_MAX_TIME 400U +#define STM32_XSPI_WRITE_REG_MAX_TIME 40U + +/* used as default value for DTS writeoc */ +#define SPI_NOR_WRITEOC_NONE 0xFF + +typedef void (*irq_config_func_t)(const struct device *dev); + +struct flash_stm32_xspi_config { + const struct stm32_pclken pclken; /* clock subsystem */ + const struct stm32_pclken pclken_ker; /* clock subsystem */ + const struct stm32_pclken pclken_mgr; /* clock subsystem */ + irq_config_func_t irq_config; + size_t flash_size; + uint32_t max_frequency; + int data_mode; /* SPI or QSPI or OSPI */ + int data_rate; /* DTR or STR */ + const struct pinctrl_dev_config *pcfg; +#if STM32_XSPI_RESET_GPIO + const struct gpio_dt_spec reset; +#endif /* STM32_XSPI_RESET_GPIO */ +}; + +struct flash_stm32_xspi_data { + /* XSPI handle is modifiable ; so part of data struct */ + XSPI_HandleTypeDef hxspi; + struct k_sem sem; + struct k_sem sync; +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + struct flash_pages_layout layout; +#endif + struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES]; + /* Number of bytes per page */ + uint16_t page_size; + /* Address width in bytes */ + uint8_t address_width; + /* Read operation dummy cycles */ + uint8_t read_dummy; + uint32_t read_opcode; + uint32_t write_opcode; + enum jesd216_mode_type read_mode; + enum jesd216_dw15_qer_type qer_type; +#if defined(CONFIG_FLASH_JESD216_API) + /* Table to hold the jedec Read ID given by the octoFlash const */ + uint8_t jedec_id[JESD216_READ_ID_LEN]; +#endif /* CONFIG_FLASH_JESD216_API */ + int cmd_status; +}; + +#endif /* ZEPHYR_DRIVERS_FLASH_XSPI_STM32_H_ */ From 0fbfee8be184d4aa037d049c31c9f5c814a1dd0a Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0703/1389] dts: arm: st: stm32h5 serie has xspi node Define the xspi node instead of ospi. Note that RCC CCIPR4 register keeps the OCTOSP1 for clock domain selection. Change the header file to xspi for the stm32 devices with xspi peripheral. Keep the flash_controller/ospi.h for bindings compatibilty. Signed-off-by: Francois Ramu --- dts/arm/st/h5/stm32h562.dtsi | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index a4acfcb8ee9c09..0a52c12fc0e55f 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -6,6 +6,8 @@ #include #include +/* keep both header files for compatibility */ +#include / { clocks { @@ -65,12 +67,12 @@ status = "disabled"; }; - lptim4: timers@44004C00 { + lptim4: timers@44004c00 { compatible = "st,stm32-lptim"; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x2000>; #address-cells = <1>; #size-cells = <0>; - reg = <0x44004C00 0x400>; + reg = <0x44004c00 0x400>; interrupts = <128 1>; interrupt-names = "wakeup"; status = "disabled"; @@ -224,11 +226,11 @@ status = "disabled"; }; - octospi1: octospi@47001400 { - compatible = "st,stm32-ospi"; + xspi1: xspi@47001400 { + compatible = "st,stm32-xspi"; reg = <0x47001400 0x400>; interrupts = <78 0>; - clock-names = "ospix", "ospi-ker"; + clock-names = "xspix", "xspi-ker"; clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00100000>, <&rcc STM32_SRC_PLL1_Q OCTOSPI1_SEL(1)>; #address-cells = <1>; From 922e1e36eff6e0709c941340de06456ea5ebd806 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0704/1389] boards: st: stm32h573 disco boards with xspi instance peripheral Use the xspi.h header file to configure the xspi node of the stm32 disco kit Signed-off-by: Francois Ramu --- boards/st/stm32h573i_dk/stm32h573i_dk.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.dts b/boards/st/stm32h573i_dk/stm32h573i_dk.dts index e27445c2ac3bf7..05f13c64f4602f 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.dts +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.dts @@ -252,7 +252,7 @@ status = "okay"; }; -&octospi1 { +&xspi1 { pinctrl-0 = <&octospi1_io0_pb1 &octospi1_io1_pd12 &octospi1_io2_pc2 &octospi1_io3_pd13 &octospi1_io4_ph2 &octospi1_io5_ph3 @@ -264,11 +264,11 @@ status = "okay"; mx25lm51245: ospi-nor-flash@90000000 { - compatible = "st,stm32-ospi-nor"; + compatible = "st,stm32-xspi-nor"; reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ ospi-max-frequency = ; - spi-bus-width = ; - data-rate = ; + spi-bus-width = ; + data-rate = ; four-byte-opcodes; status = "okay"; From 2ba8869047e12e758e0a28d4f61191979afc1624 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0705/1389] samples: drivers: include the stm32 xspi node for running the samples The stm32 xspi node is another possible multi-spi for connecting external NOR flash memories. Signed-off-by: Francois Ramu --- samples/drivers/jesd216/sample.yaml | 4 +++- samples/drivers/jesd216/src/main.c | 2 ++ samples/drivers/spi_flash/sample.yaml | 2 +- samples/drivers/spi_flash/src/main.c | 4 +++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/samples/drivers/jesd216/sample.yaml b/samples/drivers/jesd216/sample.yaml index 4ab18259153c73..c2742a68d46442 100644 --- a/samples/drivers/jesd216/sample.yaml +++ b/samples/drivers/jesd216/sample.yaml @@ -29,5 +29,7 @@ tests: integration_platforms: - nrf52840dk/nrf52840 sample.drivers.stm32.jesd216: - filter: dt_compat_enabled("st,stm32-ospi-nor") or dt_compat_enabled("st,stm32-qspi-nor") + filter: dt_compat_enabled("st,stm32-xspi-nor") + or dt_compat_enabled("st,stm32-ospi-nor") + or dt_compat_enabled("st,stm32-qspi-nor") depends_on: spi diff --git a/samples/drivers/jesd216/src/main.c b/samples/drivers/jesd216/src/main.c index 92dd10208dd244..7450df86ed2776 100644 --- a/samples/drivers/jesd216/src/main.c +++ b/samples/drivers/jesd216/src/main.c @@ -20,6 +20,8 @@ #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_qspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor) #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_ospi_nor) +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor) +#define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_xspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_qspi_nor) #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_qspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_imx_flexspi_nor) diff --git a/samples/drivers/spi_flash/sample.yaml b/samples/drivers/spi_flash/sample.yaml index b3bec006e9cb0c..b7c7a069243863 100644 --- a/samples/drivers/spi_flash/sample.yaml +++ b/samples/drivers/spi_flash/sample.yaml @@ -6,7 +6,7 @@ tests: - spi - flash filter: dt_compat_enabled("jedec,spi-nor") or dt_compat_enabled("st,stm32-qspi-nor") - or dt_compat_enabled("st,stm32-ospi-nor") + or dt_compat_enabled("st,stm32-ospi-nor") or dt_compat_enabled("st,stm32-xspi-nor") or (dt_compat_enabled("nordic,qspi-nor") and CONFIG_NORDIC_QSPI_NOR) platform_exclude: hifive_unmatched harness: console diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index 2faadd309c6e8b..e456b511030903 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -26,7 +26,9 @@ #endif #define SPI_FLASH_SECTOR_SIZE 4096 -#if defined(CONFIG_FLASH_STM32_OSPI) || defined(CONFIG_FLASH_STM32_QSPI) +#if defined(CONFIG_FLASH_STM32_OSPI) || \ + defined(CONFIG_FLASH_STM32_QSPI) || \ + defined(CONFIG_FLASH_STM32_XSPI) #define SPI_FLASH_MULTI_SECTOR_TEST #endif From 04abb1795ca9361c12509e36d02cf699c29f3eb1 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0706/1389] boards: st: stm32h745i_disco: fix CAN phy devicetree representation On this board, the CAN transceivers are not GPIO controlled, but passive, and should not be represented by the "can-transceiver-gpio" compatible (as this leads to driver compilation warnings due to missing GPIO properties). Fixes: c8faa1e3809854e83bc7abe9d33737a5047d9125 Signed-off-by: Henrik Brix Andersen --- .../stm32h745i_disco_stm32h745xx_m7.dts | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts index 2d46284294ea7e..227cb9ab8c266f 100644 --- a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts @@ -33,18 +33,6 @@ }; }; - transceiver0: can-phy0 { - compatible = "microchip,mcp2562fd", "can-transceiver-gpio"; - max-bitrate = <5000000>; - #phy-cells = <0>; - }; - - transceiver1: can-phy1 { - compatible = "microchip,mcp2562fd", "can-transceiver-gpio"; - max-bitrate = <5000000>; - #phy-cells = <0>; - }; - /* RM0455 - 23.6 External device address mapping */ sdram2: sdram@d0000000 { compatible = "zephyr,memory-region", "mmio-sram"; @@ -218,7 +206,10 @@ bus-speed-data = <1000000>; sample-point = <875>; sample-point-data = <875>; - phys = <&transceiver0>; + + can-transceiver { + max-bitrate = <5000000>; + }; }; &fdcan2 { @@ -229,7 +220,10 @@ bus-speed-data = <1000000>; sample-point = <875>; sample-point-data = <875>; - phys = <&transceiver1>; + + can-transceiver { + max-bitrate = <5000000>; + }; }; &fmc { From 8ae34f730e36a890a0a4ee91a2233f5f76564cce Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0707/1389] drivers: can: transceiver: gpio: add build assert for GPIO properties Add a build-time assert for verifying that at least one of the supported devicetree GPIO properties is present on each compatible devicetree node. Signed-off-by: Henrik Brix Andersen --- drivers/can/transceiver/can_transceiver_gpio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/can/transceiver/can_transceiver_gpio.c b/drivers/can/transceiver/can_transceiver_gpio.c index e6aaacc8c34eb5..3f7bbca688f078 100644 --- a/drivers/can/transceiver/can_transceiver_gpio.c +++ b/drivers/can/transceiver/can_transceiver_gpio.c @@ -120,6 +120,11 @@ static const struct can_transceiver_driver_api can_transceiver_gpio_driver_api = (.name##_gpio = GPIO_DT_SPEC_INST_GET(inst, name##_gpios),)) #define CAN_TRANSCEIVER_GPIO_INIT(inst) \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(inst, enable_gpios) || \ + DT_INST_NODE_HAS_PROP(inst, standby_gpios), \ + "Missing GPIO property on " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + \ static const struct can_transceiver_gpio_config can_transceiver_gpio_config_##inst = { \ CAN_TRANSCEIVER_GPIO_COND(inst, enable) \ CAN_TRANSCEIVER_GPIO_COND(inst, standby) \ From 47f403c3846691a96650a7bf220c86a30214a4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0708/1389] drivers: udc_dwc2: Fix debug logging bus fault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass DIEPTXF address instead of value to sys_read32() to prevent bus fault when debug logging is enabled. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index ea9dc2da7a4246..2f6825e52b709d 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -1168,7 +1168,7 @@ static int udc_dwc2_ep_enable(const struct device *dev, for (uint8_t i = 1U; i < priv->ineps; i++) { LOG_DBG("DIEPTXF%u %08x DIEPCTL%u %08x", - i, sys_read32((mem_addr_t)base->dieptxf[i - 1U]), i, dxepctl); + i, sys_read32((mem_addr_t)&base->dieptxf[i - 1U]), i, dxepctl); } return 0; From 0e4bd879c60671271bb29f28887570dd76b2820e Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0709/1389] twister: Allow to run sysbuild with native_sim Fix issue 72083. Update path to zephyr.exe binary using default domain from domains.yaml file. Signed-off-by: Grzegorz Chwierut --- scripts/pylib/twister/twisterlib/handlers.py | 58 +++++++------------- scripts/tests/twister/test_handlers.py | 11 ++-- 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index c3fe7da2f56a07..5ef10906b4e54a 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -74,7 +74,6 @@ def __init__(self, instance, type_str="build"): self.run = False self.type_str = type_str - self.binary = None self.pid_fn = None self.call_make_run = True @@ -150,6 +149,19 @@ def _final_handle_actions(self, harness, handler_time): self.instance.record(harness.recording) + def get_default_domain_build_dir(self): + if self.instance.testsuite.sysbuild: + # Load domain yaml to get default domain build directory + # Note: for targets using QEMU, we assume that the target will + # have added any additional images to the run target manually + domain_path = os.path.join(self.build_dir, "domains.yaml") + domains = Domains.from_file(domain_path) + logger.debug("Loaded sysbuild domain data from %s" % domain_path) + build_dir = domains.get_default_domain().build_dir + else: + build_dir = self.build_dir + return build_dir + class BinaryHandler(Handler): def __init__(self, instance, type_str): @@ -222,7 +234,8 @@ def _create_command(self, robot_test): elif self.call_make_run: command = [self.generator_cmd, "run"] else: - command = [self.binary] + binary = os.path.join(self.get_default_domain_build_dir(), "zephyr", "zephyr.exe") + command = [binary] if self.options.enable_valgrind: command = ["valgrind", "--error-exitcode=2", @@ -327,7 +340,6 @@ def __init__(self, instance, type_str): self.pid_fn = os.path.join(instance.build_dir, "renode.pid") elif type_str == 'native': self.call_make_run = False - self.binary = os.path.join(instance.build_dir, "zephyr", "zephyr.exe") self.ready = True @@ -935,20 +947,6 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, QEMUHandler._thread_close_files(fifo_in, fifo_out, pid, out_fp, in_fp, log_out_fp) - def _get_sysbuild_build_dir(self): - if self.instance.testsuite.sysbuild: - # Load domain yaml to get default domain build directory - # Note: for targets using QEMU, we assume that the target will - # have added any additional images to the run target manually - domain_path = os.path.join(self.build_dir, "domains.yaml") - domains = Domains.from_file(domain_path) - logger.debug("Loaded sysbuild domain data from %s" % domain_path) - build_dir = domains.get_default_domain().build_dir - else: - build_dir = self.build_dir - - return build_dir - def _set_qemu_filenames(self, sysbuild_build_dir): # We pass this to QEMU which looks for fifos with .in and .out suffixes. # QEMU fifo will use main build dir @@ -980,11 +978,11 @@ def _update_instance_info(self, harness_state, is_timeout): def handle(self, harness): self.run = True - sysbuild_build_dir = self._get_sysbuild_build_dir() + domain_build_dir = self.get_default_domain_build_dir() - command = self._create_command(sysbuild_build_dir) + command = self._create_command(domain_build_dir) - self._set_qemu_filenames(sysbuild_build_dir) + self._set_qemu_filenames(domain_build_dir) self.thread = threading.Thread(name=self.name, target=QEMUHandler._thread, args=(self, self.get_test_timeout(), self.build_dir, @@ -1124,20 +1122,6 @@ def _monitor_update_instance_info(handler, handler_time, out_state): handler.instance.status = out_state handler.instance.reason = "Unknown" - def _get_sysbuild_build_dir(self): - if self.instance.testsuite.sysbuild: - # Load domain yaml to get default domain build directory - # Note: for targets using QEMU, we assume that the target will - # have added any additional images to the run target manually - domain_path = os.path.join(self.build_dir, "domains.yaml") - domains = Domains.from_file(domain_path) - logger.debug("Loaded sysbuild domain data from %s" % domain_path) - build_dir = domains.get_default_domain().build_dir - else: - build_dir = self.build_dir - - return build_dir - def _set_qemu_filenames(self, sysbuild_build_dir): # PID file will be created in the main sysbuild app's build dir self.pid_fn = os.path.join(sysbuild_build_dir, "qemu.pid") @@ -1277,9 +1261,9 @@ def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexp def handle(self, harness): self.run = True - sysbuild_build_dir = self._get_sysbuild_build_dir() - command = self._create_command(sysbuild_build_dir) - self._set_qemu_filenames(sysbuild_build_dir) + domain_build_dir = self.get_default_domain_build_dir() + command = self._create_command(domain_build_dir) + self._set_qemu_filenames(domain_build_dir) logger.debug("Running %s (%s)" % (self.name, self.type_str)) is_timeout = False diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 7a3b56a130f513..b5012646eb9048 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -415,7 +415,7 @@ def wait(self, *args, **kwargs): '--log-file=build_dir/valgrind.log', '--track-origins=yes', 'generator', 'run_renode_test']), (False, True, False, 123, None, ['generator', 'run', '--seed=123']), - (False, False, False, None, ['ex1', 'ex2'], ['bin', 'ex1', 'ex2']), + (False, False, False, None, ['ex1', 'ex2'], ['build_dir/zephyr/zephyr.exe', 'ex1', 'ex2']), ] @pytest.mark.parametrize( @@ -441,6 +441,7 @@ def test_binaryhandler_create_command( handler.seed = seed handler.extra_test_args = extra_args handler.build_dir = 'build_dir' + handler.instance.testsuite.sysbuild = False command = handler._create_command(robot_test) @@ -1445,7 +1446,7 @@ def mock_process(pid): TESTDATA_19, ids=['domains build dir', 'self build dir'] ) -def test_qemuhandler_get_sysbuild_build_dir( +def test_qemuhandler_get_default_domain_build_dir( mocked_instance, self_sysbuild, self_build_dir, @@ -1462,7 +1463,7 @@ def test_qemuhandler_get_sysbuild_build_dir( handler.build_dir = self_build_dir with mock.patch('domains.Domains.from_file', from_file_mock): - result = handler._get_sysbuild_build_dir() + result = handler.get_default_domain_build_dir() assert result == expected @@ -1984,7 +1985,7 @@ def mock_filenames(sysbuild_build_dir): harness = mock.Mock(state=harness_state) handler_options_west_flash = [] - sysbuild_build_dir = os.path.join('sysbuild', 'dummydir') + domain_build_dir = os.path.join('sysbuild', 'dummydir') command = ['generator_cmd', '-C', os.path.join('cmd', 'path'), 'run'] handler.options = mock.Mock( @@ -1997,7 +1998,7 @@ def mock_filenames(sysbuild_build_dir): handler._final_handle_actions = mock.Mock(return_value=None) handler._create_command = mock.Mock(return_value=command) handler._set_qemu_filenames = mock.Mock(side_effect=mock_filenames) - handler._get_sysbuild_build_dir = mock.Mock(return_value=sysbuild_build_dir) + handler.get_default_domain_build_dir = mock.Mock(return_value=domain_build_dir) handler.terminate = mock.Mock() unlink_mock = mock.Mock() From 31d2741432809a5dce54e8e8af638714a51ed5e6 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:03 +0200 Subject: [PATCH 0710/1389] mbedtls: fix entropy module enablement - Do not set CONFIG_MBEDTLS_ZEPHYR_ENTROPY in tests/crypto/mbedtls because this can cause test failure on real devices in which test thread do not have access to drivers. - make MBEDTLS_PSA_CRYPTO_RND_SOURCE depending on MBEDTLS_PSA_CRYPTO_C because it only makes sense when the latter is defined Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.tls-generic | 2 +- tests/crypto/mbedtls/prj.conf | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index d377bb46b8d1d9..eec38e05089fbd 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -462,6 +462,7 @@ config MBEDTLS_SSL_EXTENDED_MASTER_SECRET choice MBEDTLS_PSA_CRYPTO_RND_SOURCE prompt "Select random source for built-in PSA crypto" + depends on MBEDTLS_PSA_CRYPTO_C default MBEDTLS_PSA_CRYPTO_LEGACY_RNG config MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG @@ -483,7 +484,6 @@ endchoice config MBEDTLS_PSA_CRYPTO_C bool "Platform Security Architecture cryptography API" - depends on MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG || MBEDTLS_PSA_CRYPTO_LEGACY_RNG default y if UOSCORE || UEDHOC config MBEDTLS_USE_PSA_CRYPTO diff --git a/tests/crypto/mbedtls/prj.conf b/tests/crypto/mbedtls/prj.conf index dd5e629e16a400..9f916487099c1e 100644 --- a/tests/crypto/mbedtls/prj.conf +++ b/tests/crypto/mbedtls/prj.conf @@ -8,5 +8,4 @@ CONFIG_MINIMAL_LIBC=y CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y CONFIG_MINIMAL_LIBC_RAND=y CONFIG_ENTROPY_GENERATOR=y -CONFIG_MBEDTLS_ZEPHYR_ENTROPY=y CONFIG_TEST_RANDOM_GENERATOR=y From 1ac359d06ade2fe0a9e4ef605a7753e60c570ce1 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0711/1389] twister: handler: optimize handler testsuite check in many platforms, before the debuger flash, the former testsuite many already executed, so we will see some old testsuite name. and we should not compare them directly, instead if we compare in reversed order them we can avoid such mis-judge. Signed-off-by: Hake Huang --- scripts/pylib/twister/twisterlib/handlers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 5ef10906b4e54a..b8007849eb55b6 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -113,10 +113,12 @@ def _verify_ztest_suite_name(self, harness_state, detected_suite_names, handler_ return if not detected_suite_names: self._missing_suite_name(expected_suite_names, handler_time) - for detected_suite_name in detected_suite_names: - if detected_suite_name not in expected_suite_names: + return + # compare the expect and detect from end one by one without order + _d_suite = detected_suite_names[-len(expected_suite_names):] + if set(_d_suite) != set(expected_suite_names): + if not set(_d_suite).issubset(set(expected_suite_names)): self._missing_suite_name(expected_suite_names, handler_time) - break def _missing_suite_name(self, expected_suite_names, handler_time): """ From 01d98b901adcf98c1ca5b2acff478fce788dd62b Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0712/1389] twister: Add Twister execution options to twister.json Store Twister command line options in twister.json report as `environment.options` object. It allows to keep the actual execution context for test results analysis and history comparison. A new command line option `--report-all-options` enables to report all command line options applied, including these set as default values. Signed-off-by: Dmitrii Golovanov --- .../pylib/twister/twisterlib/environment.py | 27 ++++++++++++++++--- scripts/pylib/twister/twisterlib/reports.py | 14 +++++++++- .../pylib/twister/twisterlib/twister_main.py | 4 +-- scripts/twister | 3 ++- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index ea1eb1856db174..177cc4b3f931f3 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -614,6 +614,12 @@ def add_parse_arguments(parser = None): version or a commit ID. """) + parser.add_argument( + "--report-all-options", action="store_true", + help="""Show all command line options applied, including defaults, as + environment.options object in twister.json. Default: show only non-default settings. + """) + parser.add_argument( "--retry-failed", type=int, default=0, help="Retry failing tests again, up to the number of times specified.") @@ -744,7 +750,7 @@ def add_parse_arguments(parser = None): return parser -def parse_arguments(parser, args, options = None): +def parse_arguments(parser, args, options = None, on_init=True): if options is None: options = parser.parse_args(args) @@ -862,13 +868,13 @@ def parse_arguments(parser, args, options = None): # Strip off the initial "--" following validation. options.extra_test_args = options.extra_test_args[1:] - if not options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: + if on_init and not options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: logger.error("By default Twister should work without pytest-twister-harness " "plugin being installed, so please, uninstall it by " "`pip uninstall pytest-twister-harness` and `git clean " "-dxf scripts/pylib/pytest-twister-harness`.") sys.exit(1) - elif options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: + elif on_init and options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: logger.warning("You work with installed version of " "pytest-twister-harness plugin.") @@ -880,12 +886,13 @@ def strip_ansi_sequences(s: str) -> str: class TwisterEnv: - def __init__(self, options=None) -> None: + def __init__(self, options=None, default_options=None) -> None: self.version = "Unknown" self.toolchain = None self.commit_date = "Unknown" self.run_date = None self.options = options + self.default_options = default_options if options and options.ninja: self.generator_cmd = "ninja" @@ -920,6 +927,18 @@ def __init__(self, options=None) -> None: self.alt_config_root = options.alt_config_root if options else None + def non_default_options(self) -> dict: + """Returns current command line options which are set to non-default values.""" + diff = {} + if not self.options or not self.default_options: + return diff + dict_options = vars(self.options) + dict_default = vars(self.default_options) + for k in dict_options.keys(): + if k not in dict_default or dict_options[k] != dict_default[k]: + diff[k] = dict_options[k] + return diff + def discover(self): self.check_zephyr_version() self.get_toolchain() diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index c02bda79c4eaf3..48c9df082c486f 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -11,6 +11,7 @@ import xml.etree.ElementTree as ET import string from datetime import datetime +from pathlib import PosixPath logger = logging.getLogger('twister') logger.setLevel(logging.DEBUG) @@ -235,12 +236,23 @@ def xunit_report(self, json_file, filename, selected_platform=None, full_report= def json_report(self, filename, version="NA", platform=None): logger.info(f"Writing JSON report {filename}") + + if self.env.options.report_all_options: + report_options = vars(self.env.options) + else: + report_options = self.env.non_default_options() + + # Resolve known JSON serialization problems. + for k,v in report_options.items(): + report_options[k] = str(v) if type(v) in [PosixPath] else v + report = {} report["environment"] = {"os": os.name, "zephyr_version": version, "toolchain": self.env.toolchain, "commit_date": self.env.commit_date, - "run_date": self.env.run_date + "run_date": self.env.run_date, + "options": report_options } suites = [] diff --git a/scripts/pylib/twister/twisterlib/twister_main.py b/scripts/pylib/twister/twisterlib/twister_main.py index f61880c1b0528e..33b0569f330bcf 100644 --- a/scripts/pylib/twister/twisterlib/twister_main.py +++ b/scripts/pylib/twister/twisterlib/twister_main.py @@ -62,7 +62,7 @@ def init_color(colorama_strip): colorama.init(strip=colorama_strip) -def main(options): +def main(options, default_options): start_time = time.time() # Configure color output @@ -105,7 +105,7 @@ def main(options): VERBOSE = options.verbose setup_logging(options.outdir, options.log_file, VERBOSE, options.timestamps) - env = TwisterEnv(options) + env = TwisterEnv(options, default_options) env.discover() hwm = HardwareMap(env) diff --git a/scripts/twister b/scripts/twister index aa075beb7a1fbc..c6382f9a9e3379 100755 --- a/scripts/twister +++ b/scripts/twister @@ -211,7 +211,8 @@ if __name__ == "__main__": try: parser = add_parse_arguments() options = parse_arguments(parser, sys.argv[1:]) - ret = main(options) + default_options = parse_arguments(parser, [], on_init=False) + ret = main(options, default_options) finally: if (os.name != "nt") and os.isatty(1): # (OS is not Windows) and (stdout is interactive) From c31b1b35b82b9ba2436ae36a5e76ca69a16ae41f Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0713/1389] Bluetooth: BAP: Remove err from recv_state_removed callback The callback is only ever called when we received a notification from the BASS server that the receive state is removed, which cannot contain an error code. Thus it does not make sense for the callback to have an error code. Signed-off-by: Emil Gydesen --- doc/releases/release-notes-3.7.rst | 6 ++++++ include/zephyr/bluetooth/audio/bap.h | 4 +--- subsys/bluetooth/audio/bap_broadcast_assistant.c | 9 ++++----- .../bluetooth/audio/shell/bap_broadcast_assistant.c | 11 ++--------- tests/bluetooth/tester/src/btp_bap_broadcast.c | 5 ++--- .../audio/src/bap_broadcast_assistant_test.c | 8 +------- 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index d73bd134332f32..ce4215db4a37e4 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -78,6 +78,12 @@ Kernel Bluetooth ********* +* Audio + + * Removed ``err`` from :c:struct:`bt_bap_broadcast_assistant_cb.recv_state_removed` as it was + redundant. + +* Host * Added Nordic UART Service (NUS), enabled by the :kconfig:option:`CONFIG_BT_ZEPHYR_NUS`. This Service exposes the ability to declare multiple instances of the GATT service, diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 08a2a642eb029b..cc96141213153c 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -2101,11 +2101,9 @@ struct bt_bap_broadcast_assistant_cb { * @brief Callback function for when a receive state is removed. * * @param conn The connection to the Broadcast Audio Scan Service server. - * @param err Error value. 0 on success, GATT error on fail. * @param src_id The receive state. */ - void (*recv_state_removed)(struct bt_conn *conn, int err, - uint8_t src_id); + void (*recv_state_removed)(struct bt_conn *conn, uint8_t src_id); /** * @brief Callback function for bt_bap_broadcast_assistant_scan_start(). diff --git a/subsys/bluetooth/audio/bap_broadcast_assistant.c b/subsys/bluetooth/audio/bap_broadcast_assistant.c index aef75d072e4850..6013afbf817769 100644 --- a/subsys/bluetooth/audio/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/bap_broadcast_assistant.c @@ -118,15 +118,14 @@ static void bap_broadcast_assistant_recv_state_changed( } } -static void bap_broadcast_assistant_recv_state_removed(struct bt_conn *conn, int err, - uint8_t src_id) +static void bap_broadcast_assistant_recv_state_removed(struct bt_conn *conn, uint8_t src_id) { struct bt_bap_broadcast_assistant_cb *listener, *next; SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs, listener, next, _node) { if (listener->recv_state_removed) { - listener->recv_state_removed(conn, err, src_id); + listener->recv_state_removed(conn, src_id); } } } @@ -442,8 +441,8 @@ static uint8_t notify_handler(struct bt_conn *conn, } } else { broadcast_assistant.recv_states[index].past_avail = false; - bap_broadcast_assistant_recv_state_removed(conn, 0, - broadcast_assistant.recv_states[index].src_id); + bap_broadcast_assistant_recv_state_removed( + conn, broadcast_assistant.recv_states[index].src_id); } return BT_GATT_ITER_CONTINUE; diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index dfe868fac45a1e..6f210a4ae5eb3e 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -215,16 +215,9 @@ static void bap_broadcast_assistant_recv_state_cb( } } -static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, - int err, - uint8_t src_id) +static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, uint8_t src_id) { - if (err != 0) { - shell_error(ctx_shell, "BASS recv state removed failed (%d)", - err); - } else { - shell_print(ctx_shell, "BASS recv state %u removed", src_id); - } + shell_print(ctx_shell, "BASS recv state %u removed", src_id); } static void bap_broadcast_assistant_scan_start_cb(struct bt_conn *conn, int err) diff --git a/tests/bluetooth/tester/src/btp_bap_broadcast.c b/tests/bluetooth/tester/src/btp_bap_broadcast.c index b278eb3255665c..75b2ed716e86ef 100644 --- a/tests/bluetooth/tester/src/btp_bap_broadcast.c +++ b/tests/bluetooth/tester/src/btp_bap_broadcast.c @@ -1266,10 +1266,9 @@ static void bap_broadcast_assistant_recv_state_cb(struct bt_conn *conn, int err, btp_send_broadcast_receive_state_ev(conn, state); } -static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, int err, - uint8_t src_id) +static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, uint8_t src_id) { - LOG_DBG("err: %d", err); + LOG_DBG(""); } static void bap_broadcast_assistant_scan_start_cb(struct bt_conn *conn, int err) diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c index 86f30cad9f4b1f..58beed0f7bf897 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_assistant_test.c @@ -155,14 +155,8 @@ static void bap_broadcast_assistant_recv_state_cb( SET_FLAG(flag_recv_state_updated); } -static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, int err, - uint8_t src_id) +static void bap_broadcast_assistant_recv_state_removed_cb(struct bt_conn *conn, uint8_t src_id) { - if (err != 0) { - FAIL("BASS recv state removed failed (%d)\n", err); - return; - } - printk("BASS recv state %u removed\n", src_id); SET_FLAG(flag_cb_called); From 1c41527f8ca86b67122ddcb6f2cc3373e7223b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0714/1389] samples: drivers: watchdog: Run sample on nrf54h20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlay that enables selected WDT instance on nrf54h20 Application core. Signed-off-by: Sebastian Głąb --- .../watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..94e0d719af4ef5 --- /dev/null +++ b/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt010 { + status = "okay"; +}; From 87f5e3b458d44d8b2b3ab2f77c5c3b2cda686504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0715/1389] boards: nordic: nrf54h20dk: Define alias watchdog0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define alias watchdog0 for nrf54h20 Application core. Signed-off-by: Sebastian Głąb --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 6e694191477968..5cd3d5b78e8256 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -39,6 +39,7 @@ sw2 = &button2; sw3 = &button3; ipc-to-cpusys = &cpuapp_cpusys_ipc; + watchdog0 = &wdt010; }; buttons { From bc6fa4520491fedc192d9ed05f2a4777aac18eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0716/1389] boards: nordic: nrf54h20dk: Disable watchdog tests on Radio core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is enough to test watchdog driver on the application core. Otherwise, at least three samples/tests fail due to missing overlay file for nrf54h20dk/nrf54h20/cpurad. Signed-off-by: Sebastian Głąb --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml index 68d169331ef831..53bbff4a460069 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml @@ -15,4 +15,3 @@ supported: - gpio - pwm - spi - - watchdog From b31af8792c7be427291f2dec5a5c5ccc75d50c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0717/1389] samples: drivers: watchdog: Add overlay files for nrf54l15/cpuflpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both nrf54l15pdk/cpuflpr and nrf54l15pdk/cpuflpr_xip have watchdog on the list of supported periperals. As a result, Twister tries to build samples/drivers/watchdog for these two targets. Since overlays are missing, build is failing. Add missing overlay files. Signed-off-by: Sebastian Głąb --- .../watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay | 8 ++++++++ .../boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay create mode 100644 samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay new file mode 100644 index 00000000000000..66157d79fb36ff --- /dev/null +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt30 { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay new file mode 100644 index 00000000000000..66157d79fb36ff --- /dev/null +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt30 { + status = "okay"; +}; From 1798611af5c92668bec6da13ddab6f47d5010004 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0718/1389] net: lwm2m: Add offset to post-write callback When Block-Wise transfer restarts, the post-write callback should receive some indication that the block is actually a beginning of new, instead of part of previous transfer. Fixes #71351 Signed-off-by: Seppo Takalo --- doc/releases/migration-guide-3.7.rst | 7 ++++++ doc/releases/release-notes-3.7.rst | 3 +++ include/zephyr/net/lwm2m.h | 7 +++++- .../net/lwm2m_client/src/firmware_update.c | 12 +++++----- samples/net/lwm2m_client/src/led.c | 2 +- samples/net/lwm2m_client/src/timer.c | 4 ++-- subsys/net/lib/lwm2m/ipso_buzzer.c | 8 +++---- subsys/net/lib/lwm2m/ipso_current_sensor.c | 2 +- subsys/net/lib/lwm2m/ipso_filling_sensor.c | 2 +- subsys/net/lib/lwm2m/ipso_generic_sensor.c | 2 +- subsys/net/lib/lwm2m/ipso_humidity_sensor.c | 2 +- subsys/net/lib/lwm2m/ipso_light_control.c | 8 +++---- subsys/net/lib/lwm2m/ipso_onoff_switch.c | 16 +++++++------- subsys/net/lib/lwm2m/ipso_pressure_sensor.c | 2 +- subsys/net/lib/lwm2m/ipso_push_button.c | 8 +++---- subsys/net/lib/lwm2m/ipso_temp_sensor.c | 8 +++---- subsys/net/lib/lwm2m/ipso_timer.c | 22 ++++++++++--------- subsys/net/lib/lwm2m/ipso_voltage_sensor.c | 2 +- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 15 +++++++++---- .../net/lib/lwm2m/lwm2m_obj_access_control.c | 6 +++-- subsys/net/lib/lwm2m/lwm2m_obj_device.c | 6 ++--- subsys/net/lib/lwm2m/lwm2m_obj_firmware.c | 12 +++++----- subsys/net/lib/lwm2m/lwm2m_obj_gateway.c | 7 +++--- subsys/net/lib/lwm2m/lwm2m_obj_server.c | 2 +- subsys/net/lib/lwm2m/lwm2m_obj_swmgmt.c | 20 ++++++++++------- subsys/net/lib/lwm2m/lwm2m_pull_context.c | 5 ++++- subsys/net/lib/lwm2m/lwm2m_registry.c | 4 ++-- .../lwm2m/lwm2m_registry/src/lwm2m_registry.c | 15 ++++++------- 28 files changed, 122 insertions(+), 87 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 762e581dece586..8eaed64cb5e0b2 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -378,6 +378,13 @@ Networking ``CONFIG_NET_TCP_RETRY_COUNT`` instead to control the total timeout at the TCP level. (:github:`70731`) +* In LwM2M API, the callback type :c:type:`lwm2m_engine_set_data_cb_t` has now an additional + parameter ``offset``. This parameter is used to indicate the offset of the data + during a Coap Block-wise transfer. Any post write, validate or some firmware callbacks + should be updated to include this parameter. (:github:`72590`) + + + Other Subsystems **************** diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index ce4215db4a37e4..12c90c0298bb1d 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -287,6 +287,9 @@ Networking * :c:func:`lwm2m_set_bulk` + * Added new ``offset`` parameter to :c:type:`lwm2m_engine_set_data_cb_t` callback type. + This affects post write and validate callbacks as well as some firmware callbacks. + * IPSP: * Removed IPSP support. ``CONFIG_NET_L2_BT`` does not exist anymore. diff --git a/include/zephyr/net/lwm2m.h b/include/zephyr/net/lwm2m.h index e68f5fb47ad4c1..68a5ef9617ed56 100644 --- a/include/zephyr/net/lwm2m.h +++ b/include/zephyr/net/lwm2m.h @@ -329,6 +329,10 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, * make use of this callback to pass the data back to the client or LwM2M * objects. * + * On a block-wise transfers the handler is called multiple times with the data blocks + * and increasing offset. The last block has the last_block flag set to true. + * Beginning of the block transfer has the offset set to 0. + * * A function of this type can be registered via: * lwm2m_engine_register_validate_callback() * lwm2m_engine_register_post_write_callback() @@ -344,6 +348,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, * false. * @param[in] total_size Expected total size of data for a block transfer. * For non-block transfers this is 0. + * @param[in] offset Offset of the data block. For non-block transfers this is always 0. * * @return Callback returns a negative error code (errno.h) indicating * reason of failure or 0 for success. @@ -351,7 +356,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, typedef int (*lwm2m_engine_set_data_cb_t)(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size); + bool last_block, size_t total_size, size_t offset); /** * @brief Asynchronous event notification callback. diff --git a/samples/net/lwm2m_client/src/firmware_update.c b/samples/net/lwm2m_client/src/firmware_update.c index dd6dcd8d599834..5ef2e1cf127c0d 100644 --- a/samples/net/lwm2m_client/src/firmware_update.c +++ b/samples/net/lwm2m_client/src/firmware_update.c @@ -38,13 +38,13 @@ static void *firmware_get_buf(uint16_t obj_inst_id, uint16_t res_id, return firmware_buf; } -static int firmware_block_received_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int firmware_block_received_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { - LOG_INF("FIRMWARE: BLOCK RECEIVED: len:%u last_block:%d", - data_len, last_block); + LOG_INF("FIRMWARE: BLOCK RECEIVED: offset:%zd len:%u last_block:%d", + offset, data_len, last_block); return 0; } diff --git a/samples/net/lwm2m_client/src/led.c b/samples/net/lwm2m_client/src/led.c index 98055baa580cf3..d4aa6388890708 100644 --- a/samples/net/lwm2m_client/src/led.c +++ b/samples/net/lwm2m_client/src/led.c @@ -22,7 +22,7 @@ static uint32_t led_state; /* TODO: Move to a pre write hook that can handle ret codes once available */ static int led_on_off_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, - uint16_t data_len, bool last_block, size_t total_size) + uint16_t data_len, bool last_block, size_t total_size, size_t offset) { int ret = 0; uint32_t led_val; diff --git a/samples/net/lwm2m_client/src/timer.c b/samples/net/lwm2m_client/src/timer.c index 17814ae134cecd..861074513440d8 100644 --- a/samples/net/lwm2m_client/src/timer.c +++ b/samples/net/lwm2m_client/src/timer.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); /* An example data validation callback. */ static int timer_on_off_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { LOG_INF("Validating On/Off data"); @@ -34,7 +34,7 @@ static int timer_on_off_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint1 static int timer_digital_state_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { bool *digital_state = (bool *)data; diff --git a/subsys/net/lib/lwm2m/ipso_buzzer.c b/subsys/net/lib/lwm2m/ipso_buzzer.c index f679d7e4a606e1..c44df2c54312ad 100644 --- a/subsys/net/lib/lwm2m/ipso_buzzer.c +++ b/subsys/net/lib/lwm2m/ipso_buzzer.c @@ -144,10 +144,10 @@ static int stop_buzzer(struct ipso_buzzer_data *buzzer, bool cancel) return 0; } -static int onoff_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int onoff_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_current_sensor.c b/subsys/net/lib/lwm2m/ipso_current_sensor.c index 1268b7da56d950..bfe713a1cbec60 100644 --- a/subsys/net/lib/lwm2m/ipso_current_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_current_sensor.c @@ -112,7 +112,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id, static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_filling_sensor.c b/subsys/net/lib/lwm2m/ipso_filling_sensor.c index 96944e0c16ad50..9fae4cfeb25477 100644 --- a/subsys/net/lib/lwm2m/ipso_filling_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_filling_sensor.c @@ -121,7 +121,7 @@ static void update(uint16_t obj_inst_id, uint16_t res_id, int index) static int update_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) + bool last_block, size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_generic_sensor.c b/subsys/net/lib/lwm2m/ipso_generic_sensor.c index 05a1afc9806e8d..2b5381d564c9ed 100644 --- a/subsys/net/lib/lwm2m/ipso_generic_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_generic_sensor.c @@ -121,7 +121,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id, static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_humidity_sensor.c b/subsys/net/lib/lwm2m/ipso_humidity_sensor.c index b2d147060a02e0..85bb2335c2e915 100644 --- a/subsys/net/lib/lwm2m/ipso_humidity_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_humidity_sensor.c @@ -107,7 +107,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id, static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_light_control.c b/subsys/net/lib/lwm2m/ipso_light_control.c index 55b9f7728cabd7..883dece531d2bb 100644 --- a/subsys/net/lib/lwm2m/ipso_light_control.c +++ b/subsys/net/lib/lwm2m/ipso_light_control.c @@ -88,10 +88,10 @@ static void *on_time_read_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res return NULL; } -static int on_time_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int on_time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_onoff_switch.c b/subsys/net/lib/lwm2m/ipso_onoff_switch.c index 3da496b2ca1a61..da1cf464d83fbb 100644 --- a/subsys/net/lib/lwm2m/ipso_onoff_switch.c +++ b/subsys/net/lib/lwm2m/ipso_onoff_switch.c @@ -87,10 +87,10 @@ static int get_switch_index(uint16_t obj_inst_id) return ret; } -static int state_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int state_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; @@ -157,10 +157,10 @@ static void *off_time_read_cb(uint16_t obj_inst_id, return &switch_data[i].off_time_sec; } -static int time_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i = get_switch_index(obj_inst_id); diff --git a/subsys/net/lib/lwm2m/ipso_pressure_sensor.c b/subsys/net/lib/lwm2m/ipso_pressure_sensor.c index 7dca2ed39560d2..f6b59591d7d661 100644 --- a/subsys/net/lib/lwm2m/ipso_pressure_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_pressure_sensor.c @@ -108,7 +108,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id, static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_push_button.c b/subsys/net/lib/lwm2m/ipso_push_button.c index 07782a86756ccd..475363a75efaf7 100644 --- a/subsys/net/lib/lwm2m/ipso_push_button.c +++ b/subsys/net/lib/lwm2m/ipso_push_button.c @@ -82,10 +82,10 @@ static int get_button_index(uint16_t obj_inst_id) return ret; } -static int state_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int state_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_temp_sensor.c b/subsys/net/lib/lwm2m/ipso_temp_sensor.c index ba843db0ebdfbe..6d258b9d5fbd0a 100644 --- a/subsys/net/lib/lwm2m/ipso_temp_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_temp_sensor.c @@ -107,10 +107,10 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id, return -ENOENT; } -static int sensor_value_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_timer.c b/subsys/net/lib/lwm2m/ipso_timer.c index 833002e56c49a3..cf4798d745657c 100644 --- a/subsys/net/lib/lwm2m/ipso_timer.c +++ b/subsys/net/lib/lwm2m/ipso_timer.c @@ -200,9 +200,10 @@ static void *cumulative_time_read_cb(uint16_t obj_inst_id, } static int cumulative_time_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) + uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; @@ -215,10 +216,10 @@ static int cumulative_time_post_write_cb(uint16_t obj_inst_id, return 0; } -static int enabled_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int enabled_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; @@ -236,9 +237,10 @@ static int enabled_post_write_cb(uint16_t obj_inst_id, } static int trigger_counter_post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) + uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/ipso_voltage_sensor.c b/subsys/net/lib/lwm2m/ipso_voltage_sensor.c index ec1274d07fffb8..87fb1b837613d2 100644 --- a/subsys/net/lib/lwm2m/ipso_voltage_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_voltage_sensor.c @@ -113,7 +113,7 @@ static int reset_min_max_measured_values_cb(uint16_t obj_inst_id, static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { int i; diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 3596f432476f16..462ed32fafd6f1 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -984,7 +984,8 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, if (res->validate_cb) { ret = res->validate_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id, write_buf, len, - last_pkt_block && last_block, opaque_ctx.len); + last_pkt_block && last_block, opaque_ctx.len, + msg->in.block_ctx->ctx.current); if (ret < 0) { /* -EEXIST will generate Bad Request LWM2M response. */ return -EEXIST; @@ -997,11 +998,15 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, if (res->post_write_cb) { ret = res->post_write_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id, data_ptr, len, - last_pkt_block && last_block, opaque_ctx.len); + last_pkt_block && last_block, opaque_ctx.len, + msg->in.block_ctx->ctx.current); if (ret < 0) { return ret; } } + if (msg->in.block_ctx) { + msg->in.block_ctx->ctx.current += len; + } } if (msg->in.block_ctx != NULL) { @@ -1200,11 +1205,13 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng } if (obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) { + size_t offset = msg->in.block_ctx ? msg->in.block_ctx->ctx.current : 0; + #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 if (res->validate_cb) { ret = res->validate_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id, write_buf, len, last_block, - total_size); + total_size, offset); if (ret < 0) { /* -EEXIST will generate Bad Request LWM2M response. */ return -EEXIST; @@ -1227,7 +1234,7 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng if (res->post_write_cb) { ret = res->post_write_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id, data_ptr, len, last_block, - total_size); + total_size, offset); } } diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c b/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c index e5eb8c56efb1cf..287be88f72645f 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_access_control.c @@ -335,8 +335,10 @@ static void add_existing_objects(void) } } -static int write_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, bool last_block, size_t total_size) +static int write_validate_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { /* validates and removes acl instances for non-existing servers */ diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_device.c b/subsys/net/lib/lwm2m/lwm2m_obj_device.c index cdebef24532b9d..208423eb04a419 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_device.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_device.c @@ -190,9 +190,9 @@ static void *current_time_pre_write_cb(uint16_t obj_inst_id, uint16_t res_id, } static int current_time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id, - uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { if (data_len == 4U) { time_offset = *(uint32_t *)data - k_uptime_seconds(); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index ad313163548080..1ba3789f1cf3d4 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -235,8 +235,9 @@ void lwm2m_firmware_set_update_result(uint8_t result) } static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, - uint16_t res_inst_id, uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { uint8_t state; int ret = 0; @@ -270,7 +271,7 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, write_callback = lwm2m_firmware_get_write_cb_inst(obj_inst_id); if (write_callback) { ret = write_callback(obj_inst_id, res_id, res_inst_id, data, data_len, last_block, - total_size); + total_size, offset); } if (ret >= 0) { @@ -298,8 +299,9 @@ static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, } static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, - uint16_t res_inst_id, uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { LOG_DBG("PACKAGE_URI WRITE: %s", package_uri[obj_inst_id]); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c index 106ef951653404..fb82fe6c3f5c44 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c @@ -61,9 +61,10 @@ static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][GATEWAY_MAX_ID]; static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; lwm2m_engine_gateway_msg_cb gateway_msg_cb[MAX_INSTANCE_COUNT]; -static int prefix_validation_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) +static int prefix_validation_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int i; int length; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_server.c b/subsys/net/lib/lwm2m/lwm2m_obj_server.c index a7d3e541bbec4f..9c1dfc0ca1d6f5 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_server.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_server.c @@ -146,7 +146,7 @@ bool lwm2m_server_get_mute_send(uint16_t obj_inst_id) static int lifetime_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { ARG_UNUSED(obj_inst_id); ARG_UNUSED(res_id); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_swmgmt.c b/subsys/net/lib/lwm2m/lwm2m_obj_swmgmt.c index f1466be6c87e93..69dfd5c1f8cd3e 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_swmgmt.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_swmgmt.c @@ -187,9 +187,10 @@ static int callback_execute_not_defined(uint16_t obj_inst_id, uint8_t *args, uin return -EINVAL; } -static int callback_write_not_defined(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) +static int callback_write_not_defined(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { LOG_ERR("Callback not defined for inst %u", obj_inst_id); return -EINVAL; @@ -558,8 +559,10 @@ static int deactivate_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len) return handle_event(instance, EVENT_DEACTIVATE); } -static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, bool last_block, size_t total_size) +static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { int ret = -EINVAL; struct lwm2m_swmgmt_data *instance = NULL; @@ -643,9 +646,10 @@ static void set_update_result(uint16_t obj_inst_id, int error_code) } } -static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) +static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT int error_code; diff --git a/subsys/net/lib/lwm2m/lwm2m_pull_context.c b/subsys/net/lib/lwm2m/lwm2m_pull_context.c index e1eac08554ff56..c4c782d538f8df 100644 --- a/subsys/net/lib/lwm2m/lwm2m_pull_context.c +++ b/subsys/net/lib/lwm2m/lwm2m_pull_context.c @@ -303,6 +303,8 @@ static int do_firmware_transfer_reply_cb(const struct coap_packet *response, } if (context.write_cb) { + size_t offset = context.block_ctx.current; + /* flush incoming data to write_cb */ while (payload_len > 0) { len = (payload_len > write_buflen) ? write_buflen : payload_len; @@ -317,7 +319,8 @@ static int do_firmware_transfer_reply_cb(const struct coap_packet *response, ret = context.write_cb(context.obj_inst_id, 0, 0, write_buf, len, last_block && (payload_len == 0U), - context.block_ctx.total_size); + context.block_ctx.total_size, offset); + offset += len; if (ret < 0) { goto error; } diff --git a/subsys/net/lib/lwm2m/lwm2m_registry.c b/subsys/net/lib/lwm2m/lwm2m_registry.c index 3ead504bc94191..54bda0a0ca15af 100644 --- a/subsys/net/lib/lwm2m/lwm2m_registry.c +++ b/subsys/net/lib/lwm2m/lwm2m_registry.c @@ -668,7 +668,7 @@ static int lwm2m_engine_set(const struct lwm2m_obj_path *path, const void *value #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 if (res->validate_cb) { ret = res->validate_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id, - (uint8_t *)value, len, false, 0); + (uint8_t *)value, len, false, 0, 0); if (ret < 0) { k_mutex_unlock(®istry_lock); return -EINVAL; @@ -774,7 +774,7 @@ static int lwm2m_engine_set(const struct lwm2m_obj_path *path, const void *value if (res->post_write_cb) { ret = res->post_write_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id, - data_ptr, len, false, 0); + data_ptr, len, false, 0, 0); } if (changed && LWM2M_HAS_PERM(obj_field, LWM2M_PERM_R)) { diff --git a/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c b/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c index 4c193cfd50b389..b6178abb17f1df 100644 --- a/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c +++ b/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c @@ -23,10 +23,10 @@ static void *pre_write_cb(uint16_t obj_inst_id, return pre_write_cb_buf; } -static int post_write_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int post_write_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { callback_checker |= 0x02; return 0; @@ -41,10 +41,9 @@ static void *read_cb(uint16_t obj_inst_id, return 0; } -static int validate_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int validate_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, uint16_t data_len, + bool last_block, size_t total_size, size_t offset) { callback_checker |= 0x08; return 0; From 589fea0f556f07e6603494b894285791f23c5d90 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0719/1389] test: lwm2m: Add tests for Block-Wise transfers Block-Wise GET, PUT and SEND Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/Kconfig | 1 + subsys/net/lib/lwm2m/lwm2m_shell.c | 17 ++- tests/net/lib/lwm2m/interop/prj.conf | 15 +- tests/net/lib/lwm2m/interop/pytest/leshan.py | 4 + .../lwm2m/interop/pytest/test_blockwise.py | 133 ++++++++++++++++++ .../lib/lwm2m/interop/src/firmware_update.c | 80 +++++++++++ .../net/lib/lwm2m/interop/src/lwm2m-client.c | 14 ++ 7 files changed, 257 insertions(+), 7 deletions(-) create mode 100644 tests/net/lib/lwm2m/interop/pytest/test_blockwise.py create mode 100644 tests/net/lib/lwm2m/interop/src/firmware_update.c diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index d8e0b6fc61fb6f..4fdd7228f707cc 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -523,6 +523,7 @@ config LWM2M_SECONDS_TO_UPDATE_EARLY config LWM2M_SHELL bool "LwM2M shell utilities" select SHELL + select CRC help Activate shell module that provides LwM2M commands like send to the console. diff --git a/subsys/net/lib/lwm2m/lwm2m_shell.c b/subsys/net/lib/lwm2m/lwm2m_shell.c index 5f4d3e20269bfb..153423f6402a14 100644 --- a/subsys/net/lib/lwm2m/lwm2m_shell.c +++ b/subsys/net/lib/lwm2m/lwm2m_shell.c @@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #include +#include #include #include @@ -31,7 +32,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); "-uX\tRead value as uintX_t\n" \ "-sX\tRead value as intX_t\n" \ "-f \tRead value as float\n" \ - "-t \tRead value as time_t\n" + "-t \tRead value as time_t\n" \ + "-crc32\tCalculate CRC32 of the content\n" #define LWM2M_HELP_WRITE "write PATH [OPTIONS] VALUE\nWrite into LwM2M resource\n" \ "-s \tWrite value as string (default)\n" \ "-b \tWrite value as bool\n" \ @@ -180,6 +182,19 @@ static int cmd_read(const struct shell *sh, size_t argc, char **argv) goto out; } shell_hexdump(sh, buff, buff_len); + } else if (strcmp(dtype, "-crc32") == 0) { + const char *buff; + uint16_t buff_len = 0; + + ret = lwm2m_get_res_buf(&path, (void **)&buff, + NULL, &buff_len, NULL); + if (ret != 0) { + goto out; + } + + uint32_t crc = crc32_ieee(buff, buff_len); + + shell_print(sh, "%u", crc); } else if (strcmp(dtype, "-s") == 0) { const char *buff; uint16_t buff_len = 0; diff --git a/tests/net/lib/lwm2m/interop/prj.conf b/tests/net/lib/lwm2m/interop/prj.conf index 6115e6f40e389c..39d998db6f6f02 100644 --- a/tests/net/lib/lwm2m/interop/prj.conf +++ b/tests/net/lib/lwm2m/interop/prj.conf @@ -21,8 +21,11 @@ CONFIG_LWM2M_SHELL=y CONFIG_LWM2M_TICKLESS=y CONFIG_NET_SOCKETPAIR=y -#Enable Portfolio object +#Enable test objects CONFIG_LWM2M_PORTFOLIO_OBJ_SUPPORT=y +CONFIG_LWM2M_BINARYAPPDATA_OBJ_SUPPORT=y +CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT=y +CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT=y #LwM2M v1.1 configure CONFIG_LWM2M_VERSION_1_1=y @@ -36,7 +39,7 @@ CONFIG_LWM2M_RW_SENML_JSON_SUPPORT=y #Enable SenML CBOR content format CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT=y -CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=40 +CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=60 CONFIG_ZCBOR_CANONICAL=y #Enable legacy content formats @@ -90,11 +93,11 @@ CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID=y # MTU - IPv6 header - UDP header - DTLS header - CoAP header room # 1280 - 40 - 8 - 21 - 48 CONFIG_LWM2M_COAP_MAX_MSG_SIZE=1163 -CONFIG_LWM2M_COAP_BLOCK_SIZE=1024 +CONFIG_LWM2M_COAP_BLOCK_SIZE=512 CONFIG_LWM2M_COAP_BLOCK_TRANSFER=y -CONFIG_LWM2M_COAP_ENCODE_BUFFER_SIZE=4096 -CONFIG_LWM2M_NUM_OUTPUT_BLOCK_CONTEXT=1 -CONFIG_LWM2M_NUM_BLOCK1_CONTEXT=1 +CONFIG_LWM2M_COAP_ENCODE_BUFFER_SIZE=8192 +CONFIG_LWM2M_NUM_OUTPUT_BLOCK_CONTEXT=2 +CONFIG_LWM2M_NUM_BLOCK1_CONTEXT=2 CONFIG_SYS_HASH_FUNC32=y CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE=0 CONFIG_LWM2M_ENGINE_MAX_PENDING=2 diff --git a/tests/net/lib/lwm2m/interop/pytest/leshan.py b/tests/net/lib/lwm2m/interop/pytest/leshan.py index 181f15ebf6138e..198c3fc2880ed5 100644 --- a/tests/net/lib/lwm2m/interop/pytest/leshan.py +++ b/tests/net/lib/lwm2m/interop/pytest/leshan.py @@ -156,6 +156,8 @@ def _type_to_string(cls, value): return 'integer' if isinstance(value, datetime): return 'time' + if isinstance(value, bytes): + return 'opaque' return 'string' @classmethod @@ -163,6 +165,8 @@ def _convert_type(cls, value): """Wrapper for special types that are not understood by Json""" if isinstance(value, datetime): return int(value.timestamp()) + elif isinstance(value, bytes): + return binascii.b2a_hex(value).decode() else: return value diff --git a/tests/net/lib/lwm2m/interop/pytest/test_blockwise.py b/tests/net/lib/lwm2m/interop/pytest/test_blockwise.py new file mode 100644 index 00000000000000..27bece69f1e318 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/pytest/test_blockwise.py @@ -0,0 +1,133 @@ +""" +Tests for Block-Wise transfers in LwM2M +####################################### + +Copyright (c) 2024 Nordic Semiconductor ASA + +SPDX-License-Identifier: Apache-2.0 + + +""" + +import time +import logging +import zlib +import re +import random +import string +import binascii +from leshan import Leshan + +from twister_harness import Shell +from twister_harness import DeviceAdapter + +logger = logging.getLogger(__name__) + +def test_blockwise_1(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """Blockwise test 1: Block-Wise PUT using OPAQUE content format""" + + fw = b'1234567890' * 500 + fmt = leshan.format + to = leshan.timeout + leshan.format = 'OPAQUE' + leshan.timeout = 600 + leshan.write(endpoint, '5/0/0', fw) + # Our Firmware object prints out the CRC of the received firmware + # when Update is executed + leshan.execute(endpoint, '5/0/2') + lines = dut.readlines_until(regex='app_fw_update: UPDATE', timeout=5.0) + assert len(lines) > 0 + line = lines[-1] + crc = int(re.search('CRC ([0-9]+)', line).group(1)) + # Verify that CRC matches + assert crc == zlib.crc32(fw) + leshan.format = fmt + leshan.timeout = to + +def test_blockwise_2(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """Blockwise test 2: Block-Wise PUT with retry""" + + fw = b'1234567890' * 500 + fmt = leshan.format + to = leshan.timeout + leshan.format = 'OPAQUE' + # Set timeout to 1 second to force Leshan to stop sending + leshan.timeout = 1 + try: + leshan.write(endpoint, '5/0/0', fw) + except Exception as e: + logger.debug(f'Caught exception: {e}') + shell.exec_command('lwm2m update') + time.sleep(1) + # Now send the firmware again using longer timeout + leshan.timeout = 600 + leshan.write(endpoint, '5/0/0', fw) + # Our Firmware object prints out the CRC of the received firmware + # when Update is executed + leshan.execute(endpoint, '5/0/2') + lines = dut.readlines_until(regex='app_fw_update: UPDATE', timeout=5.0) + assert len(lines) > 0 + line = lines[-1] + crc = int(re.search('CRC ([0-9]+)', line).group(1)) + # Verify that CRC matches + assert crc == zlib.crc32(fw) + leshan.format = fmt + leshan.timeout = to + + +def test_blockwise_3(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """Blockwise test 3: Block-Wise Get using TLV and SenML-CBOR content formats""" + + shell.exec_command('lwm2m create /19/0') + + # Generate 4 kB of binary app-data + # and write it into BinaryAppData object + data = ''.join(random.choice(string.ascii_letters) for i in range(4096)).encode() + fmt = leshan.format + to = leshan.timeout + leshan.format = 'OPAQUE' + leshan.timeout = 600 + leshan.write(endpoint, '19/0/0/0', data) + + # Verify data is correctly transferred + lines = shell.get_filtered_output(shell.exec_command('lwm2m read /19/0/0/0 -crc32')) + crc = int(lines[0]) + assert crc == zlib.crc32(data) + + # Try reading the data using different content formats + for fmt in ['TLV', 'SENML_CBOR']: + leshan.format = fmt + data = leshan.read(endpoint, '19/0/0') + data = binascii.a2b_hex(data[0][0]) + assert crc == zlib.crc32(data) + + leshan.format = fmt + leshan.timeout = to + shell.exec_command('lwm2m delete /19/0') + +def test_blockwise_4(shell: Shell, dut: DeviceAdapter, leshan: Leshan, endpoint: str): + """Blockwise test 4: Block-Wise SEND using SenML-CBOR content format""" + + shell.exec_command('lwm2m create /19/0') + # Generate 4 kB of binary app-data + data = ''.join(random.choice(string.ascii_letters) for i in range(4096)).encode() + fmt = leshan.format + to = leshan.timeout + leshan.format = 'OPAQUE' + leshan.timeout = 600 + leshan.write(endpoint, '19/0/0/0', data) + leshan.format = 'SENML_CBOR' + + # Execute SEND and verify that correct data is received + with leshan.get_event_stream(endpoint) as events: + shell.exec_command('lwm2m send /19/0') + dut.readlines_until(regex=r'.*SEND status: 0', timeout=5.0) + send = events.next_event('SEND') + assert send is not None + content = binascii.a2b_hex(send[19][0][0][0]) + assert zlib.crc32(content) == zlib.crc32(data) + + leshan.format = fmt + leshan.timeout = to + + shell.exec_command('lwm2m delete /19/0') diff --git a/tests/net/lib/lwm2m/interop/src/firmware_update.c b/tests/net/lib/lwm2m/interop/src/firmware_update.c new file mode 100644 index 00000000000000..7ed44093dbd587 --- /dev/null +++ b/tests/net/lib/lwm2m/interop/src/firmware_update.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_MODULE_NAME app_fw_update +#define LOG_LEVEL LOG_LEVEL_DBG +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#include +#include +#include "lwm2m_engine.h" + +static uint8_t firmware_buf[64]; +static uint32_t crc; + +/* Array with supported PULL firmware update protocols */ +static uint8_t supported_protocol[1]; + +static int firmware_update_cb(uint16_t obj_inst_id, + uint8_t *args, uint16_t args_len) +{ + LOG_INF("UPDATE, (CRC %u)", crc); + + lwm2m_set_u8(&LWM2M_OBJ(5, 0, 3), STATE_IDLE); + lwm2m_set_u8(&LWM2M_OBJ(5, 0, 5), RESULT_SUCCESS); + return 0; +} + +static void *firmware_get_buf(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, size_t *data_len) +{ + *data_len = sizeof(firmware_buf); + return firmware_buf; +} + +static int firmware_block_received_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) +{ + if (offset == 0) { + crc = crc32_ieee(data, data_len); + } else { + crc = crc32_ieee_update(crc, data, data_len); + } + LOG_INF("FIRMWARE: BLOCK RECEIVED: offset:%zd len:%u last_block:%d crc: %u", + offset, data_len, last_block, crc); + + /* Add extra delay so short block-wise may timeout */ + k_sleep(K_MSEC(100)); + return 0; +} + +static int firmware_cancel_cb(const uint16_t obj_inst_id) +{ + LOG_INF("FIRMWARE: Update canceled"); + return 0; +} + +static int init_firmware_update(void) +{ + /* setup data buffer for block-wise transfer */ + lwm2m_register_pre_write_callback(&LWM2M_OBJ(5, 0, 0), firmware_get_buf); + lwm2m_firmware_set_write_cb(firmware_block_received_cb); + + /* register cancel callback */ + lwm2m_firmware_set_cancel_cb(firmware_cancel_cb); + lwm2m_firmware_set_update_cb(firmware_update_cb); + + lwm2m_create_res_inst(&LWM2M_OBJ(5, 0, 8, 0)); + lwm2m_set_res_buf(&LWM2M_OBJ(5, 0, 8, 0), &supported_protocol[0], + sizeof(supported_protocol[0]), + sizeof(supported_protocol[0]), 0); + + return 0; +} +LWM2M_APP_INIT(init_firmware_update); diff --git a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c index cb4ab22acd2379..bc668c15c3cea8 100644 --- a/tests/net/lib/lwm2m/interop/src/lwm2m-client.c +++ b/tests/net/lib/lwm2m/interop/src/lwm2m-client.c @@ -88,6 +88,18 @@ int set_socketoptions(struct lwm2m_ctx *ctx) return lwm2m_set_default_sockopt(ctx); } +static int create_appdata(uint16_t obj_inst_id) +{ + /* Create BinaryAppData object */ + static uint8_t data[4096]; + static char description[16]; + + lwm2m_set_res_buf(&LWM2M_OBJ(19, 0, 0, 0), data, sizeof(data), 0, 0); + lwm2m_set_res_buf(&LWM2M_OBJ(19, 0, 3), description, sizeof(description), 0, 0); + + return 0; +} + static int lwm2m_setup(void) { /* setup DEVICE object */ @@ -118,6 +130,8 @@ static int lwm2m_setup(void) lwm2m_create_res_inst(&LWM2M_OBJ(3, 0, 8, 1)); lwm2m_set_res_buf(&LWM2M_OBJ(3, 0, 8, 1), &usb_ma, sizeof(usb_ma), sizeof(usb_ma), 0); + lwm2m_register_create_callback(19, create_appdata); + return 0; } From 7c50faf9f85bc58e0cb50f921c7cea9ac3effebb Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0720/1389] net: lwm2m: Allow Block-Wise write without callbacks Allow Block-Wise writes to resources that have enough buffer for the whole content. Calculate the offset before calling the content specific write handlers when callback is not set. Previously only resources with post-write callback were able to assemble the content. Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 462ed32fafd6f1..f7e79dc40aa7a9 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -1031,6 +1031,7 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng bool last_block = true; void *write_buf; size_t write_buf_len; + size_t offset = 0; if (!obj_inst || !res || !res_inst || !obj_field || !msg) { return -EINVAL; @@ -1050,19 +1051,26 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng res_inst->res_inst_id, &data_len); } - if (res->post_write_cb -#if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 - || res->validate_cb -#endif - ) { - if (msg->in.block_ctx != NULL) { - /* Get block_ctx for total_size (might be zero) */ - total_size = msg->in.block_ctx->ctx.total_size; - LOG_DBG("BLOCK1: total:%zu current:%zu" - " last:%u", - msg->in.block_ctx->ctx.total_size, msg->in.block_ctx->ctx.current, - msg->in.block_ctx->last_block); + if (msg->in.block_ctx != NULL) { + /* Get block_ctx for total_size (might be zero) */ + total_size = msg->in.block_ctx->ctx.total_size; + offset = msg->in.block_ctx->ctx.current; + + LOG_DBG("BLOCK1: total:%zu current:%zu" + " last:%u", + msg->in.block_ctx->ctx.total_size, msg->in.block_ctx->ctx.current, + msg->in.block_ctx->last_block); + } + + /* Only when post_write callback is set, we allow larger content than our + * buffer sizes. The post-write callback handles assembling of the data + */ + if (!res->post_write_cb) { + if ((offset > 0 && offset >= data_len) || total_size > data_len) { + return -ENOMEM; } + data_len -= offset; + data_ptr = (uint8_t *)data_ptr + offset; } #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 @@ -1205,7 +1213,6 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, struct lwm2m_eng } if (obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) { - size_t offset = msg->in.block_ctx ? msg->in.block_ctx->ctx.current : 0; #if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 if (res->validate_cb) { From bcd3341d30668e5b79e7a04265063fbd7b9d86be Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0721/1389] test: lwm2m: Enable DTLS Connection ID Enable connection ID because it is on by default on the client example as well. Signed-off-by: Seppo Takalo --- tests/net/lib/lwm2m/interop/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/net/lib/lwm2m/interop/prj.conf b/tests/net/lib/lwm2m/interop/prj.conf index 39d998db6f6f02..e5de79a39d30fe 100644 --- a/tests/net/lib/lwm2m/interop/prj.conf +++ b/tests/net/lib/lwm2m/interop/prj.conf @@ -30,6 +30,7 @@ CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT=y #LwM2M v1.1 configure CONFIG_LWM2M_VERSION_1_1=y CONFIG_LWM2M_DTLS_SUPPORT=y +CONFIG_LWM2M_DTLS_CID=y CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP=y #Enable SenML JSON content format @@ -60,6 +61,7 @@ CONFIG_LWM2M_QUEUE_MODE_ENABLED=y CONFIG_LWM2M_QUEUE_MODE_UPTIME=20 CONFIG_LWM2M_UPDATE_PERIOD=30 CONFIG_LWM2M_RD_CLIENT_STOP_POLLING_AT_IDLE=y +CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=1 # LwM2M configuration as OMA-ETS-LightweightM2M_INT-V1_1-20190912-D Configuration 3 CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=30 @@ -68,6 +70,7 @@ CONFIG_LWM2M_SERVER_DEFAULT_PMAX=10 CONFIG_MBEDTLS=y CONFIG_MBEDTLS_TLS_VERSION_1_2=y +CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID=y # Special MbedTLS changes CONFIG_MBEDTLS_ENABLE_HEAP=y From 2b14ab299cc6221603c83f6744466d11d6f9269c Mon Sep 17 00:00:00 2001 From: John Johnson Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0722/1389] drivers: esp_at: make esp_pull_quoted() to only return -EAGAIN If no " character is found in buffer by esp_pull_quoted() it returns -EAGAIN which causes a loop that never ends. This is because the buffer dont get filled up with new data so no " chrachter will be found. This commit changes esp_pull_quoted() to only return -EAGAIN, so the buffer can get filled with new data and thus the loop can come to an end. Signed-off-by: John Johnson --- drivers/wifi/esp_at/esp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/wifi/esp_at/esp.c b/drivers/wifi/esp_at/esp.c index 2261a11f714a1c..ff32e3884efa26 100644 --- a/drivers/wifi/esp_at/esp.c +++ b/drivers/wifi/esp_at/esp.c @@ -256,7 +256,7 @@ MODEM_CMD_DEFINE(on_cmd_cipstamac) static int esp_pull_quoted(char **str, char *str_end, char **unquoted) { if (**str != '"') { - return -EBADMSG; + return -EAGAIN; } (*str)++; From c27ab4a9fb39b1ce348cb482d38e10917ed440ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0723/1389] kernel: docs: correct sys_heap_aligned_realloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit correct doc of sys_heap_aligned_realloc(). Signed-off-by: Fin Maaß --- include/zephyr/sys/sys_heap.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/zephyr/sys/sys_heap.h b/include/zephyr/sys/sys_heap.h index aa72793a2421e4..82f7202048e083 100644 --- a/include/zephyr/sys/sys_heap.h +++ b/include/zephyr/sys/sys_heap.h @@ -162,11 +162,6 @@ void sys_heap_free(struct sys_heap *heap, void *mem); * new block fails, then NULL will be returned and the old block will * not be freed or modified. * - * @note The return of a NULL on failure is a different behavior than - * POSIX realloc(), which specifies that the original pointer will be - * returned (i.e. it is not possible to safely detect realloc() - * failure in POSIX, but it is here). - * * @param heap Heap from which to allocate * @param ptr Original pointer returned from a previous allocation * @param align Alignment in bytes, must be a power of two From f9beb8e1e80a806c73039db393d0dcdd0b1af138 Mon Sep 17 00:00:00 2001 From: Armando Visconti Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0724/1389] drivers/sensor: lps25hb: Fix int32 overflow in the val2 part The val2 calculation was done using (1000000 / 40960) as multiplying factor, which was sometimes leading to a int32 overflow. So, let's use the equivalent (but smaller) (3125 / 128). Fix #46615 Signed-off-by: Armando Visconti --- drivers/sensor/st/lps25hb/lps25hb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/sensor/st/lps25hb/lps25hb.c b/drivers/sensor/st/lps25hb/lps25hb.c index 0ce9b8862a384c..38291b114719e3 100644 --- a/drivers/sensor/st/lps25hb/lps25hb.c +++ b/drivers/sensor/st/lps25hb/lps25hb.c @@ -69,9 +69,14 @@ static int lps25hb_sample_fetch(const struct device *dev, static inline void lps25hb_press_convert(struct sensor_value *val, int32_t raw_val) { - /* val = raw_val / 40960 */ + /* Pressure sensitivity is 4096 LSB/hPa */ + /* Also convert hPa into kPa */ val->val1 = raw_val / 40960; - val->val2 = ((int32_t)raw_val * 1000000 / 40960) % 1000000; + + /* For the decimal part use (3125 / 128) as a factor instead of + * (1000000 / 40960) to avoid int32 overflow + */ + val->val2 = (raw_val % 40960) * 3125 / 128; } static inline void lps25hb_temp_convert(struct sensor_value *val, From 613c95aebb4b63d2ac361920745367a18ed53572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:39:04 +0200 Subject: [PATCH 0725/1389] drivers: ethernet: eth_liteeth: add set_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add set_config to set the mac address. Signed-off-by: Fin Maaß --- drivers/ethernet/eth_liteeth.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/ethernet/eth_liteeth.c b/drivers/ethernet/eth_liteeth.c index 332ad5e657187a..5fc2780fdae96b 100644 --- a/drivers/ethernet/eth_liteeth.c +++ b/drivers/ethernet/eth_liteeth.c @@ -180,6 +180,25 @@ static void eth_irq_handler(const struct device *port) } } +static int eth_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config) +{ + struct eth_liteeth_dev_data *context = dev->data; + int ret = -ENOTSUP; + + switch (type) { + case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: + memcpy(context->mac_addr, config->mac_address.addr, sizeof(context->mac_addr)); + ret = net_if_set_link_addr(context->iface, context->mac_addr, + sizeof(context->mac_addr), NET_LINK_ETHERNET); + break; + default: + break; + } + + return ret; +} + #ifdef CONFIG_ETH_LITEETH_0 static struct eth_liteeth_dev_data eth_data = { @@ -247,6 +266,7 @@ static enum ethernet_hw_caps eth_caps(const struct device *dev) static const struct ethernet_api eth_api = { .iface_api.init = eth_iface_init, .get_capabilities = eth_caps, + .set_config = eth_set_config, .send = eth_tx }; From 5009d4b9eee17ddd822ba851817a92f8fd8ed10d Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0726/1389] samples: boards: nrf: nrfx_prs: extend regex to test default task Verifies that at least SPIM is initialized properly. Signed-off-by: Piotr Kosycarz --- samples/boards/nrf/nrfx_prs/sample.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/boards/nrf/nrfx_prs/sample.yaml b/samples/boards/nrf/nrfx_prs/sample.yaml index 149dd1724838e9..95c772d7d890d8 100644 --- a/samples/boards/nrf/nrfx_prs/sample.yaml +++ b/samples/boards/nrf/nrfx_prs/sample.yaml @@ -17,3 +17,8 @@ tests: - "nrfx PRS example on .*" - "-> press \".*\" to trigger a transfer" - "-> press \".*\" to switch the type of peripheral" + - "Switched to SPIM" + - "-- Background transfer on \".*\" --" + - "Tx: 4E 6F 72 64 69 63 20 53 65 6D 69 63 6F 6E 64 75 63 74 6F 72 00" + - "Rx:" + - "-- Background transfer on \".*\" --" From 3003c1cb46212033926cde55cbb311fc40ee373d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0727/1389] boards: nordic: nrf54h20dk: Add counter to the supported peripherals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable Twister tests for the counter driver for: - nrf54h20/cpuapp; - nrf54h20/cpurad. Signed-off-by: Sebastian Głąb --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 198f4db403b38a..2f83ef80de6102 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -12,6 +12,7 @@ toolchain: ram: 256 flash: 512 supported: + - counter - gpio - pwm - spi diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml index 53bbff4a460069..e36f2e21ffea6a 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml @@ -12,6 +12,7 @@ toolchain: ram: 192 flash: 256 supported: + - counter - gpio - pwm - spi From 9765b4ddc99c816dfa35843c04514c50e42b7d91 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0728/1389] drivers: gpio: Add support for Apollo3 SoCs GPIO This commit adds support for the GPIO which can be found in Apollo3 SoCs Signed-off-by: Hao Luo --- boards/ambiq/apollo3_evb/apollo3_evb.dts | 53 ++++ boards/ambiq/apollo3_evb/apollo3_evb.yaml | 1 + boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 57 +++++ boards/ambiq/apollo3p_evb/apollo3p_evb.yaml | 1 + drivers/gpio/gpio_ambiq.c | 263 ++++++++++++++++++-- dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 36 +++ dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 46 ++++ west.yml | 2 +- 8 files changed, 438 insertions(+), 21 deletions(-) diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index 78bba84b8524a5..97021e84f27176 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -19,6 +19,51 @@ aliases { watchdog0 = &wdt0; + led0 = &led0; + led1 = &led1; + led2 = &led2; + sw0 = &button0; + sw1 = &button1; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0_31 10 GPIO_ACTIVE_LOW>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpio0_31 30 GPIO_ACTIVE_LOW>; + label = "LED 1"; + }; + led2: led_2 { + gpios = <&gpio0_31 15 GPIO_ACTIVE_LOW>; + label = "LED 2"; + }; + led3: led_3 { + gpios = <&gpio0_31 14 GPIO_ACTIVE_LOW>; + label = "LED 3"; + }; + led4: led_4 { + gpios = <&gpio0_31 17 GPIO_ACTIVE_LOW>; + label = "LED 4"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0_31 16 GPIO_ACTIVE_LOW>; + label = "BTN0"; + }; + button1: button_1 { + gpios = <&gpio0_31 18 GPIO_ACTIVE_LOW>; + label = "BTN1"; + }; + button2: button_2 { + gpios = <&gpio0_31 19 GPIO_ACTIVE_LOW>; + label = "BTN2"; + }; }; }; @@ -45,3 +90,11 @@ pinctrl-names = "default"; status = "okay"; }; + +&gpio0_31 { + status = "okay"; +}; + +&gpio32_63 { + status = "okay"; +}; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.yaml b/boards/ambiq/apollo3_evb/apollo3_evb.yaml index c76500facc4553..1be99d9d92bdf7 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.yaml +++ b/boards/ambiq/apollo3_evb/apollo3_evb.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb supported: - uart + - gpio testing: ignore_tags: - net diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index 910fca95567f92..e510c52ad44b7b 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -19,6 +19,51 @@ aliases { watchdog0 = &wdt0; + led0 = &led0; + led1 = &led1; + led2 = &led2; + sw0 = &button0; + sw1 = &button1; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0_31 10 GPIO_ACTIVE_LOW>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpio0_31 30 GPIO_ACTIVE_LOW>; + label = "LED 1"; + }; + led2: led_2 { + gpios = <&gpio0_31 15 GPIO_ACTIVE_LOW>; + label = "LED 2"; + }; + led3: led_3 { + gpios = <&gpio0_31 14 GPIO_ACTIVE_LOW>; + label = "LED 3"; + }; + led4: led_4 { + gpios = <&gpio0_31 17 GPIO_ACTIVE_LOW>; + label = "LED 4"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0_31 16 GPIO_ACTIVE_LOW>; + label = "BTN0"; + }; + button1: button_1 { + gpios = <&gpio0_31 18 GPIO_ACTIVE_LOW>; + label = "BTN1"; + }; + button2: button_2 { + gpios = <&gpio0_31 19 GPIO_ACTIVE_LOW>; + label = "BTN2"; + }; }; }; @@ -45,3 +90,15 @@ pinctrl-names = "default"; status = "okay"; }; + +&gpio0_31 { + status = "okay"; +}; + +&gpio32_63 { + status = "okay"; +}; + +&gpio64_95 { + status = "okay"; +}; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml index db00dbedcd647b..fe17883861b225 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb supported: - uart + - gpio testing: ignore_tags: - net diff --git a/drivers/gpio/gpio_ambiq.c b/drivers/gpio/gpio_ambiq.c index e264a4096d8ce8..0c0f1db458c523 100644 --- a/drivers/gpio/gpio_ambiq.c +++ b/drivers/gpio/gpio_ambiq.c @@ -37,6 +37,41 @@ static int ambiq_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gp { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + pin += dev_cfg->offset; + + am_hal_gpio_pincfg_t pincfg = g_AM_HAL_GPIO_DEFAULT; + + if (flags & GPIO_INPUT) { + pincfg = g_AM_HAL_GPIO_INPUT; + if (flags & GPIO_PULL_UP) { + pincfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K; + } else if (flags & GPIO_PULL_DOWN) { + pincfg.ePullup = AM_HAL_GPIO_PIN_PULLDOWN; + } + } + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_SINGLE_ENDED) { + if (flags & GPIO_LINE_OPEN_DRAIN) { + pincfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN; + } + } else { + pincfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL; + } + } + if (flags & GPIO_DISCONNECTED) { + pincfg = g_AM_HAL_GPIO_DEFAULT; + } + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + pincfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH; + am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET); + + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + pincfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW; + am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR); + } +#else pin += (dev_cfg->offset >> 2); am_hal_gpio_pincfg_t pincfg = am_hal_gpio_pincfg_default; @@ -70,7 +105,7 @@ static int ambiq_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gp pincfg.GP.cfg_b.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW; am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR); } - +#endif am_hal_gpio_pinconfig(pin, pincfg); return 0; @@ -82,6 +117,40 @@ static int ambiq_gpio_get_config(const struct device *dev, gpio_pin_t pin, gpio_ const struct ambiq_gpio_config *const dev_cfg = dev->config; am_hal_gpio_pincfg_t pincfg; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + pin += dev_cfg->offset; + + am_hal_gpio_pinconfig_get(pin, &pincfg); + + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_DISABLE && + pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_NONE) { + *out_flags = GPIO_DISCONNECTED; + } + if (pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) { + *out_flags = GPIO_INPUT; + if (pincfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_1_5K) { + *out_flags |= GPIO_PULL_UP; + } else if (pincfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN) { + *out_flags |= GPIO_PULL_DOWN; + } + } + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) { + *out_flags = GPIO_OUTPUT | GPIO_PUSH_PULL; + if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) { + *out_flags |= GPIO_OUTPUT_HIGH; + } else if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) { + *out_flags |= GPIO_OUTPUT_LOW; + } + } + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) { + *out_flags = GPIO_OUTPUT | GPIO_OPEN_DRAIN; + if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) { + *out_flags |= GPIO_OUTPUT_HIGH; + } else if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) { + *out_flags |= GPIO_OUTPUT_LOW; + } + } +#else pin += (dev_cfg->offset >> 2); am_hal_gpio_pinconfig_get(pin, &pincfg); @@ -114,7 +183,7 @@ static int ambiq_gpio_get_config(const struct device *dev, gpio_pin_t pin, gpio_ *out_flags |= GPIO_OUTPUT_LOW; } } - +#endif return 0; } #endif @@ -127,6 +196,33 @@ static int ambiq_gpio_port_get_direction(const struct device *dev, gpio_port_pin am_hal_gpio_pincfg_t pincfg; gpio_port_pins_t ip = 0; gpio_port_pins_t op = 0; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; + + if (inputs != NULL) { + for (int i = 0; i < dev_cfg->ngpios; i++) { + if ((map >> i) & 1) { + am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg); + if (pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) { + ip |= BIT(i); + } + } + } + *inputs = ip; + } + if (outputs != NULL) { + for (int i = 0; i < dev_cfg->ngpios; i++) { + if ((map >> i) & 1) { + am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg); + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL || + pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) { + op |= BIT(i); + } + } + } + *outputs = op; + } +#else uint32_t pin_offset = dev_cfg->offset >> 2; if (inputs != NULL) { @@ -152,7 +248,7 @@ static int ambiq_gpio_port_get_direction(const struct device *dev, gpio_port_pin } *outputs = op; } - +#endif return 0; } #endif @@ -161,8 +257,11 @@ static int ambiq_gpio_port_get_raw(const struct device *dev, gpio_port_value_t * { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + *value = (*AM_HAL_GPIO_RDn(dev_cfg->offset)); +#else *value = (*AM_HAL_GPIO_RDn(dev_cfg->offset >> 2)); - +#endif return 0; } @@ -170,8 +269,11 @@ static int ambiq_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pi gpio_port_value_t value) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; - +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((mask >> i) & 1) { am_hal_gpio_state_write(i + pin_offset, ((value >> i) & 1)); @@ -184,7 +286,11 @@ static int ambiq_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pi static int ambiq_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((pins >> i) & 1) { @@ -198,7 +304,11 @@ static int ambiq_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins static int ambiq_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((pins >> i) & 1) { @@ -212,7 +322,11 @@ static int ambiq_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pi static int ambiq_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((pins >> i) & 1) { @@ -223,17 +337,49 @@ static int ambiq_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_ return 0; } +#define APOLLO3_HANDLE_SHARED_GPIO_IRQ(n) \ + static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \ + const struct ambiq_gpio_config *cfg_##n = dev_##n->config; \ + struct ambiq_gpio_data *const data_##n = dev_##n->data; \ + uint32_t status_##n = (uint32_t)(ui64Status >> cfg_##n->offset); \ + if (status_##n) { \ + gpio_fire_callbacks(&data_##n->cb, dev_##n, status_##n); \ + } + +#define APOLLO3P_HANDLE_SHARED_GPIO_IRQ(n) \ + static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \ + struct ambiq_gpio_data *const data_##n = dev_##n->data; \ + if (pGpioIntStatusMask->U.Msk[n]) { \ + gpio_fire_callbacks(&data_##n->cb, dev_##n, pGpioIntStatusMask->U.Msk[n]); \ + } + static void ambiq_gpio_isr(const struct device *dev) { +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + ARG_UNUSED(dev); + +#if defined(CONFIG_SOC_APOLLO3_BLUE) + uint64_t ui64Status; + + am_hal_gpio_interrupt_status_get(false, &ui64Status); + am_hal_gpio_interrupt_clear(ui64Status); + DT_INST_FOREACH_STATUS_OKAY(APOLLO3_HANDLE_SHARED_GPIO_IRQ) +#elif defined(CONFIG_SOC_APOLLO3P_BLUE) + AM_HAL_GPIO_MASKCREATE(GpioIntStatusMask); + am_hal_gpio_interrupt_status_get(false, pGpioIntStatusMask); + am_hal_gpio_interrupt_clear(pGpioIntStatusMask); + DT_INST_FOREACH_STATUS_OKAY(APOLLO3P_HANDLE_SHARED_GPIO_IRQ) +#endif +#else + uint32_t int_status; struct ambiq_gpio_data *const data = dev->data; const struct ambiq_gpio_config *const dev_cfg = dev->config; - uint32_t int_status; - am_hal_gpio_interrupt_irq_status_get(dev_cfg->irq_num, false, &int_status); am_hal_gpio_interrupt_irq_clear(dev_cfg->irq_num, int_status); gpio_fire_callbacks(&data->cb, dev, int_status); +#endif } static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, @@ -242,10 +388,57 @@ static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin const struct ambiq_gpio_config *const dev_cfg = dev->config; struct ambiq_gpio_data *const data = dev->data; - am_hal_gpio_pincfg_t pincfg; + int ret; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_gpio_pincfg_t pincfg = g_AM_HAL_GPIO_DEFAULT; + int gpio_pin = pin + dev_cfg->offset; + + ret = am_hal_gpio_pinconfig_get(gpio_pin, &pincfg); + + if (mode == GPIO_INT_MODE_DISABLED) { + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE; + ret = am_hal_gpio_pinconfig(gpio_pin, pincfg); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + AM_HAL_GPIO_MASKCREATE(GpioIntMask); + ret = am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + ret = am_hal_gpio_interrupt_disable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + k_spin_unlock(&data->lock, key); + + } else { + if (mode == GPIO_INT_MODE_LEVEL) { + return -ENOTSUP; + } + switch (trig) { + case GPIO_INT_TRIG_LOW: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_HI2LO; + break; + case GPIO_INT_TRIG_HIGH: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI; + break; + case GPIO_INT_TRIG_BOTH: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_BOTH; + break; + default: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE; + break; + } + ret = am_hal_gpio_pinconfig(gpio_pin, pincfg); + + irq_enable(dev_cfg->irq_num); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + AM_HAL_GPIO_MASKCREATE(GpioIntMask); + ret = am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + ret = am_hal_gpio_interrupt_enable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + k_spin_unlock(&data->lock, key); + } +#else + am_hal_gpio_pincfg_t pincfg = am_hal_gpio_pincfg_default; int gpio_pin = pin + (dev_cfg->offset >> 2); uint32_t int_status; - int ret; ret = am_hal_gpio_pinconfig_get(gpio_pin, &pincfg); @@ -295,6 +488,7 @@ static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin (void *)&gpio_pin); k_spin_unlock(&data->lock, key); } +#endif return ret; } @@ -306,14 +500,36 @@ static int ambiq_gpio_manage_callback(const struct device *dev, struct gpio_call return gpio_manage_callback(&data->cb, callback, set); } +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +static void ambiq_gpio_cfg_func(void) +{ + /* Apollo3 GPIO banks share the same irq number, connect to bank0 once when init and handle + * different banks in ambiq_gpio_isr + */ + static bool global_irq_init = true; + + if (!global_irq_init) { + return; + } + + global_irq_init = false; + + /* Shared irq config default to BANK0. */ + IRQ_CONNECT(GPIO_IRQn, DT_INST_IRQ(0, priority), ambiq_gpio_isr, DEVICE_DT_INST_GET(0), 0); +} +#endif + static int ambiq_gpio_init(const struct device *port) { const struct ambiq_gpio_config *const dev_cfg = port->config; NVIC_ClearPendingIRQ(dev_cfg->irq_num); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + ambiq_gpio_cfg_func(); +#else dev_cfg->cfg_func(); - +#endif return 0; } @@ -334,10 +550,25 @@ static const struct gpio_driver_api ambiq_gpio_drv_api = { #endif }; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +/* Apollo3 GPIO banks share the same irq number, connect irq here will cause build error, so we + * leave this function blank here and do it in ambiq_gpio_cfg_func + */ +#define AMBIQ_GPIO_CONFIG_FUNC(n) static void ambiq_gpio_cfg_func_##n(void){}; +#else +#define AMBIQ_GPIO_CONFIG_FUNC(n) \ + static void ambiq_gpio_cfg_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), ambiq_gpio_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + return; \ + }; +#endif + #define AMBIQ_GPIO_DEFINE(n) \ static struct ambiq_gpio_data ambiq_gpio_data_##n; \ static void ambiq_gpio_cfg_func_##n(void); \ - \ static const struct ambiq_gpio_config ambiq_gpio_config_##n = { \ .common = \ { \ @@ -348,15 +579,7 @@ static const struct gpio_driver_api ambiq_gpio_drv_api = { .ngpios = DT_INST_PROP(n, ngpios), \ .irq_num = DT_INST_IRQN(n), \ .cfg_func = ambiq_gpio_cfg_func_##n}; \ - static void ambiq_gpio_cfg_func_##n(void) \ - { \ - \ - IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), ambiq_gpio_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - \ - return; \ - }; \ - \ + AMBIQ_GPIO_CONFIG_FUNC(n) \ DEVICE_DT_INST_DEFINE(n, &ambiq_gpio_init, NULL, &ambiq_gpio_data_##n, \ &ambiq_gpio_config_##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ &ambiq_gpio_drv_api); diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index f863ee14ba81c6..5ae40c06790a24 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -162,6 +162,42 @@ pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo3-pinctrl"; reg = <0x40010000 0x800>; + #address-cells = <1>; + #size-cells = <0>; + + gpio: gpio@40010000 { + compatible = "ambiq,gpio"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0_31 0x0 0x0 + 0x20 0x0 &gpio32_63 0x0 0x0 + >; + reg = <0x40010000>; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; + ranges; + + gpio0_31: gpio0_31@0 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + interrupts = <13 0>; + status = "disabled"; + }; + + gpio32_63: gpio32_63@20 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + interrupts = <13 0>; + status = "disabled"; + ngpios = <18>; + }; + }; }; wdt0: watchdog@40024000 { diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index 988e5b48a7fa0e..ac53b55883e2d6 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -182,6 +182,52 @@ pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo3-pinctrl"; reg = <0x40010000 0x800>; + #address-cells = <1>; + #size-cells = <0>; + + gpio: gpio@40010000 { + compatible = "ambiq,gpio"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0_31 0x0 0x0 + 0x20 0x0 &gpio32_63 0x0 0x0 + 0x40 0x0 &gpio64_95 0x0 0x0 + >; + reg = <0x40010000>; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; + ranges; + + gpio0_31: gpio0_31@0 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + interrupts = <13 0>; + status = "disabled"; + }; + + gpio32_63: gpio32_63@20 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + interrupts = <13 0>; + status = "disabled"; + }; + + gpio64_95: gpio64_95@40 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40>; + interrupts = <13 0>; + status = "disabled"; + ngpios = <10>; + }; + }; }; wdt0: watchdog@40024000 { diff --git a/west.yml b/west.yml index 0beadf4237d144..40a896f65bc5a2 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: f6858cb3fe3d44945a23d114b7feeeac22ce71cf + revision: 94dd874cd726ba8185a301e78337c5c39685123f path: modules/hal/ambiq groups: - hal From 0f7013cfac1a0c11cd5fff74d7853de899523319 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0729/1389] drivers: entropy: smartbond: Add support for PM This commit should add all the functionality needed for the entropy driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios --- .../renesas/da1469x_dk_pro/Kconfig.defconfig | 7 +- drivers/entropy/entropy_smartbond.c | 64 ++++++++++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig index 34b4913118160f..d487e093a080ff 100644 --- a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig +++ b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig @@ -34,13 +34,18 @@ config LV_Z_POINTER_INPUT_MSGQ_COUNT endif # INPUT -#if PM || PM_DEVICE +#if PM || PM_DEVICE || PM_DEVICE_RUNTIME # Increase stack size to avoid raising usage-fault # exceptions due to stack overflow. config IDLE_STACK_SIZE default 2048 +# Make sure the serial device has higher +# initialization priority. +config SERIAL_INIT_PRIORITY + default KERNEL_INIT_PRIORITY_DEFAULT + #endif # PM || PM_DEVICE endif # BOARD_DA1469X_DK_PRO diff --git a/drivers/entropy/entropy_smartbond.c b/drivers/entropy/entropy_smartbond.c index 28b6f08e100bfb..0b42f77f4f8fc8 100644 --- a/drivers/entropy/entropy_smartbond.c +++ b/drivers/entropy/entropy_smartbond.c @@ -10,6 +10,11 @@ #include #include #include +#include +#include + +#include +LOG_MODULE_REGISTER(smartbond_entropy, CONFIG_ENTROPY_LOG_LEVEL); #define DT_DRV_COMPAT renesas_smartbond_trng @@ -334,6 +339,51 @@ static int entropy_smartbond_get_entropy_isr(const struct device *dev, uint8_t * return cnt; } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +/* + * TRNG is powered by PD_SYS which is the same power domain used to power the SoC. + * Entering the sleep state should not be allowed for as long as the ISR and thread + * SW FIFOs are being filled with random numbers. + */ +static inline bool entropy_is_sleep_allowed(void) +{ + return !(TRNG->TRNG_CTRL_REG & TRNG_TRNG_CTRL_REG_TRNG_ENABLE_Msk); +} + +static int entropy_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + /* Initialize with an error code that should abort sleeping */ + int ret = -EBUSY; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + __ASSERT_NO_MSG(entropy_is_sleep_allowed()); + + /* + * No need to turn on TRNG. It should be done when we the space in the FIFOs + * are below the defined ISR and thread FIFO's thresholds. + * + * \sa CONFIG_ENTROPY_SMARTBOND_THR_THRESHOLD + * \sa CONFIG_ENTROPY_SMARTBOND_ISR_THRESHOLD + * + */ + ret = 0; + break; + case PM_DEVICE_ACTION_SUSPEND: + /* Sleep is only allowed when there is no TRNG activity */ + if (entropy_is_sleep_allowed()) { + /* At this point TRNG should be disabled; no need to turn it off. */ + ret = 0; + } + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif + static const struct entropy_driver_api entropy_smartbond_api_funcs = { .get_entropy = entropy_smartbond_get_entropy, .get_entropy_isr = entropy_smartbond_get_entropy_isr}; @@ -361,8 +411,18 @@ static int entropy_smartbond_init(const struct device *dev) trng_enable(true); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#endif + return 0; } -DEVICE_DT_INST_DEFINE(0, entropy_smartbond_init, NULL, &entropy_smartbond_data, NULL, PRE_KERNEL_1, - CONFIG_ENTROPY_INIT_PRIORITY, &entropy_smartbond_api_funcs); +PM_DEVICE_DT_INST_DEFINE(0, entropy_smartbond_pm_action); + +DEVICE_DT_INST_DEFINE(0, entropy_smartbond_init, PM_DEVICE_DT_INST_GET(0), + &entropy_smartbond_data, NULL, PRE_KERNEL_1, + CONFIG_ENTROPY_INIT_PRIORITY, &entropy_smartbond_api_funcs); From 8e7cf74b68f45eb42a0f5ab089aedc63e5187147 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0730/1389] boards: phytec: Remove Messtechnik GmbH PHYTEC has multiple offices in different locations like the US, France, India and China. The headquarter is located in Germany. Since now 50% of the PHYTEC boards are from the US office, we should drop 'Messtechnik GmbH', which is the offical title of the German office, and keep the name more general. Signed-off-by: Daniel Schultz --- boards/phytec/index.rst | 4 ++-- dts/bindings/vendor-prefixes.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/boards/phytec/index.rst b/boards/phytec/index.rst index 0bde22965df24c..bb484358db1840 100644 --- a/boards/phytec/index.rst +++ b/boards/phytec/index.rst @@ -1,7 +1,7 @@ .. _boards-phytec: -PHYTEC Messtechnik GmbH -####################### +PHYTEC +###### .. toctree:: :maxdepth: 1 diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 21920433fc7f15..93970fd70a79a4 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -497,7 +497,7 @@ pda Precision Design Associates, Inc. pericom Pericom Technology Inc. pervasive Pervasive Displays, Inc. phicomm PHICOMM Co., Ltd. -phytec PHYTEC Messtechnik GmbH +phytec PHYTEC picochip Picochip Ltd pine64 Pine64 pineriver Shenzhen PineRiver Designs Co., Ltd. From f154c0621010e4d8d80fd167322db97caf58f709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0731/1389] drivers: adc: Update adc driver to support nRF54L15 device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expands driver to cover nRF54L15 features like AIN as GPIO configuration, new reference voltage, different set of supported gain options. Signed-off-by: Karol Lasończyk --- drivers/adc/adc_nrfx_saadc.c | 189 ++++++++++++++++++++++++++++------- 1 file changed, 153 insertions(+), 36 deletions(-) diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 6d1973ca0aae9c..e5e658c893aee6 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -6,7 +6,7 @@ #define ADC_CONTEXT_USES_KERNEL_TIMER #include "adc_context.h" -#include +#include #include #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL @@ -16,6 +16,20 @@ LOG_MODULE_REGISTER(adc_nrfx_saadc); #define DT_DRV_COMPAT nordic_nrf_saadc +#if (NRF_SAADC_HAS_AIN_AS_PIN) + +static const uint8_t saadc_psels[NRF_SAADC_AIN7 + 1] = { + [NRF_SAADC_AIN0] = NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + [NRF_SAADC_AIN1] = NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + [NRF_SAADC_AIN2] = NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + [NRF_SAADC_AIN3] = NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), + [NRF_SAADC_AIN4] = NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1), + [NRF_SAADC_AIN5] = NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), + [NRF_SAADC_AIN6] = NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1), + [NRF_SAADC_AIN7] = NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1), +}; + +#else BUILD_ASSERT((NRF_SAADC_AIN0 == NRF_SAADC_INPUT_AIN0) && (NRF_SAADC_AIN1 == NRF_SAADC_INPUT_AIN1) && (NRF_SAADC_AIN2 == NRF_SAADC_INPUT_AIN2) && @@ -28,8 +42,12 @@ BUILD_ASSERT((NRF_SAADC_AIN0 == NRF_SAADC_INPUT_AIN0) && #if defined(SAADC_CH_PSELP_PSELP_VDDHDIV5) (NRF_SAADC_VDDHDIV5 == NRF_SAADC_INPUT_VDDHDIV5) && #endif - (NRF_SAADC_VDD == NRF_SAADC_INPUT_VDD), +#if defined(SAADC_CH_PSELP_PSELP_VDD) + (NRF_SAADC_VDD == NRF_SAADC_INPUT_VDD) && +#endif + 1, "Definitions from nrf-adc.h do not match those from nrf_saadc.h"); +#endif struct driver_data { struct adc_context ctx; @@ -43,85 +61,158 @@ static struct driver_data m_data = { ADC_CONTEXT_INIT_SYNC(m_data, ctx), }; +/* Helper function to convert number of samples to the byte representation. */ +static uint32_t samples_to_bytes(const struct adc_sequence *sequence, uint16_t number_of_samples) +{ + if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8 && sequence->resolution == 8) { + return number_of_samples; + } + + return number_of_samples * 2; +} + +/* Helper function to convert acquisition time to register TACQ value. */ +static int adc_convert_acq_time(uint16_t acquisition_time, nrf_saadc_acqtime_t *p_tacq_val) +{ + int result = 0; + +#if NRF_SAADC_HAS_ACQTIME_ENUM + switch (acquisition_time) { + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 3): + *p_tacq_val = NRF_SAADC_ACQTIME_3US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 5): + *p_tacq_val = NRF_SAADC_ACQTIME_5US; + break; + case ADC_ACQ_TIME_DEFAULT: + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10): + *p_tacq_val = NRF_SAADC_ACQTIME_10US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 15): + *p_tacq_val = NRF_SAADC_ACQTIME_15US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 20): + *p_tacq_val = NRF_SAADC_ACQTIME_20US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40): + *p_tacq_val = NRF_SAADC_ACQTIME_40US; + break; + default: + result = -EINVAL; + } +#else +#define MINIMUM_ACQ_TIME_IN_NS 125 +#define DEFAULT_ACQ_TIME_IN_NS 10000 + + nrf_saadc_acqtime_t tacq = 0; + uint16_t acq_time = + (acquisition_time == ADC_ACQ_TIME_DEFAULT + ? DEFAULT_ACQ_TIME_IN_NS + : (ADC_ACQ_TIME_VALUE(acquisition_time) * + (ADC_ACQ_TIME_UNIT(acquisition_time) == ADC_ACQ_TIME_MICROSECONDS + ? 1000 + : 1))); + + tacq = (nrf_saadc_acqtime_t)(acq_time / MINIMUM_ACQ_TIME_IN_NS) - 1; + if ((tacq > NRF_SAADC_ACQTIME_MAX) || (acq_time < MINIMUM_ACQ_TIME_IN_NS)) { + result = -EINVAL; + } else { + *p_tacq_val = tacq; + } +#endif + + return result; +} /* Implementation of the ADC driver API function: adc_channel_setup. */ static int adc_nrfx_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { nrf_saadc_channel_config_t config = { - .resistor_p = NRF_SAADC_RESISTOR_DISABLED, - .resistor_n = NRF_SAADC_RESISTOR_DISABLED, - .burst = NRF_SAADC_BURST_DISABLED, +#if NRF_SAADC_HAS_CH_CONFIG_RES + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, +#endif + .burst = NRF_SAADC_BURST_DISABLED, }; uint8_t channel_id = channel_cfg->channel_id; + uint32_t input_negative = channel_cfg->input_negative; if (channel_id >= SAADC_CH_NUM) { return -EINVAL; } switch (channel_cfg->gain) { +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_6) case ADC_GAIN_1_6: config.gain = NRF_SAADC_GAIN1_6; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_5) case ADC_GAIN_1_5: config.gain = NRF_SAADC_GAIN1_5; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_4) case ADC_GAIN_1_4: config.gain = NRF_SAADC_GAIN1_4; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_3) case ADC_GAIN_1_3: config.gain = NRF_SAADC_GAIN1_3; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_2) case ADC_GAIN_1_2: config.gain = NRF_SAADC_GAIN1_2; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain2_3) + case ADC_GAIN_2_3: + config.gain = NRF_SAADC_GAIN2_3; + break; +#endif case ADC_GAIN_1: config.gain = NRF_SAADC_GAIN1; break; case ADC_GAIN_2: config.gain = NRF_SAADC_GAIN2; break; +#if defined(SAADC_CH_CONFIG_GAIN_Gain4) case ADC_GAIN_4: config.gain = NRF_SAADC_GAIN4; break; +#endif default: LOG_ERR("Selected ADC gain is not valid"); return -EINVAL; } switch (channel_cfg->reference) { +#if defined(SAADC_CH_CONFIG_REFSEL_Internal) case ADC_REF_INTERNAL: config.reference = NRF_SAADC_REFERENCE_INTERNAL; break; +#endif +#if defined(SAADC_CH_CONFIG_REFSEL_VDD1_4) case ADC_REF_VDD_1_4: config.reference = NRF_SAADC_REFERENCE_VDD4; break; +#endif +#if defined(SAADC_CH_CONFIG_REFSEL_External) + case ADC_REF_EXTERNAL0: + config.reference = NRF_SAADC_REFERENCE_EXTERNAL; + break; +#endif default: LOG_ERR("Selected ADC reference is not valid"); return -EINVAL; } - switch (channel_cfg->acquisition_time) { - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 3): - config.acq_time = NRF_SAADC_ACQTIME_3US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 5): - config.acq_time = NRF_SAADC_ACQTIME_5US; - break; - case ADC_ACQ_TIME_DEFAULT: - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10): - config.acq_time = NRF_SAADC_ACQTIME_10US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 15): - config.acq_time = NRF_SAADC_ACQTIME_15US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 20): - config.acq_time = NRF_SAADC_ACQTIME_20US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40): - config.acq_time = NRF_SAADC_ACQTIME_40US; - break; - default: + int ret = adc_convert_acq_time(channel_cfg->acquisition_time, &config.acq_time); + + if (ret) { LOG_ERR("Selected ADC acquisition time is not valid"); return -EINVAL; } @@ -134,17 +225,37 @@ static int adc_nrfx_channel_setup(const struct device *dev, * in a sampling sequence. */ - nrf_saadc_channel_init(NRF_SAADC, channel_id, &config); - nrf_saadc_channel_input_set(NRF_SAADC, - channel_id, - NRF_SAADC_INPUT_DISABLED, - channel_cfg->input_negative); +#if (NRF_SAADC_HAS_AIN_AS_PIN) + if ((channel_cfg->input_positive > NRF_SAADC_AIN7) || + (channel_cfg->input_positive < NRF_SAADC_AIN0)) { + return -EINVAL; + } + + if (config.mode == NRF_SAADC_MODE_DIFFERENTIAL) { + if (input_negative > NRF_SAADC_AIN7 || + input_negative < NRF_SAADC_AIN0) { + return -EINVAL; + } + + input_negative = saadc_psels[input_negative]; + } else { + input_negative = NRF_SAADC_INPUT_DISABLED; + } /* Store the positive input selection in a dedicated array, * to get it later when the channel is selected for a sampling * and to mark the channel as configured (ready to be selected). */ + m_data.positive_inputs[channel_id] = saadc_psels[channel_cfg->input_positive]; +#else m_data.positive_inputs[channel_id] = channel_cfg->input_positive; +#endif + + nrf_saadc_channel_init(NRF_SAADC, channel_id, &config); + nrf_saadc_channel_input_set(NRF_SAADC, + channel_id, + NRF_SAADC_INPUT_DISABLED, + input_negative); return 0; } @@ -168,10 +279,11 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, ARG_UNUSED(ctx); if (!repeat) { - nrf_saadc_buffer_pointer_set( - NRF_SAADC, - (uint16_t *)nrf_saadc_buffer_pointer_get(NRF_SAADC) + - nrf_saadc_amount_get(NRF_SAADC)); + nrf_saadc_value_t *buffer = + (uint8_t *)nrf_saadc_buffer_pointer_get(NRF_SAADC) + + samples_to_bytes(&ctx->sequence, nrfy_saadc_amount_get(NRF_SAADC)); + + nrfy_saadc_buffer_pointer_set(NRF_SAADC, buffer); } } @@ -256,7 +368,8 @@ static int check_buffer_size(const struct adc_sequence *sequence, { size_t needed_buffer_size; - needed_buffer_size = active_channels * sizeof(uint16_t); + needed_buffer_size = samples_to_bytes(sequence, active_channels); + if (sequence->options) { needed_buffer_size *= (1 + sequence->options->extra_samplings); } @@ -429,7 +542,11 @@ static const struct adc_driver_api adc_nrfx_driver_api = { #ifdef CONFIG_ADC_ASYNC .read_async = adc_nrfx_read_async, #endif +#if defined(CONFIG_SOC_NRF54L15) + .ref_internal = 900, +#else .ref_internal = 600, +#endif }; /* From 73811db32d5f058fd324a8685606ad0a6448c980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0732/1389] boards: Enable ADC in nRF54L15 PDK configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simple enabling adc node. Signed-off-by: Karol Lasończyk --- boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts index 159bb224258c85..24b15763bdc8f6 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts @@ -148,3 +148,7 @@ t-exit-dpd = <35000>; }; }; + +&adc { + status = "okay"; +}; From f9ad0e0a7436c20ea83569a99d8b1ec294bf3efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0733/1389] samples: adc: Add overlay for nRF54L15 PDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New file with ADC configuration for nRF54L15 PDK. Signed-off-by: Karol Lasończyk --- .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 45 ++++++++++++++++ .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 51 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay create mode 100644 samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..f185624f9b933f --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.11 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.13 */ + zephyr,input-negative = ; /* P1.14 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..a0639a405c4050 --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + }; +}; + +/ { + aliases { + adc0 = &adc; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.11 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.13 */ + zephyr,input-negative = ; /* P1.14 */ + zephyr,resolution = <12>; + }; +}; From a4d6f8d8545179b37f3e62db5557d9744cdd0774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0734/1389] tests: adc: Add overlay for nRF54L15 PDK for adc_api test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New file to make test works. Signed-off-by: Karol Lasończyk --- .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/drivers/adc/adc_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/tests/drivers/adc/adc_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/tests/drivers/adc/adc_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..e10ddc5432828e --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 2>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; +}; From e3b89340b5bd3b818b7855d5a9a68e3ed28b2f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0735/1389] boards: nordic: Add ADC to supported in nRF54L15 PDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expand supported list. Signed-off-by: Karol Lasończyk --- boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml index 057c3b3f390bb9..fd563bc6c1e31e 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml @@ -12,6 +12,7 @@ toolchain: ram: 188 flash: 324 supported: + - adc - counter - gpio - i2c From 1dbefe6cc4c683469a8a38750296ecf8a0c6bbe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0736/1389] drivers: watchdog: wdt_nrfx.c: Unistall timeouts in wdt_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to API description, wdt_disable() shall automatically uninstall all timeouts. https://docs.zephyrproject.org/latest/hardware/peripherals/watchdog.html Implement missing wdt_disable() functionality: - disable WDT RR channels; - remove callback from timeout channels; - set data->m_allocated_channels to zero. Signed-off-by: Sebastian Głąb --- drivers/watchdog/wdt_nrfx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/watchdog/wdt_nrfx.c b/drivers/watchdog/wdt_nrfx.c index 706c2621bbb630..1c23c9452b41af 100644 --- a/drivers/watchdog/wdt_nrfx.c +++ b/drivers/watchdog/wdt_nrfx.c @@ -60,7 +60,9 @@ static int wdt_nrf_disable(const struct device *dev) { #if NRFX_WDT_HAS_STOP const struct wdt_nrfx_config *config = dev->config; + struct wdt_nrfx_data *data = dev->data; nrfx_err_t err_code; + int channel_id; err_code = nrfx_wdt_stop(&config->wdt); @@ -69,6 +71,13 @@ static int wdt_nrf_disable(const struct device *dev) return -EFAULT; } + nrfx_wdt_channels_free(&config->wdt); + + for (channel_id = 0; channel_id < data->m_allocated_channels; channel_id++) { + data->m_callbacks[channel_id] = NULL; + } + data->m_allocated_channels = 0; + return 0; #else ARG_UNUSED(dev); From 48ed0dd316ea3bbecffc5a1157cad079d06f3348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0737/1389] tests: drivers: watchdog: wdt_error_cases: Add test scenario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test scenario that verifies correct error code returned by wdt_setup() when called just after wdt_disable(). Scenario: - configure WDT timeout; - start WDT by calling wdt_setup(); - remove all WDT timeouts by calling wdt_disable(); - confirm wdt_setup() returns error code due to lack of configured WDT timeouts. Signed-off-by: Sebastian Głąb --- .../watchdog/wdt_error_cases/src/main.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/drivers/watchdog/wdt_error_cases/src/main.c b/tests/drivers/watchdog/wdt_error_cases/src/main.c index 65569ad30a4319..b16daccb2e37e3 100644 --- a/tests/drivers/watchdog/wdt_error_cases/src/main.c +++ b/tests/drivers/watchdog/wdt_error_cases/src/main.c @@ -776,6 +776,48 @@ ZTEST(wdt_coverage, test_08d_wdt_disable_check_timeouts_uninstalled) zassert_equal(m_test_08d_B_value, 0, "Timeout B has fired while it shouldn't"); } +/** + * @brief Test error code when wdt_setup() is called after wdt_disable() + * + * Confirm that wdt_setup() returns error value or ASSERTION FAIL + * when it's called before any timeout was configured with wdt_install_timeouts(). + * All timeouts were uninstalled by calling wdt_disable(). + * + */ +ZTEST(wdt_coverage, test_08e_wdt_setup_immediately_after_wdt_disable) +{ + int ret; + + if (!(WDT_TEST_FLAGS & WDT_DISABLE_SUPPORTED)) { + /* Skip this test because wdt_disable() is NOT supported. */ + ztest_test_skip(); + } + + m_cfg_wdt0.callback = NULL; + m_cfg_wdt0.flags = DEFAULT_FLAGS; + m_cfg_wdt0.window.max = DEFAULT_WINDOW_MAX; + m_cfg_wdt0.window.min = DEFAULT_WINDOW_MIN; + + ret = wdt_install_timeout(wdt, &m_cfg_wdt0); + zassert_true(ret >= 0, "Watchdog install error, got unexpected value of %d", ret); + TC_PRINT("Configured WDT channel %d\n", ret); + + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret == 0, "Watchdog setup error, got unexpected value of %d", ret); + + ret = wdt_disable(wdt); + zassert_true(ret == 0, "Watchdog disable error, got unexpected value of %d", ret); + + /* Call wdt_setup when no timeouts are configured. */ + /* Timeouts were removed by calling wdt_disable(). */ + ztest_set_assert_valid(true); + ret = wdt_setup(wdt, DEFAULT_OPTIONS); + zassert_true(ret < 0, + "Calling wdt_setup before installing timeouts should fail, got unexpected " + "value of %d", + ret); +} + /** * @brief wdt_feed() negative test * From b57c2b37acaf464cf8cb6ea2cf9d33e0b777bd12 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0738/1389] MAINTAINERS: Synopsys: remove IRISZZW Remove IRISZZW from collaborators as he no longer works for Synopsys Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- MAINTAINERS.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 77f9820f681b61..9825f700e2b624 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3150,7 +3150,6 @@ Synopsys Platforms: collaborators: - abrodkin - evgeniy-paltsev - - IRISZZW files: - soc/snps/ - boards/snps/ From 086895be0dcc351d1e827d5d8445b70143c6a951 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0739/1389] MAINTAINERS: Synopsys: add mdb & nsim west runners Add mdb & nsim west runners files as parts of Synopsys platform Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- MAINTAINERS.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 9825f700e2b624..c31f7b35956f3f 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3154,6 +3154,9 @@ Synopsys Platforms: - soc/snps/ - boards/snps/ - samples/boards/arc_secure_services/ + - scripts/west_commands/runners/mdb.py + - scripts/west_commands/tests/test_mdb.py + - scripts/west_commands/runners/nsim.py labels: - "platform: Synopsys" From 839458dc98d6da67592e5442547d086ef75be99a Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:05 +0200 Subject: [PATCH 0740/1389] MAINTAINERS: Synopsys: add nsim cmake support file Add nsim cmake support file as parts of Synopsys platform Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index c31f7b35956f3f..2d464460eb59c3 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3157,6 +3157,7 @@ Synopsys Platforms: - scripts/west_commands/runners/mdb.py - scripts/west_commands/tests/test_mdb.py - scripts/west_commands/runners/nsim.py + - cmake/emu/nsim.cmake labels: - "platform: Synopsys" From c2e82f3315541ed2b1f6b72757a8e7a87e6d4793 Mon Sep 17 00:00:00 2001 From: Mykola Kvach Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0741/1389] drivers: regulator: fixed warning during build in gpio regulator Fix warning in gpio regulator: "declaration of 'ret' shadows a previous local". Signed-off-by: Mykola Kvach --- drivers/regulator/regulator_gpio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/regulator/regulator_gpio.c b/drivers/regulator/regulator_gpio.c index 49d373897b38eb..d888a5fd6dcc46 100644 --- a/drivers/regulator/regulator_gpio.c +++ b/drivers/regulator/regulator_gpio.c @@ -167,8 +167,6 @@ static int regulator_gpio_init(const struct device *dev) regulator_common_data_init(dev); for (unsigned int gpio_idx = 0; gpio_idx < cfg->num_gpios; gpio_idx++) { - int ret; - if (!gpio_is_ready_dt(&cfg->gpios[gpio_idx])) { LOG_ERR("%s: gpio pin: %s not ready", dev->name, cfg->gpios[gpio_idx].port ? cfg->gpios[gpio_idx].port->name From 84fd76c986e477caeaf699b47dcddc1a642487e1 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0742/1389] net: zperf: Fix upload ping timeout error Fixes remote address for ping before upload. This caused the ping in zperf upload to timeout as shown in the following output: ``` uart:~$ zperf udp upload 2001:db8::2 5001 10 50 1M Remote port is 5001 Connecting to 2001:db8::2 Duration: 10.00 s Packet size: 50 bytes Rate: 1000 kbps Starting... ping 2001:db8::2 timeout Rate: 1.00 Mbps Packet duration 390 us ``` Fixes: https://github.com/zephyrproject-rtos/zephyr/issues/68674 Signed-off-by: Ayush Singh --- subsys/net/lib/zperf/zperf_shell.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index 1b97bdde7b92c9..97d9e1e9140842 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -685,7 +685,8 @@ static void send_ping(const struct shell *sh, return; } - memcpy(&dest_addr.sin6_addr, addr, sizeof(struct in6_addr)); + dest_addr.sin6_family = AF_INET6; + net_ipv6_addr_copy_raw((uint8_t *)&dest_addr.sin6_addr, (uint8_t *)addr); k_sem_init(&sem_wait, 0, 1); From 916311c2b7e7e1319b9bdef237579d699e2d2126 Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0743/1389] scripts: twister: Fix Unit Tests on Windows systems Unit tests currently are not runnable on Windows systems, failing on two testfiles: test_jobserver.py and test_testsuite.py. This commit removes code dependency on Windows-unavailable elements on Windows systems via skipping the offending tests. Signed-off-by: Lukasz Mrugala --- scripts/tests/twister/test_jobserver.py | 14 ++++---- scripts/tests/twister/test_testsuite.py | 43 +++++++++++++++++-------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/scripts/tests/twister/test_jobserver.py b/scripts/tests/twister/test_jobserver.py index c97e93204479b2..554df8545fb2e0 100644 --- a/scripts/tests/twister/test_jobserver.py +++ b/scripts/tests/twister/test_jobserver.py @@ -14,15 +14,13 @@ from contextlib import nullcontext from errno import ENOENT -from fcntl import F_GETFL from selectors import EVENT_READ -from twisterlib.jobserver import ( - JobHandle, - JobClient, - GNUMakeJobClient, - GNUMakeJobServer -) +# Job server only works on Linux for now. +pytestmark = pytest.mark.skipif(sys.platform != 'linux', reason='JobServer only works on Linux.') +if sys.platform == 'linux': + from twisterlib.jobserver import GNUMakeJobClient, GNUMakeJobServer, JobClient, JobHandle + from fcntl import F_GETFL def test_jobhandle(capfd): @@ -96,7 +94,6 @@ def test_jobclient_popen(kwargs, expected_kwargs): (True, 16), ] - @pytest.mark.parametrize( 'inheritable, internal_jobs', TESTDATA_2, @@ -283,6 +280,7 @@ def mock_fcntl(fd, flag): **expected_kwargs) + def test_gnumakejobclient_get_job(): inherit_read_fd = mock.Mock() inherit_write_fd = mock.Mock() diff --git a/scripts/tests/twister/test_testsuite.py b/scripts/tests/twister/test_testsuite.py index 74402561fc1905..565fa9dadd848a 100644 --- a/scripts/tests/twister/test_testsuite.py +++ b/scripts/tests/twister/test_testsuite.py @@ -213,26 +213,41 @@ def test_scan_file(test_data, test_file, class_env, expected: ScanPathResult): assert result == expected -TESTDATA_3 = [ - ( - 'nt', - {'access': mmap.ACCESS_READ} - ), - ( - 'posix', - { - 'flags': mmap.MAP_PRIVATE, - 'prot': mmap.PROT_READ, - 'offset': 0 - } +# Generate testcases depending on available mmap attributes +TESTIDS_3 = [] +TESTDATA_3 = [] + +try: + TESTDATA_3.append( + ( + 'nt', + {'access': mmap.ACCESS_READ} + ) ) -] + TESTIDS_3.append('windows') +except AttributeError: + pass + +try: + TESTDATA_3.append( + ( + 'posix', + { + 'flags': mmap.MAP_PRIVATE, + 'prot': mmap.PROT_READ, + 'offset': 0 + } + ) + ) + TESTIDS_3.append('linux') +except AttributeError: + pass @pytest.mark.parametrize( 'os_name, expected', TESTDATA_3, - ids=['windows', 'linux'] + ids=TESTIDS_3 ) def test_scan_file_mmap(os_name, expected): class TestException(Exception): From eb99b78ef8eed5af05a32f69c566344c693a8ea7 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0744/1389] boards: st: remove "- sdhc" tag from supported list SDHC twister tag indicates that the board supports an SD host controller driver. Since the ST SDMMC support is provided directly via a disk driver, SDHC tests are not supported on ST boards. Drop this tag in order to avoid twister failures running the SDHC tests on these platforms. Signed-off-by: Daniel DeGrasse --- boards/olimex/olimexino_stm32/olimexino_stm32.yaml | 1 - boards/st/stm32f746g_disco/stm32f746g_disco.yaml | 1 - boards/st/stm32f7508_dk/stm32f7508_dk.yaml | 1 - boards/st/stm32h573i_dk/stm32h573i_dk.yaml | 1 - boards/st/stm32l496g_disco/stm32l496g_disco.yaml | 1 - boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml | 1 - boards/st/stm32l562e_dk/stm32l562e_dk.yaml | 1 - boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml | 1 - boards/weact/mini_stm32h743/mini_stm32h743.yaml | 1 - 9 files changed, 9 deletions(-) diff --git a/boards/olimex/olimexino_stm32/olimexino_stm32.yaml b/boards/olimex/olimexino_stm32/olimexino_stm32.yaml index b4cf8b26bfbf1d..266ff002184975 100644 --- a/boards/olimex/olimexino_stm32/olimexino_stm32.yaml +++ b/boards/olimex/olimexino_stm32/olimexino_stm32.yaml @@ -11,7 +11,6 @@ supported: - gpio - i2c - pwm - - sdhc - spi - usb_device - watchdog diff --git a/boards/st/stm32f746g_disco/stm32f746g_disco.yaml b/boards/st/stm32f746g_disco/stm32f746g_disco.yaml index f3ef45a79062e9..5442db5bb67373 100644 --- a/boards/st/stm32f746g_disco/stm32f746g_disco.yaml +++ b/boards/st/stm32f746g_disco/stm32f746g_disco.yaml @@ -16,7 +16,6 @@ supported: - gpio - pwm - counter - - sdhc - usb_device - display - memc diff --git a/boards/st/stm32f7508_dk/stm32f7508_dk.yaml b/boards/st/stm32f7508_dk/stm32f7508_dk.yaml index b474319510dda8..9415c4660d1c77 100644 --- a/boards/st/stm32f7508_dk/stm32f7508_dk.yaml +++ b/boards/st/stm32f7508_dk/stm32f7508_dk.yaml @@ -19,7 +19,6 @@ supported: - gpio - pwm - counter - - sdhc - usb_device - display - memc diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.yaml b/boards/st/stm32h573i_dk/stm32h573i_dk.yaml index b2b3ae93b79a0d..f6d5f12b173306 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.yaml +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.yaml @@ -24,6 +24,5 @@ supported: - usb_device - usb - i2c - - sdhc - rtc vendor: st diff --git a/boards/st/stm32l496g_disco/stm32l496g_disco.yaml b/boards/st/stm32l496g_disco/stm32l496g_disco.yaml index 3544d15980c3b2..15301e002c7177 100644 --- a/boards/st/stm32l496g_disco/stm32l496g_disco.yaml +++ b/boards/st/stm32l496g_disco/stm32l496g_disco.yaml @@ -15,7 +15,6 @@ supported: - spi - gpio - counter - - sdhc - adc - qspi vendor: st diff --git a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml index 89ab98c92b108c..81d844caf75df3 100644 --- a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml +++ b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml @@ -18,7 +18,6 @@ supported: - i2c - pwm - rtc - - sdhc - spi - uart - usb diff --git a/boards/st/stm32l562e_dk/stm32l562e_dk.yaml b/boards/st/stm32l562e_dk/stm32l562e_dk.yaml index dcbe7539d6482d..c2acb4cb09823e 100644 --- a/boards/st/stm32l562e_dk/stm32l562e_dk.yaml +++ b/boards/st/stm32l562e_dk/stm32l562e_dk.yaml @@ -19,7 +19,6 @@ supported: - dma - usart - arduino_spi - - sdhc - usb - usb_device - nvs diff --git a/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml b/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml index c092f8da95d82e..50d239c805bebe 100644 --- a/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml +++ b/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml @@ -13,7 +13,6 @@ supported: - dac - spi - arduino_spi - - sdhc - usb - usb_device ram: 192 diff --git a/boards/weact/mini_stm32h743/mini_stm32h743.yaml b/boards/weact/mini_stm32h743/mini_stm32h743.yaml index 0ce1024b6d08bc..b92c045ee2359f 100644 --- a/boards/weact/mini_stm32h743/mini_stm32h743.yaml +++ b/boards/weact/mini_stm32h743/mini_stm32h743.yaml @@ -15,6 +15,5 @@ supported: - backup_sram - watchdog - usb - - sdhc - qspi vendor: weact From 36cc8d0f71469acde61070aa57ec34b5d558a2e1 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0745/1389] test: drivers: disk: disk_access: add STM32 specific testcase STM32 devices with an SDMMC driver will still need to be tested, but they do not use the SDHC framework for their disk driver. Therefore, add a special testcase to validate disk access support for devices with the STM32 specific SDMMC DT compatible enabled. Signed-off-by: Daniel DeGrasse --- tests/drivers/disk/disk_access/testcase.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/drivers/disk/disk_access/testcase.yaml b/tests/drivers/disk/disk_access/testcase.yaml index 5ee0c79e915003..9fc566158bc282 100644 --- a/tests/drivers/disk/disk_access/testcase.yaml +++ b/tests/drivers/disk/disk_access/testcase.yaml @@ -34,3 +34,5 @@ tests: platform_allow: - native_sim/native/64 - native_sim + drivers.disk.stm32_sdhc: + filter: dt_compat_enabled("st,stm32-sdmmc") From 491d1d58c9f8cf8263e74e93f7f40eac3baeeb47 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0746/1389] drivers: regulator/nxp_vref: Fixed incorrect input parameter Fixed incorrect parameter passed in function linear_range_get_value. Signed-off-by: Zhaoxiang Jin --- drivers/regulator/regulator_nxp_vref.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/regulator_nxp_vref.c b/drivers/regulator/regulator_nxp_vref.c index 3d2ba23010e316..e15488e7210783 100644 --- a/drivers/regulator/regulator_nxp_vref.c +++ b/drivers/regulator/regulator_nxp_vref.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * SPDX-License-Identifier: Apache-2.0 */ @@ -165,7 +165,7 @@ static int regulator_nxp_vref_get_voltage(const struct device *dev, /* Linear range index is the register value */ idx = (base->UTRIM & VREF_UTRIM_TRIM2V1_MASK) >> VREF_UTRIM_TRIM2V1_SHIFT; - ret = linear_range_get_value(&utrim_range, base->UTRIM, volt_uv); + ret = linear_range_get_value(&utrim_range, idx, volt_uv); return ret; } From 1961aa9233364d5d97900498b9820468b6c19935 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0747/1389] drivers: regulator/nxp_vref: Remove nxp_ground_select property Remove nxp_ground_select property. Delete the use of NXP vref peripheral CSR register REFL_GRL_SEL bit. Signed-off-by: Zhaoxiang Jin --- drivers/regulator/regulator_nxp_vref.c | 8 -------- dts/bindings/regulator/nxp,vref.yaml | 8 +------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/regulator/regulator_nxp_vref.c b/drivers/regulator/regulator_nxp_vref.c index e15488e7210783..d3aa0f48a15247 100644 --- a/drivers/regulator/regulator_nxp_vref.c +++ b/drivers/regulator/regulator_nxp_vref.c @@ -24,7 +24,6 @@ struct regulator_nxp_vref_data { struct regulator_nxp_vref_config { struct regulator_common_config common; VREF_Type *base; - uint8_t gnd_sel; uint16_t buf_start_delay; uint16_t bg_start_time; }; @@ -183,16 +182,10 @@ static const struct regulator_driver_api api = { static int regulator_nxp_vref_init(const struct device *dev) { - const struct regulator_nxp_vref_config *config = dev->config; - VREF_Type *base = config->base; int ret; regulator_common_data_init(dev); - /* Select ground */ - base->CSR &= ~VREF_CSR_REFL_GRD_SEL_MASK; - base->CSR |= config->gnd_sel; - ret = regulator_nxp_vref_disable(dev); if (ret < 0) { return ret; @@ -207,7 +200,6 @@ static int regulator_nxp_vref_init(const struct device *dev) static const struct regulator_nxp_vref_config config_##inst = { \ .common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst), \ .base = (VREF_Type *) DT_INST_REG_ADDR(inst), \ - .gnd_sel = DT_INST_ENUM_IDX_OR(inst, nxp_ground_select, 0), \ .buf_start_delay = DT_INST_PROP(inst, \ nxp_buffer_startup_delay_us), \ .bg_start_time = DT_INST_PROP(inst, \ diff --git a/dts/bindings/regulator/nxp,vref.yaml b/dts/bindings/regulator/nxp,vref.yaml index e3466ad29d5e07..8d5acb1f2bc251 100644 --- a/dts/bindings/regulator/nxp,vref.yaml +++ b/dts/bindings/regulator/nxp,vref.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP VREF SOC peripheral @@ -20,12 +20,6 @@ properties: reg: required: true - nxp,ground-select: - type: string - enum: - - "VREFL3V" # 0 - - "VSSA" # 1 - nxp,buffer-startup-delay-us: type: int required: true From 3a2f7c82944e4af884eda44d228a8f5dd5611fa6 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0748/1389] docs: releases/migration-guide-3.7: Add NXP regulator driver info Add NXP regulator (nxp,vref) driver info Signed-off-by: Zhaoxiang Jin --- doc/releases/migration-guide-3.7.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 8eaed64cb5e0b2..0ba7d361c03288 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -278,6 +278,14 @@ Serial Timer ===== +regulator +========= + +* The :dtcompatible:`nxp,vref` driver no longer supports the ground selection function, + as this setting should not be modified by the user. The DT property ``nxp,ground-select`` + has been removed, users should remove this property from their devicetree if it is present. + (:github:`70642`) + Bluetooth ********* From d504d1e7f18e3ef85fe769ca66e14d6ca3f061ea Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0749/1389] drivers: adc: Support regulator output as reference to LPADC Support regulator output different voltage as reference to LPADC the regulator output voltage can be set through property zephyr,vref-mv Signed-off-by: Zhaoxiang Jin --- drivers/adc/adc_mcux_lpadc.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/adc/adc_mcux_lpadc.c b/drivers/adc/adc_mcux_lpadc.c index 1f47328496f7ce..02c6e7ac648eed 100644 --- a/drivers/adc/adc_mcux_lpadc.c +++ b/drivers/adc/adc_mcux_lpadc.c @@ -122,10 +122,15 @@ static int mcux_lpadc_acquisition_time_setup(const struct device *dev, uint16_t static int mcux_lpadc_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { + const struct mcux_lpadc_config *config = dev->config; + const struct device **regulator = config->ref_supplies; + uint16_t vref_mv = CONTAINER_OF(channel_cfg, struct adc_dt_spec, channel_cfg)->vref_mv; + int32_t vref_uv = (int32_t)((uint32_t)vref_mv * 1000); struct mcux_lpadc_data *data = dev->data; lpadc_conv_command_config_t *cmd; uint8_t channel_side; uint8_t channel_num; + int err; /* User may configure maximum number of active channels */ if (channel_cfg->channel_id >= CONFIG_LPADC_CHANNEL_COUNT) { @@ -200,8 +205,25 @@ static int mcux_lpadc_channel_setup(const struct device *dev, } #endif - if (channel_cfg->reference != ADC_REF_EXTERNAL0) { - LOG_ERR("Invalid channel reference"); + /* + * ADC_REF_EXTERNAL1: Use SoC internal regulator as LPADC reference voltage. + * ADC_REF_EXTERNAL0: Use other voltage source (maybe also within the SoCs) + * as LPADC reference voltage, like VREFH, VDDA, etc. + */ + if (channel_cfg->reference == ADC_REF_EXTERNAL1) { + LOG_DBG("ref external1"); + if (*regulator != NULL) { + err = regulator_set_voltage(*regulator, vref_uv, vref_uv); + if (err < 0) { + return err; + } + } else { + return -EINVAL; + } + } else if (channel_cfg->reference == ADC_REF_EXTERNAL0) { + LOG_DBG("ref external0"); + } else { + LOG_DBG("ref not support"); return -EINVAL; } From a6a75e00149bf54a937b7ab10d2dbc056231db99 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0750/1389] dts: arm/nxp/mcxn94x: Add vref node for NXP MCXN94x Add the vref node for NXP MCXN94x Signed-off-by: Zhaoxiang Jin --- dts/arm/nxp/nxp_mcxn94x_common.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index 2410a6377c792a..fc125774e62efe 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -796,6 +796,17 @@ max-bus-freq = <52000000>; min-bus-freq = <400000>; }; + + vref: vref@111000 { + compatible = "nxp,vref"; + regulator-name = "mcxn94x-vref"; + reg = <0x111000 0x14>; + status = "disabled"; + nxp,buffer-startup-delay-us = <400>; + nxp,bandgap-startup-time-us = <20>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2100000>; + }; }; &systick { From ad176800a6248c22d56cee5a0ca1a1dd83ef79b8 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0751/1389] dts: arm/nxp/mcxn94x: Add lpadc nodes for NXP mcxn94x Add lpadc nodes for NXP mcxn94x Signed-off-by: Zhaoxiang Jin --- dts/arm/nxp/nxp_mcxn94x_common.dtsi | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index fc125774e62efe..890e7d007dfd86 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -807,6 +807,39 @@ regulator-min-microvolt = <1000000>; regulator-max-microvolt = <2100000>; }; + + lpadc0: lpadc@10d000 { + compatible = "nxp,lpc-lpadc"; + reg = <0x10d000 0x1000>; + interrupts = <45 0>; + status = "disabled"; + clk-divider = <1>; + clk-source = <0>; + voltage-ref= <1>; + calibration-average = <128>; + power-level = <0>; + offset-value-a = <0>; + offset-value-b = <0>; + #io-channel-cells = <1>; + clocks = <&syscon MCUX_LPADC1_CLK>; + nxp,reference-supply = <&vref>; + }; + + lpadc1: lpadc@10e000 { + compatible = "nxp,lpc-lpadc"; + reg = <0x10e000 0x1000>; + interrupts = <46 0>; + status = "disabled"; + clk-divider = <1>; + clk-source = <0>; + voltage-ref= <0>; + calibration-average = <128>; + power-level = <1>; + offset-value-a = <0>; + offset-value-b = <0>; + #io-channel-cells = <1>; + clocks = <&syscon MCUX_LPADC2_CLK>; + }; }; &systick { From 41996f70ea861ac7874130e023b835b597ae7009 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0752/1389] boards: nxp/frdm_mcxn947: Support vref for NXP frdm_mcxn947 Support vref for NXP frdm_mcxn947 Signed-off-by: Zhaoxiang Jin --- boards/nxp/frdm_mcxn947/board.c | 5 +++++ boards/nxp/frdm_mcxn947/doc/index.rst | 2 ++ boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts | 4 ++++ boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml | 1 + 4 files changed, 12 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index 0481fafddf55e2..d8ed68f6d7ce14 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -205,6 +205,11 @@ static int frdm_mcxn947_init(void) flexspi_clock_set_freq(MCUX_FLEXSPI_CLK, MHZ(50)); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(vref), okay) + CLOCK_EnableClock(kCLOCK_Vref); + SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; diff --git a/boards/nxp/frdm_mcxn947/doc/index.rst b/boards/nxp/frdm_mcxn947/doc/index.rst index 9dd884e07283c3..5fd4904e5bb714 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -84,6 +84,8 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | USDHC | on-chip | sdhc | +-----------+------------+-------------------------------------+ +| VREF | on-chip | REGULATOR | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts index 462edb3332bc37..52d9bf8c0bb4b5 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -153,3 +153,7 @@ status = "okay"; }; }; + +&vref { + status = "okay"; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml index a1c2b1c2da1287..2f4ed54a7c72cd 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml @@ -24,4 +24,5 @@ supported: - pwm - counter - sdhc + - regulator vendor: nxp From dcdcf6b91657ffc1a8f40d306f026e2ccb3572aa Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0753/1389] boards: nxp/frdm_mcxn947: Support lpadc for NXP frdm_mcxn947 Support lpadc for NXP frdm_mcxn947 Signed-off-by: Zhaoxiang Jin --- boards/nxp/frdm_mcxn947/board.c | 5 +++++ boards/nxp/frdm_mcxn947/doc/index.rst | 2 ++ boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi | 9 +++++++++ boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi | 5 +++++ boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts | 4 ++++ boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml | 1 + 6 files changed, 26 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index d8ed68f6d7ce14..b79265127b3c96 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -210,6 +210,11 @@ static int frdm_mcxn947_init(void) SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpadc0), okay) + CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1U); + CLOCK_AttachClk(kFRO_HF_to_ADC0); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; diff --git a/boards/nxp/frdm_mcxn947/doc/index.rst b/boards/nxp/frdm_mcxn947/doc/index.rst index 5fd4904e5bb714..b04849a61dc25e 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -86,6 +86,8 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | VREF | on-chip | REGULATOR | +-----------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi index 4d3e9771382985..8bdc9e1c91fe75 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi @@ -148,4 +148,13 @@ input-enable; }; }; + pinmux_lpadc0: pinmux_lpadc0 { + group0 { + pinmux = , + , + ; + slew-rate = "fast"; + drive-strength = "low"; + }; + }; }; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi index 0634ddcae56ffa..e928f64ab33bc3 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi @@ -183,3 +183,8 @@ pinctrl-names = "default", "slow", "med"; no-1-8-v; }; + +&lpadc0 { + pinctrl-0 = <&pinmux_lpadc0>; + pinctrl-names = "default"; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts index 52d9bf8c0bb4b5..338e8e520ae7c8 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -157,3 +157,7 @@ &vref { status = "okay"; }; + +&lpadc0 { + status = "okay"; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml index 2f4ed54a7c72cd..10127d1a6693cf 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml @@ -25,4 +25,5 @@ supported: - counter - sdhc - regulator + - adc vendor: nxp From 07bcd3b6e92342a572c764890d6bae91d1593ea4 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0754/1389] samples: drivers/adc: Support adc example for NXP frdm_mcxn947 Support adc example for NXP frdm_mcxn947 Signed-off-by: Zhaoxiang Jin --- .../boards/frdm_mcxn947_mcxn947_cpu0.overlay | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay diff --git a/samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay new file mode 100644 index 00000000000000..051e3c1a3a47f3 --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -0,0 +1,50 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&lpadc0 0>, <&lpadc0 1>; + }; +}; + +&lpadc0 { + #address-cells = <1>; + #size-cells = <0>; + + /* + * To use this sample: + * LPADC0 CH1A and CH1B are set up in differential mode (B-A) + * - Connect LPADC0 CH1A signal to voltage between 0~1.8V (J8 pin 20) + * - Connect LPADC0 CH1B signal to voltage between 0~1.8V (J8 pin 24) + * LPADC0 CH2A is set up in single ended mode + * - Connect LPADC0 CH2A signal to voltage between 0~1.8V (J8 pin 28) + */ + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <13>; + zephyr,input-positive = ; + zephyr,input-negative = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; +}; From 36f1165bd9f1918e6767e52d6952aa6bede52ed4 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0755/1389] tests: drivers/adc/adc_api: Support adc api test for NXP frdm_mcxn947 Support adc api test for NXP frdm_mcxn947 Signed-off-by: Zhaoxiang Jin --- .../boards/frdm_mcxn947_mcxn947_cpu0.overlay | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/drivers/adc/adc_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay diff --git a/tests/drivers/adc/adc_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/tests/drivers/adc/adc_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay new file mode 100644 index 00000000000000..99d447efc68ab3 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -0,0 +1,36 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + zephyr,user { + io-channels = <&lpadc0 0>, <&lpadc0 1>; + }; +}; + +&lpadc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; +}; From 7546297036cf376debc47c47733a8afa19f03463 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0756/1389] tests: drivers/regulator/voltage: Add regulator test for NXP frdm_mcxn947 Support regulator(vref) output vt oltage test for NXP frdm_mcxn947 Signed-off-by: Zhaoxiang Jin --- .../boards/frdm_mcxn947_mcxn947_cpu0.overlay | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/drivers/regulator/voltage/boards/frdm_mcxn947_mcxn947_cpu0.overlay diff --git a/tests/drivers/regulator/voltage/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/tests/drivers/regulator/voltage/boards/frdm_mcxn947_mcxn947_cpu0.overlay new file mode 100644 index 00000000000000..3dfb29da938a41 --- /dev/null +++ b/tests/drivers/regulator/voltage/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -0,0 +1,47 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* To do this test, connect LPADC0 channel 2A(J8 pin 28) to VREF_OUT (TP1) */ + +/ { + resources: resources { + compatible = "test-regulator-voltage"; + regulators = <&vref>; + tolerance-microvolt = <10000>; + set-read-delay-ms = <1>; + adc-avg-count = <10>; + io-channels = <&lpadc0 0>; + min-microvolt = <1000000>; + max-microvolt = <2100000>; + }; +}; + +&vref { + regulator-initial-mode = ; +}; + +&lpadc0 { + #address-cells = <1>; + #size-cells = <0>; + + /* In this case, the LPADC reference source cannot be set to VREFO, + * switch the reference source to VDD_ANA. + */ + voltage-ref= <2>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; +}; From a064c1c351fc883725b4196a2bb82be431b6684c Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0757/1389] dts: arm: nuvoton: add rtc node of numaker m2l31x Update m2l31x.dtsi, to add one rtc node for rtc support. Signed-off-by: cyliang tw --- dts/arm/nuvoton/m2l31x.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dts/arm/nuvoton/m2l31x.dtsi b/dts/arm/nuvoton/m2l31x.dtsi index 1ebbd9118a0740..5a755676e8cc12 100644 --- a/dts/arm/nuvoton/m2l31x.dtsi +++ b/dts/arm/nuvoton/m2l31x.dtsi @@ -18,6 +18,10 @@ zephyr,flash-controller = &rmc; }; + aliases { + rtc = &rtc; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -40,6 +44,7 @@ compatible = "nuvoton,numaker-scc"; reg = <0x40000200 0x100>; #clock-cells = <0>; + lxt = "enable"; clk-pclkdiv = <(NUMAKER_CLK_PCLKDIV_APB0DIV_DIV2 | NUMAKER_CLK_PCLKDIV_APB1DIV_DIV2)>; core-clock = ; @@ -320,6 +325,15 @@ status = "disabled"; #io-channel-cells = <1>; }; + + rtc: rtc@40041000 { + compatible = "nuvoton,numaker-rtc"; + reg = <0x40041000 0x138>; + interrupts = <6 0>; + oscillator = "lxt"; + clocks = <&pcc NUMAKER_RTC_MODULE 0 0>; + alarms-count = <1>; + }; }; }; From a4bf3187bf52317058af8739cc650a9fe86fa55b Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:06 +0200 Subject: [PATCH 0758/1389] usb: device_next: tweak USB device notification support Since no threads are waiting for the FIFO and we do not need any k_fifo features, we can just use slist. Some notifications (caused by interrupts), especially "VBUS ready", can be triggered very quickly right after UDC initialization if the USB controller is already connected. Depending on the global thread configuration, messsage publishing work can be executed before the context is marked as initialized. Use delayed work to reschedule publishing when the context is not initialized. Signed-off-by: Johann Fischer --- subsys/usb/device_next/Kconfig | 8 ++++++ subsys/usb/device_next/usbd_msg.c | 45 ++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index 7d783422ec3d09..72d3a84e5b46d5 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -47,6 +47,14 @@ config USBD_MSG_SLAB_COUNT help Maximum number of USB device notification messages that can be queued. +config USBD_MSG_WORK_DELAY + int "USB device notification messages work delay" + range 1 100 + default 1 + help + Message work may need to be delayed because the device stack is not + yet ready to publish the message. The delay unit is milliseconds. + rsource "class/Kconfig" endif # USB_DEVICE_STACK_NEXT diff --git a/subsys/usb/device_next/usbd_msg.c b/subsys/usb/device_next/usbd_msg.c index b9afb534fa1d1a..8bf3c7a43a4c33 100644 --- a/subsys/usb/device_next/usbd_msg.c +++ b/subsys/usb/device_next/usbd_msg.c @@ -6,8 +6,8 @@ #include #include -#include #include +#include #include #include "usbd_device.h" @@ -16,8 +16,9 @@ LOG_MODULE_REGISTER(usbd_msg, CONFIG_USBD_LOG_LEVEL); static void msg_work_handler(struct k_work *work); -static K_WORK_DEFINE(msg_work, msg_work_handler); -K_FIFO_DEFINE(msg_queue); +static K_WORK_DELAYABLE_DEFINE(msg_work, msg_work_handler); +static struct k_spinlock ml_lock; +static sys_slist_t msg_list; struct usbd_msg_pkt { sys_snode_t node; @@ -32,6 +33,7 @@ static inline void usbd_msg_pub(struct usbd_contex *const ctx, const struct usbd_msg msg) { struct usbd_msg_pkt *m_pkt; + k_spinlock_key_t key; if (k_mem_slab_alloc(&usbd_msg_slab, (void **)&m_pkt, K_NO_WAIT)) { LOG_DBG("Failed to allocate message memory"); @@ -41,24 +43,47 @@ static inline void usbd_msg_pub(struct usbd_contex *const ctx, m_pkt->ctx = ctx; m_pkt->msg = msg; - k_fifo_put(&msg_queue, m_pkt); - if (k_work_submit(&msg_work) < 0) { - __ASSERT(false, "Failed to submit work"); + key = k_spin_lock(&ml_lock); + sys_slist_append(&msg_list, &m_pkt->node); + k_spin_unlock(&ml_lock, key); + + if (k_work_schedule(&msg_work, K_NO_WAIT) < 0) { + __ASSERT(false, "Failed to schedule work"); } } static void msg_work_handler(struct k_work *work) { + struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct usbd_msg_pkt *m_pkt; + k_spinlock_key_t key; + sys_snode_t *node; + + key = k_spin_lock(&ml_lock); + node = sys_slist_peek_head(&msg_list); + k_spin_unlock(&ml_lock, key); + + __ASSERT(node != NULL, "slist appears to be empty"); + m_pkt = SYS_SLIST_CONTAINER(node, m_pkt, node); + + if (!usbd_is_initialized(m_pkt->ctx)) { + LOG_DBG("USB device support is not yet initialized"); + (void)k_work_reschedule(dwork, K_MSEC(CONFIG_USBD_MSG_WORK_DELAY)); + return; + } + + key = k_spin_lock(&ml_lock); + node = sys_slist_get(&msg_list); + k_spin_unlock(&ml_lock, key); - m_pkt = k_fifo_get(&msg_queue, K_NO_WAIT); - if (m_pkt != NULL) { + if (node != NULL) { + m_pkt = SYS_SLIST_CONTAINER(node, m_pkt, node); m_pkt->ctx->msg_cb(&m_pkt->msg); k_mem_slab_free(&usbd_msg_slab, (void *)m_pkt); } - if (!k_fifo_is_empty(&msg_queue)) { - (void)k_work_submit(work); + if (!sys_slist_is_empty(&msg_list)) { + (void)k_work_schedule(dwork, K_NO_WAIT); } } From f8c863fbdc69dc837508ed5af555cb064eba1ab1 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0759/1389] usb: device_next: add USB device context to message delivery callback Add USB device context argument to message delivery callback. Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 17 +++++++++++++++++ include/zephyr/usb/usbd_msg.h | 12 ------------ samples/subsys/usb/cdc_acm/src/main.c | 2 +- subsys/usb/device_next/usbd_msg.c | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index f278ded3e76163..1a61c41523b071 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -169,6 +169,22 @@ struct usbd_status { enum usbd_speed speed : 2; }; +struct usbd_contex; + +/** + * @brief Callback type definition for USB device message delivery + * + * The implementation uses the system workqueue, and a callback provided and + * registered by the application. The application callback is called in the + * context of the system workqueue. Notification messages are stored in a queue + * and delivered to the callback in sequence. + * + * @param[in] ctx Pointer to USB device support context + * @param[in] msg Pointer to USB device message + */ +typedef void (*usbd_msg_cb_t)(struct usbd_contex *const ctx, + const struct usbd_msg *const msg); + /** * USB device support runtime context * @@ -882,6 +898,7 @@ int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, int usbd_config_maxpower(struct usbd_contex *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const uint8_t power); + /** * @} */ diff --git a/include/zephyr/usb/usbd_msg.h b/include/zephyr/usb/usbd_msg.h index 00ef52a3865660..a11cff7d1daff5 100644 --- a/include/zephyr/usb/usbd_msg.h +++ b/include/zephyr/usb/usbd_msg.h @@ -81,18 +81,6 @@ struct usbd_msg { }; }; -/** - * @brief Callback type definition for USB device message delivery - * - * The implementation uses the system workqueue, and a callback provided and - * registered by the application. The application callback is called in the - * context of the system workqueue. Notification messages are stored in a queue - * and delivered to the callback in sequence. - * - * @param[in] msg Pointer to USB device message - */ -typedef void (*usbd_msg_cb_t)(const struct usbd_msg *const msg); - /** * @brief Returns the message type as a constant string * diff --git a/samples/subsys/usb/cdc_acm/src/main.c b/samples/subsys/usb/cdc_acm/src/main.c index 41cc248aa6b3a2..a9375fa3b7c88a 100644 --- a/samples/subsys/usb/cdc_acm/src/main.c +++ b/samples/subsys/usb/cdc_acm/src/main.c @@ -52,7 +52,7 @@ static inline void print_baudrate(const struct device *dev) static struct usbd_contex *sample_usbd; K_SEM_DEFINE(dtr_sem, 0, 1); -static void sample_msg_cb(const struct usbd_msg *msg) +static void sample_msg_cb(struct usbd_contex *const ctx, const struct usbd_msg *msg) { LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); diff --git a/subsys/usb/device_next/usbd_msg.c b/subsys/usb/device_next/usbd_msg.c index 8bf3c7a43a4c33..b70b85928f4c0d 100644 --- a/subsys/usb/device_next/usbd_msg.c +++ b/subsys/usb/device_next/usbd_msg.c @@ -78,7 +78,7 @@ static void msg_work_handler(struct k_work *work) if (node != NULL) { m_pkt = SYS_SLIST_CONTAINER(node, m_pkt, node); - m_pkt->ctx->msg_cb(&m_pkt->msg); + m_pkt->ctx->msg_cb(m_pkt->ctx, &m_pkt->msg); k_mem_slab_free(&usbd_msg_slab, (void *)m_pkt); } From 7bec5d01bce3c0489bcd5ea8567bbf6b79bd2823 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0760/1389] usb: device_next: remove initialized state checks in event processing For the simple events, do not check whether the device driver and stack are marked as initialized. USB device notification will reschedule delivery if the stack is not yet marked initialized. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_common.c | 4 ---- subsys/usb/device_next/usbd_core.c | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/udc/udc_common.c b/drivers/usb/udc/udc_common.c index 90a73d592307c3..eeed077ebc47a8 100644 --- a/drivers/usb/udc/udc_common.c +++ b/drivers/usb/udc/udc_common.c @@ -175,10 +175,6 @@ int udc_submit_event(const struct device *dev, .dev = dev, }; - if (!udc_is_initialized(dev)) { - return -EPERM; - } - return data->event_cb(dev, &drv_evt); } diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c index 180d136b186115..40999b0f7e4fa5 100644 --- a/subsys/usb/device_next/usbd_core.c +++ b/subsys/usb/device_next/usbd_core.c @@ -193,8 +193,7 @@ static void usbd_thread(void *p1, void *p2, void *p3) k_msgq_get(&usbd_msgq, &event, K_FOREVER); STRUCT_SECTION_FOREACH(usbd_contex, uds_ctx) { - if (uds_ctx->dev == event.dev && - usbd_is_initialized(uds_ctx)) { + if (uds_ctx->dev == event.dev) { usbd_event_handler(uds_ctx, &event); } } From 788d83758e83f12f886048f08dffd9072863e7b1 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0761/1389] usb: device_next: add controller can detect VBUS state change capability There are controllers with capability to detect VBUS state change. This can be used in a generic application to explicitly handle the VBUS detected event after usbd_init() and for example allow the PMIC to detect to what type of port device controller is connected. Signed-off-by: Johann Fischer --- include/zephyr/drivers/usb/udc.h | 2 ++ include/zephyr/usb/usbd.h | 14 ++++++++++++++ subsys/usb/device_next/usbd_device.c | 7 +++++++ 3 files changed, 23 insertions(+) diff --git a/include/zephyr/drivers/usb/udc.h b/include/zephyr/drivers/usb/udc.h index 7e13d565a736a9..2e4d4dbcf32cc0 100644 --- a/include/zephyr/drivers/usb/udc.h +++ b/include/zephyr/drivers/usb/udc.h @@ -42,6 +42,8 @@ struct udc_device_caps { uint32_t out_ack : 1; /** Controller expects device address to be set before status stage */ uint32_t addr_before_status : 1; + /** Controller can detect the state change of USB supply VBUS.*/ + uint32_t can_detect_vbus : 1; /** Maximum packet size for control endpoint */ enum udc_mps0 mps0 : 2; }; diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 1a61c41523b071..ded72ebade979a 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -899,6 +899,20 @@ int usbd_config_maxpower(struct usbd_contex *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const uint8_t power); +/** + * @brief Check that the controller can detect the VBUS state change. + * + * This can be used in a generic application to explicitly handle the VBUS + * detected event after usbd_init(). For example, to call usbd_enable() after a + * short delay to give the PMIC time to detect the bus, or to handle cases + * where usbd_enable() can only be called after a VBUS detected event. + * + * @param[in] uds_ctx Pointer to USB device support context + * + * @return true if controller can detect VBUS state change, false otherwise + */ +bool usbd_can_detect_vbus(struct usbd_contex *const uds_ctx); + /** * @} */ diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index f13c1266f53af6..0f83839d20e060 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -296,3 +296,10 @@ int usbd_shutdown(struct usbd_contex *const uds_ctx) return 0; } + +bool usbd_can_detect_vbus(struct usbd_contex *const uds_ctx) +{ + const struct udc_device_caps caps = udc_caps(uds_ctx->dev); + + return caps.can_detect_vbus; +} From 336db1424beb1e35f5f0b4964235eb473e601ee4 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0762/1389] drivers: udc_nrf: rework controller initialization udc_init() only initializes and enables the USB regulator. This is enough to detect VBUS changes, the USB controller is enabled in udc_enable(). Deinitialization happens correspondingly in reverse order. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_nrf.c | 73 +++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index d4ecc130587c42..f02dfcdc308b83 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -470,14 +470,14 @@ static void udc_nrf_power_handler(nrfx_power_usb_evt_t pwr_evt) switch (pwr_evt) { case NRFX_POWER_USB_EVT_DETECTED: LOG_DBG("POWER event detected"); + udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_READY, 0); break; case NRFX_POWER_USB_EVT_READY: - LOG_INF("POWER event ready"); - udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_READY, 0); + LOG_DBG("POWER event ready"); nrf_usbd_common_start(true); break; case NRFX_POWER_USB_EVT_REMOVED: - LOG_INF("POWER event removed"); + LOG_DBG("POWER event removed"); udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_REMOVED, 0); break; default: @@ -631,9 +631,26 @@ static int udc_nrf_host_wakeup(const struct device *dev) static int udc_nrf_enable(const struct device *dev) { + unsigned int key; int ret; - nrf_usbd_common_enable(); + ret = nrf_usbd_common_init(usbd_event_handler); + if (ret != NRFX_SUCCESS) { + LOG_ERR("nRF USBD driver initialization failed"); + return -EIO; + } + + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, + USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } sys_notify_init_spinwait(&hfxo_cli.notify); ret = onoff_request(hfxo_mgr, &hfxo_cli); @@ -642,6 +659,11 @@ static int udc_nrf_enable(const struct device *dev) return ret; } + /* Disable interrupts until USBD is enabled */ + key = irq_lock(); + nrf_usbd_common_enable(); + irq_unlock(key); + return 0; } @@ -651,6 +673,18 @@ static int udc_nrf_disable(const struct device *dev) nrf_usbd_common_disable(); + if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { + LOG_ERR("Failed to disable control endpoint"); + return -EIO; + } + + if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) { + LOG_ERR("Failed to disable control endpoint"); + return -EIO; + } + + nrf_usbd_common_uninit(); + ret = onoff_cancel_or_release(hfxo_mgr, &hfxo_cli); if (ret < 0) { LOG_ERR("Failed to stop HFXO %d", ret); @@ -663,7 +697,6 @@ static int udc_nrf_disable(const struct device *dev) static int udc_nrf_init(const struct device *dev) { const struct udc_nrf_config *cfg = dev->config; - int ret; hfxo_mgr = z_nrf_clock_control_get_onoff(cfg->clock); @@ -683,25 +716,7 @@ static int udc_nrf_init(const struct device *dev) (void)nrfx_power_init(&cfg->pwr); nrfx_power_usbevt_init(&cfg->evt); - ret = nrf_usbd_common_init(usbd_event_handler); - if (ret != NRFX_SUCCESS) { - LOG_ERR("nRF USBD driver initialization failed"); - return -EIO; - } - nrfx_power_usbevt_enable(); - if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, - USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { - LOG_ERR("Failed to enable control endpoint"); - return -EIO; - } - - if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, - USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { - LOG_ERR("Failed to enable control endpoint"); - return -EIO; - } - LOG_INF("Initialized"); return 0; @@ -711,18 +726,7 @@ static int udc_nrf_shutdown(const struct device *dev) { LOG_INF("shutdown"); - if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { - LOG_ERR("Failed to disable control endpoint"); - return -EIO; - } - - if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) { - LOG_ERR("Failed to disable control endpoint"); - return -EIO; - } - nrfx_power_usbevt_disable(); - nrf_usbd_common_uninit(); nrfx_power_usbevt_uninit(); #ifdef CONFIG_HAS_HW_NRF_USBREG irq_disable(USBREGULATOR_IRQn); @@ -794,6 +798,7 @@ static int udc_nrf_driver_init(const struct device *dev) data->caps.rwup = true; data->caps.out_ack = true; data->caps.mps0 = UDC_NRF_MPS0; + data->caps.can_detect_vbus = true; return 0; } From 4c008494d5cc6e434f836733bbef82339cf2616d Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0763/1389] usb: device_next: remove unused API function Remove unused and not required usbd_ep_ctrl_buf_alloc(). Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 14 -------------- subsys/usb/device_next/usbd_endpoint.c | 11 ----------- 2 files changed, 25 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index ded72ebade979a..1797b54f6dc2fa 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -697,20 +697,6 @@ int usbd_ep_clear_halt(struct usbd_contex *uds_ctx, uint8_t ep); */ bool usbd_ep_is_halted(struct usbd_contex *uds_ctx, uint8_t ep); -/** - * @brief Allocate buffer for USB device control request - * - * Allocate a new buffer from controller's driver buffer pool. - * - * @param[in] uds_ctx Pointer to USB device support context - * @param[in] ep Endpoint address - * @param[in] size Size of the request buffer - * - * @return pointer to allocated request or NULL on error. - */ -struct net_buf *usbd_ep_ctrl_buf_alloc(struct usbd_contex *const uds_ctx, - const uint8_t ep, const size_t size); - /** * @brief Allocate buffer for USB device request * diff --git a/subsys/usb/device_next/usbd_endpoint.c b/subsys/usb/device_next/usbd_endpoint.c index 31ac1a5f7a0a6c..fa68313ce8db07 100644 --- a/subsys/usb/device_next/usbd_endpoint.c +++ b/subsys/usb/device_next/usbd_endpoint.c @@ -86,17 +86,6 @@ static void usbd_ep_ctrl_set_zlp(struct usbd_contex *const uds_ctx, * All the functions below are part of public USB device support API. */ -struct net_buf *usbd_ep_ctrl_buf_alloc(struct usbd_contex *const uds_ctx, - const uint8_t ep, const size_t size) -{ - if (USB_EP_GET_IDX(ep)) { - /* Not a control endpoint */ - return NULL; - } - - return udc_ep_buf_alloc(uds_ctx->dev, ep, size); -} - int usbd_ep_ctrl_enqueue(struct usbd_contex *const uds_ctx, struct net_buf *const buf) { From 7aae5b8f5fce54a0583258b2b00a8fcb2df52b73 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0764/1389] usb: device_next: lock scheduler in usbd_init() Lock the scheduler to ensure that the context is not preempted before it is fully initialized. Signed-off-by: Johann Fischer --- subsys/usb/device_next/usbd_device.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index 0f83839d20e060..9057e439040b8d 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -182,6 +182,11 @@ int usbd_init(struct usbd_contex *const uds_ctx) { int ret; + /* + * Lock the scheduler to ensure that the context is not preempted + * before it is fully initialized. + */ + k_sched_lock(); usbd_device_lock(uds_ctx); if (uds_ctx->dev == NULL) { @@ -211,6 +216,8 @@ int usbd_init(struct usbd_contex *const uds_ctx) init_exit: usbd_device_unlock(uds_ctx); + k_sched_unlock(); + return ret; } From 4988f1881a5a849a0215865b0292c33cce8c1352 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0765/1389] samples: usb: cdc_acm: enable USB support only when device is connected If the controller can detect VBUS state changes, enable USB support only when the device is connected and disable it when the device is disconnected. Signed-off-by: Johann Fischer --- samples/subsys/usb/cdc_acm/src/main.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/samples/subsys/usb/cdc_acm/src/main.c b/samples/subsys/usb/cdc_acm/src/main.c index a9375fa3b7c88a..91f7a8db7f7af0 100644 --- a/samples/subsys/usb/cdc_acm/src/main.c +++ b/samples/subsys/usb/cdc_acm/src/main.c @@ -56,6 +56,20 @@ static void sample_msg_cb(struct usbd_contex *const ctx, const struct usbd_msg * { LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); + if (usbd_can_detect_vbus(ctx)) { + if (msg->type == USBD_MSG_VBUS_READY) { + if (usbd_enable(ctx)) { + LOG_ERR("Failed to enable device support"); + } + } + + if (msg->type == USBD_MSG_VBUS_REMOVED) { + if (usbd_disable(ctx)) { + LOG_ERR("Failed to disable device support"); + } + } + } + if (msg->type == USBD_MSG_CDC_ACM_CONTROL_LINE_STATE) { uint32_t dtr = 0U; @@ -80,13 +94,15 @@ static int enable_usb_device_next(void) return -ENODEV; } - err = usbd_enable(sample_usbd); - if (err) { - LOG_ERR("Failed to enable device support"); - return err; + if (!usbd_can_detect_vbus(sample_usbd)) { + err = usbd_enable(sample_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return err; + } } - LOG_DBG("USB device support enabled"); + LOG_INF("USB device support enabled"); return 0; } From e2295a2a99f3fac37641955d0f0cb3746baea665 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0766/1389] samples: usb: cdc_acm: set USBD_CDC_ACM_LOG_LEVEL to error Set USBD_CDC_ACM_LOG_LEVEL to error. Signed-off-by: Johann Fischer --- samples/subsys/usb/cdc_acm/usbd_next_prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/usb/cdc_acm/usbd_next_prj.conf b/samples/subsys/usb/cdc_acm/usbd_next_prj.conf index c5147519f87044..f08928438b7770 100644 --- a/samples/subsys/usb/cdc_acm/usbd_next_prj.conf +++ b/samples/subsys/usb/cdc_acm/usbd_next_prj.conf @@ -8,6 +8,7 @@ CONFIG_USBD_CDC_ACM_CLASS=y CONFIG_LOG=y CONFIG_USBD_LOG_LEVEL_WRN=y CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_USBD_CDC_ACM_LOG_LEVEL_ERR=y CONFIG_SAMPLE_USBD_PID=0x0001 CONFIG_SAMPLE_USBD_PRODUCT="USBD CDC ACM sample" From 6e196174a08c809bcfd58d4b32cf9a388d52203a Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0767/1389] twister: Fix default command line dependency on --device-testing Fix default command line options check dependency on `--device-testing` when it is provided to run Twister and turn device command options as mandatory. Fixes after changes introduced with #72399. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/environment.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 177cc4b3f931f3..dcd8fe9189cf87 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -72,7 +72,7 @@ def add_parse_arguments(parser = None): run_group_option = parser.add_mutually_exclusive_group() - device = parser.add_mutually_exclusive_group(required="--device-testing" in sys.argv) + device = parser.add_mutually_exclusive_group() test_or_build = parser.add_mutually_exclusive_group() @@ -808,6 +808,10 @@ def parse_arguments(parser, args, options = None, on_init=True): logger.error("valgrind enabled but valgrind executable not found") sys.exit(1) + if (not options.device_testing) and (options.device_serial or options.device_serial_pty or options.hardware_map): + logger.error("Use --device-testing with --device-serial, or --device-serial-pty, or --hardware-map.") + sys.exit(1) + if options.device_testing and (options.device_serial or options.device_serial_pty) and len(options.platform) != 1: logger.error("When --device-testing is used with --device-serial " "or --device-serial-pty, exactly one platform must " From 6dc6c1f1b1786277aa5e346cd09729046d801f2d Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0768/1389] Bluetooth: HFP_AG: Initialize HFP AG Implement basic functions for HFP AG. Signed-off-by: Lyle Zhu --- include/zephyr/bluetooth/classic/hfp_ag.h | 298 +++ subsys/bluetooth/Kconfig.logging | 4 + subsys/bluetooth/host/Kconfig | 71 + subsys/bluetooth/host/classic/CMakeLists.txt | 5 + subsys/bluetooth/host/classic/hfp_ag.c | 2100 +++++++++++++++++ .../bluetooth/host/classic/hfp_ag_internal.h | 135 ++ subsys/bluetooth/host/classic/hfp_internal.h | 65 +- 7 files changed, 2650 insertions(+), 28 deletions(-) create mode 100644 include/zephyr/bluetooth/classic/hfp_ag.h create mode 100644 subsys/bluetooth/host/classic/hfp_ag.c create mode 100644 subsys/bluetooth/host/classic/hfp_ag_internal.h diff --git a/include/zephyr/bluetooth/classic/hfp_ag.h b/include/zephyr/bluetooth/classic/hfp_ag.h new file mode 100644 index 00000000000000..6e5173d9fa4c12 --- /dev/null +++ b/include/zephyr/bluetooth/classic/hfp_ag.h @@ -0,0 +1,298 @@ +/** @file + * @brief Handsfree Profile Audio Gateway handling. + */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HFP_AG_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HFP_AG_H_ + +/** + * @brief Hands Free Profile - Audio Gateway (HFP-AG) + * @defgroup bt_hfp_ag Hands Free Profile - Audio Gateway (HFP-AG) + * @ingroup bluetooth + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* HFP AG Indicators */ +enum bt_hfp_ag_indicator { + BT_HFP_AG_SERVICE_IND = 0, /* Service availability indicator */ + BT_HFP_AG_CALL_IND = 1, /* call status indicator */ + BT_HFP_AG_CALL_SETUP_IND = 2, /* Call set up status indicator */ + BT_HFP_AG_CALL_HELD_IND = 3, /* Call hold status indicator */ + BT_HFP_AG_SIGNAL_IND = 4, /* Signal strength indicator */ + BT_HFP_AG_ROAM_IND = 5, /* Roaming status indicator */ + BT_HFP_AG_BATTERY_IND = 6, /* Battery change indicator */ + BT_HFP_AG_IND_MAX /* Indicator MAX value */ +}; + +/* HFP CODEC */ +#define BT_HFP_AG_CODEC_CVSD 0x01 +#define BT_HFP_AG_CODEC_MSBC 0x02 +#define BT_HFP_AG_CODEC_LC3_SWB 0x03 + +struct bt_hfp_ag; + +/** @brief HFP profile AG application callback */ +struct bt_hfp_ag_cb { + /** HF AG connected callback to application + * + * If this callback is provided it will be called whenever the + * AG connection completes. + * + * @param ag HFP AG object. + */ + void (*connected)(struct bt_hfp_ag *ag); + /** HF disconnected callback to application + * + * If this callback is provided it will be called whenever the + * connection gets disconnected, including when a connection gets + * rejected or cancelled or any error in SLC establishment. + * + * @param ag HFP AG object. + */ + void (*disconnected)(struct bt_hfp_ag *ag); + /** HF SCO/eSCO connected Callback + * + * If this callback is provided it will be called whenever the + * SCO/eSCO connection completes. + * + * @param ag HFP AG object. + * @param sco_conn SCO/eSCO Connection object. + */ + void (*sco_connected)(struct bt_hfp_ag *ag, struct bt_conn *sco_conn); + /** HF SCO/eSCO disconnected Callback + * + * If this callback is provided it will be called whenever the + * SCO/eSCO connection gets disconnected. + * + * @param ag HFP AG object. + * @param sco_conn SCO/eSCO Connection object. + */ + void (*sco_disconnected)(struct bt_hfp_ag *ag); + + /** HF memory dialing request Callback + * + * If this callback is provided it will be called whenever a + * new call is requested with memory dialing from HFP unit. + * Get the phone number according to the given AG memory location. + * + * @param ag HFP AG object. + * @param location AG memory location + * @param number Dailing number + * + * @return 0 in case of success or negative value in case of error. + */ + int (*memory_dial)(struct bt_hfp_ag *ag, const char *location, char **number); + + /** HF outgoing Callback + * + * If this callback is provided it will be called whenever a + * new call is outgoing. + * + * @param ag HFP AG object. + * @param number Dailing number + */ + void (*outgoing)(struct bt_hfp_ag *ag, const char *number); + + /** HF incoming Callback + * + * If this callback is provided it will be called whenever a + * new call is incoming. + * + * @param ag HFP AG object. + * @param number Incoming number + */ + void (*incoming)(struct bt_hfp_ag *ag, const char *number); + + /** HF ringing Callback + * + * If this callback is provided it will be called whenever the + * call is in the ringing + * + * @param ag HFP AG object. + * @param in_bond true - in-bond ringing, false - No in-bond ringing + */ + void (*ringing)(struct bt_hfp_ag *ag, bool in_band); + + /** HF call accept Callback + * + * If this callback is provided it will be called whenever the + * call is accepted. + * + * @param ag HFP AG object. + */ + void (*accept)(struct bt_hfp_ag *ag); + + /** HF call reject Callback + * + * If this callback is provided it will be called whenever the + * call is rejected. + * + * @param ag HFP AG object. + */ + void (*reject)(struct bt_hfp_ag *ag); + + /** HF call terminate Callback + * + * If this callback is provided it will be called whenever the + * call is terminated. + * + * @param ag HFP AG object. + */ + void (*terminate)(struct bt_hfp_ag *ag); + + /** Supported codec Ids callback + * + * If this callback is provided it will be called whenever the + * supported codec ids are updated. + * + * @param ag HFP AG object. + */ + void (*codec)(struct bt_hfp_ag *ag, uint32_t ids); +}; + +/** @brief Register HFP AG profile + * + * Register Handsfree profile AG callbacks to monitor the state and get the + * required HFP details to display. + * + * @param cb callback structure. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_register(struct bt_hfp_ag_cb *cb); + +/** @brief Create the hfp ag session + * + * Create the hfp ag session + * + * @param conn ACL connection object. + * @param ag Created HFP AG object. + * @param channel Peer rfcomm channel to be connected. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_connect(struct bt_conn *conn, struct bt_hfp_ag **ag, uint8_t channel); + +/** @brief Disconnect the hfp ag session + * + * Disconnect the hfp ag session + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit of an incoming call + * + * Notify HFP Unit of an incoming call. + * + * @param ag HFP AG object. + * @param number Dailing number. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_incoming(struct bt_hfp_ag *ag, const char *number); + +/** @brief Reject the incoming call + * + * Reject the incoming call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_reject(struct bt_hfp_ag *ag); + +/** @brief Accept the incoming call + * + * Accept the incoming call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_accept(struct bt_hfp_ag *ag); + +/** @brief Terminate the active/hold call + * + * Terminate the active/hold call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_terminate(struct bt_hfp_ag *ag); + +/** @brief Dial a call + * + * Dial a call. + * + * @param ag HFP AG object. + * @param number Dailing number. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_outgoing(struct bt_hfp_ag *ag, const char *number); + +/** @brief Notify HFP Unit that the remote starts ringing + * + * Notify HFP Unit that the remote starts ringing. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_ringing(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit that the remote rejects the call + * + * Notify HFP Unit that the remote rejects the call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_reject(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit that the remote accepts the call + * + * Notify HFP Unit that the remote accepts the call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_accept(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit that the remote terminates the active/hold call + * + * Notify HFP Unit that the remote terminates the active/hold call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_terminate(struct bt_hfp_ag *ag); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HFP_HF_H_ */ diff --git a/subsys/bluetooth/Kconfig.logging b/subsys/bluetooth/Kconfig.logging index 6cd4006c91abc5..ab28df1bcec32c 100644 --- a/subsys/bluetooth/Kconfig.logging +++ b/subsys/bluetooth/Kconfig.logging @@ -298,6 +298,10 @@ module = BT_HFP_HF module-str = "Bluetooth Hands Free Profile (HFP)" source "subsys/logging/Kconfig.template.log_config_inherit" +module = BT_HFP_AG +module-str = "Bluetooth Hands Free Audio Gateway Profile (HFP AG)" +source "subsys/logging/Kconfig.template.log_config_inherit" + module = BT_AVDTP module-str = "Bluetooth AVDTP debug" source "subsys/logging/Kconfig.template.log_config_inherit" diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 328a4905976af9..9c0e53e80e135e 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -1048,6 +1048,77 @@ config BT_HFP_HF help This option enables Bluetooth HF support +config BT_HFP_AG + bool "Bluetooth Handsfree profile AG Role support [EXPERIMENTAL]" + depends on PRINTK + select BT_RFCOMM + select EXPERIMENTAL + help + This option enables Bluetooth AG support + +if BT_HFP_AG +config BT_HFP_AG_TX_BUF_COUNT + int "Maximum number of TX buffers for HFP AG [EXPERIMENTAL]" + default BT_RFCOMM_TX_MAX + range BT_RFCOMM_TX_MAX 255 + help + Maximum number of pending TX buffers that have an associated + sending buf. Normally this can be left to the default value, which + is equal to the number of session in the stack-internal pool. + +config BT_HFP_AG_THREAD_STACK_SIZE + int "Size of the HFP AG thread stack [EXPERIMENTAL]" + default 1024 + help + Stack size needed for executing thread for HFP AG. + +config BT_HFP_AG_THREAD_PRIO + # Hidden option for HFP AG thread priority + int + default 6 + +config BT_HFP_AG_OUTGOING_TIMEOUT + int "Call outgoing timeout value for HFP AG [EXPERIMENTAL]" + default 3 + range 1 10 + help + The option sets the timeout of call outgoing. If the call does + not switch to alerting state before timeout, it will be + stopped by the HFP AG. The unit is seconds. + +config BT_HFP_AG_INCOMING_TIMEOUT + int "Incoming call timeout value for HFP AG [EXPERIMENTAL]" + default 3 + range 1 10 + help + The option sets the timeout of incoming call. If the call does + not switch to ringing state before timeout, it will be + stopped by the HFP AG. The unit is seconds. + +config BT_HFP_AG_ALERTING_TIMEOUT + int "Call alerting/ringing timeout value for HFP AG [EXPERIMENTAL]" + default 60 + range 10 60 + help + The option sets the timeout of call alerting/ringing. If the + call is not active before timeout, it will be stopped + by the HFP AG. The unit is seconds. + +config BT_HFP_AG_PHONE_NUMBER_MAX_LEN + int "Supported max length of phone number for HFP AG [EXPERIMENTAL]" + default 32 + range 1 255 + help + Supported max length of phone number for HFP AG. + +config BT_HFP_AG_RING_NOTIFY_INTERVAL + int "Ring notification interval [EXPERIMENTAL]" + default 3 + help + Ring notification interval if the call is in alert state. + The unit is seconds. +endif # BT_HFP_AG + config BT_AVDTP bool "Bluetooth AVDTP protocol support [EXPERIMENTAL]" select EXPERIMENTAL diff --git a/subsys/bluetooth/host/classic/CMakeLists.txt b/subsys/bluetooth/host/classic/CMakeLists.txt index 48b3935f86f045..039f961c78627f 100644 --- a/subsys/bluetooth/host/classic/CMakeLists.txt +++ b/subsys/bluetooth/host/classic/CMakeLists.txt @@ -22,3 +22,8 @@ zephyr_library_sources_ifdef( hfp_hf.c at.c ) + +zephyr_library_sources_ifdef( + CONFIG_BT_HFP_AG + hfp_ag.c + ) diff --git a/subsys/bluetooth/host/classic/hfp_ag.c b/subsys/bluetooth/host/classic/hfp_ag.c new file mode 100644 index 00000000000000..eaf06d088051f3 --- /dev/null +++ b/subsys/bluetooth/host/classic/hfp_ag.c @@ -0,0 +1,2100 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "common/assert.h" + +#include +#include + +#include "host/hci_core.h" +#include "host/conn_internal.h" +#include "l2cap_br_internal.h" +#include "rfcomm_internal.h" +#include "at.h" +#include "sco_internal.h" + +#include "hfp_internal.h" +#include "hfp_ag_internal.h" + +#define LOG_LEVEL CONFIG_BT_HFP_AG_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_hfp_ag); + +typedef int (*bt_hfp_ag_parse_command_t)(struct bt_hfp_ag *ag, struct net_buf *buf); + +struct bt_hfp_ag_at_cmd_handler { + const char *cmd; + bt_hfp_ag_parse_command_t handler; +}; + +static const struct { + const char *name; + const char *connector; + uint32_t min; + uint32_t max; +} ag_ind[] = { + {"service", "-", 0, 1}, /* BT_HFP_AG_SERVICE_IND */ + {"call", ",", 0, 1}, /* BT_HFP_AG_CALL_IND */ + {"callsetup", "-", 0, 3}, /* BT_HFP_AG_CALL_SETUP_IND */ + {"callheld", "-", 0, 2}, /* BT_HFP_AG_CALL_HELD_IND */ + {"signal", "-", 0, 5}, /* BT_HFP_AG_SIGNAL_IND */ + {"roam", ",", 0, 1}, /* BT_HFP_AG_ROAM_IND */ + {"battchg", "-", 0, 5} /* BT_HFP_AG_BATTERY_IND */ +}; + +typedef void (*bt_hfp_ag_tx_cb_t)(struct bt_hfp_ag *ag, void *user_data); + +struct bt_ag_tx { + sys_snode_t node; + + struct bt_hfp_ag *ag; + struct net_buf *buf; + bt_hfp_ag_tx_cb_t cb; + void *user_data; +}; + +NET_BUF_POOL_FIXED_DEFINE(ag_pool, CONFIG_BT_HFP_AG_TX_BUF_COUNT, + BT_RFCOMM_BUF_SIZE(BT_HF_CLIENT_MAX_PDU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static struct bt_hfp_ag bt_hfp_ag_pool[CONFIG_BT_MAX_CONN]; + +static struct bt_hfp_ag_cb *bt_ag; + +/* Sent but not acknowledged TX packets with a callback */ +static struct bt_ag_tx ag_tx[CONFIG_BT_HFP_AG_TX_BUF_COUNT * 2]; +static K_FIFO_DEFINE(ag_tx_free); +static K_FIFO_DEFINE(ag_tx_notify); + +struct k_thread ag_thread; +static K_KERNEL_STACK_MEMBER(ag_thread_stack, CONFIG_BT_HFP_AG_THREAD_STACK_SIZE); +static k_tid_t ag_thread_id; + +static enum at_cme bt_hfp_ag_get_cme_err(int err) +{ + enum at_cme cme_err; + + switch (err) { + case -EOPNOTSUPP: + cme_err = CME_ERROR_OPERATION_NOT_SUPPORTED; + break; + case -EFAULT: + cme_err = CME_ERROR_AG_FAILURE; + break; + case -ENOSR: + cme_err = CME_ERROR_MEMORY_FAILURE; + break; + case -ENOMEM: + __fallthrough; + case -ENOBUFS: + cme_err = CME_ERROR_MEMORY_FULL; + break; + case -ENAMETOOLONG: + cme_err = CME_ERROR_DIAL_STRING_TO_LONG; + break; + case -EINVAL: + cme_err = CME_ERROR_INVALID_INDEX; + break; + case -ENOTSUP: + cme_err = CME_ERROR_OPERATION_NOT_ALLOWED; + break; + case -ENOTCONN: + cme_err = CME_ERROR_NO_CONNECTION_TO_PHONE; + break; + default: + cme_err = CME_ERROR_AG_FAILURE; + break; + } + + return cme_err; +} + +static void hfp_ag_lock(struct bt_hfp_ag *ag) +{ + k_sem_take(&ag->lock, K_FOREVER); +} + +static void hfp_ag_unlock(struct bt_hfp_ag *ag) +{ + k_sem_give(&ag->lock); +} + +static void bt_hfp_ag_set_state(struct bt_hfp_ag *ag, bt_hfp_state_t state) +{ + LOG_DBG("update state %p, old %d -> new %d", ag, ag->state, state); + + ag->state = state; + + switch (state) { + case BT_HFP_DISCONNECTED: + if (bt_ag && bt_ag->disconnected) { + bt_ag->disconnected(ag); + } + break; + case BT_HFP_CONNECTING: + break; + case BT_HFP_CONFIG: + break; + case BT_HFP_CONNECTED: + if (bt_ag && bt_ag->connected) { + bt_ag->connected(ag); + } + break; + case BT_HFP_DISCONNECTING: + break; + default: + LOG_WRN("no valid (%u) state was set", state); + break; + } +} + +static void bt_hfp_ag_set_call_state(struct bt_hfp_ag *ag, bt_hfp_call_state_t call_state) +{ + LOG_DBG("update call state %p, old %d -> new %d", ag, ag->call_state, call_state); + + ag->call_state = call_state; + + switch (call_state) { + case BT_HFP_CALL_TERMINATE: + atomic_clear(ag->flags); + k_work_cancel_delayable(&ag->deferred_work); + break; + case BT_HFP_CALL_OUTGOING: + k_work_reschedule(&ag->deferred_work, K_SECONDS(CONFIG_BT_HFP_AG_OUTGOING_TIMEOUT)); + break; + case BT_HFP_CALL_INCOMING: + k_work_reschedule(&ag->deferred_work, K_SECONDS(CONFIG_BT_HFP_AG_INCOMING_TIMEOUT)); + break; + case BT_HFP_CALL_ALERTING: + k_work_reschedule(&ag->ringing_work, K_NO_WAIT); + k_work_reschedule(&ag->deferred_work, K_SECONDS(CONFIG_BT_HFP_AG_ALERTING_TIMEOUT)); + break; + case BT_HFP_CALL_ACTIVE: + k_work_cancel_delayable(&ag->ringing_work); + k_work_cancel_delayable(&ag->deferred_work); + break; + case BT_HFP_CALL_HOLD: + break; + default: + /* Invalid state */ + break; + } + + if (ag->state == BT_HFP_DISCONNECTING) { + int err = bt_rfcomm_dlc_disconnect(&ag->rfcomm_dlc); + + if (err) { + LOG_ERR("Fail to disconnect DLC %p", &ag->rfcomm_dlc); + } + } +} + +static struct bt_ag_tx *bt_ag_tx_alloc(void) +{ + /* The TX context always get freed in the system workqueue, + * so if we're in the same workqueue but there are no immediate + * contexts available, there's no chance we'll get one by waiting. + */ + if (k_current_get() == &k_sys_work_q.thread) { + return k_fifo_get(&ag_tx_free, K_NO_WAIT); + } + + if (IS_ENABLED(CONFIG_BT_HFP_AG_LOG_LEVEL_DBG)) { + struct bt_ag_tx *tx = k_fifo_get(&ag_tx_free, K_NO_WAIT); + + if (tx) { + return tx; + } + + LOG_WRN("Unable to get an immediate free bt_ag_tx"); + } + + return k_fifo_get(&ag_tx_free, K_FOREVER); +} + +static void bt_ag_tx_free(struct bt_ag_tx *tx) +{ + LOG_DBG("Free tx buffer %p", tx); + + (void)memset(tx, 0, sizeof(*tx)); + + k_fifo_put(&ag_tx_free, tx); +} + +static int hfp_ag_next_step(struct bt_hfp_ag *ag, bt_hfp_ag_tx_cb_t cb, void *user_data) +{ + struct bt_ag_tx *tx; + + LOG_DBG("cb %p user_data %p", cb, user_data); + + tx = bt_ag_tx_alloc(); + if (tx == NULL) { + LOG_ERR("No tx buffers!"); + return -ENOMEM; + } + + LOG_DBG("Alloc tx buffer %p", tx); + + tx->ag = ag; + tx->buf = NULL; + tx->cb = cb; + tx->user_data = user_data; + + k_fifo_put(&ag_tx_notify, tx); + + return 0; +} + +static int hfp_ag_send(struct bt_hfp_ag *ag, struct bt_ag_tx *tx) +{ + return bt_rfcomm_dlc_send(&ag->rfcomm_dlc, tx->buf); +} + +static int hfp_ag_send_data(struct bt_hfp_ag *ag, bt_hfp_ag_tx_cb_t cb, void *user_data, + const char *format, ...) +{ + struct net_buf *buf; + struct bt_ag_tx *tx; + va_list vargs; + int err; + + LOG_DBG("AG %p sending data cb %p user_data %p", ag, cb, user_data); + + buf = bt_rfcomm_create_pdu(&ag_pool); + if (!buf) { + LOG_ERR("No Buffers!"); + return -ENOMEM; + } + + tx = bt_ag_tx_alloc(); + if (tx == NULL) { + LOG_ERR("No tx buffers!"); + net_buf_unref(buf); + return -ENOMEM; + } + + LOG_DBG("buf %p tx %p", buf, tx); + + tx->ag = ag; + tx->buf = buf; + tx->cb = cb; + tx->user_data = user_data; + + va_start(vargs, format); + err = vsnprintk((char *)buf->data, (net_buf_tailroom(buf) - 1), format, vargs); + va_end(vargs); + + if (err < 0) { + LOG_ERR("Unable to format variable arguments"); + net_buf_unref(buf); + bt_ag_tx_free(tx); + return err; + } + + net_buf_add(buf, err); + + LOG_HEXDUMP_DBG(buf->data, buf->len, "Sending:"); + + hfp_ag_lock(ag); + sys_slist_append(&ag->tx_pending, &tx->node); + hfp_ag_unlock(ag); + + err = hfp_ag_send(ag, tx); + if (err < 0) { + LOG_ERR("Rfcomm send error :(%d)", err); + hfp_ag_lock(ag); + sys_slist_find_and_remove(&ag->tx_pending, &tx->node); + hfp_ag_unlock(ag); + net_buf_unref(buf); + bt_ag_tx_free(tx); + return err; + } + + return 0; +} + +static void skip_space(struct net_buf *buf) +{ + while ((buf->len > 0) && (buf->data[0] == ' ')) { + (void)net_buf_pull(buf, 1); + } +} + +static int get_number(struct net_buf *buf, uint32_t *number) +{ + int err = -EINVAL; + + *number = 0; + + skip_space(buf); + while (buf->len > 0) { + if ((buf->data[0] >= '0') && (buf->data[0] <= '9')) { + *number = *number * 10 + buf->data[0] - '0'; + (void)net_buf_pull(buf, 1); + err = 0; + } else { + break; + } + } + skip_space(buf); + + return err; +} + +static bool is_char(struct net_buf *buf, uint8_t c) +{ + bool found = false; + + skip_space(buf); + if (buf->len > 0) { + if (buf->data[0] == c) { + (void)net_buf_pull(buf, 1); + found = true; + } + } + skip_space(buf); + + return found; +} + +static int bt_hfp_ag_brsf_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + uint32_t hf_features; + int err; + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + err = get_number(buf, &hf_features); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + ag->hf_features = hf_features; + + return hfp_ag_send_data(ag, NULL, NULL, "\r\n+BRSF:%d\r\n", ag->ag_features); +} + +static int bt_hfp_ag_bac_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + uint32_t codec; + uint32_t codec_ids = 0U; + int err; + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + if (!(ag->hf_features & BT_HFP_HF_FEATURE_CODEC_NEG) || + !(ag->ag_features & BT_HFP_AG_FEATURE_CODEC_NEG)) { + return -EOPNOTSUPP; + } + + while (err == 0) { + err = get_number(buf, &codec); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, ',')) { + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + } + + if (codec < (sizeof(codec_ids) * 8)) { + codec_ids |= BIT(codec); + } + } + + ag->hf_codec_ids = codec_ids; + + if (bt_ag && bt_ag->codec) { + bt_ag->codec(ag, ag->hf_codec_ids); + } + + return 0; +} + +static int bt_hfp_ag_cind_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + bool inquiry_status = true; + + if (is_char(buf, '=')) { + inquiry_status = false; + } + + if (!is_char(buf, '?')) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (!inquiry_status) { + err = hfp_ag_send_data( + ag, NULL, NULL, + "\r\n+CIND:(\"%s\",(%d%s%d)),(\"%s\",(%d%s%d)),(\"%s\",(%d%s%d)),(\"%s\",(%" + "d%s%d)),(\"%s\",(%d%s%d)),(\"%s\",(%d%s%d)),(\"%s\",(%d%s%d))\r\n", + ag_ind[BT_HFP_AG_SERVICE_IND].name, ag_ind[BT_HFP_AG_SERVICE_IND].min, + ag_ind[BT_HFP_AG_SERVICE_IND].connector, ag_ind[BT_HFP_AG_SERVICE_IND].max, + ag_ind[BT_HFP_AG_CALL_IND].name, ag_ind[BT_HFP_AG_CALL_IND].min, + ag_ind[BT_HFP_AG_CALL_IND].connector, ag_ind[BT_HFP_AG_CALL_IND].max, + ag_ind[BT_HFP_AG_CALL_SETUP_IND].name, ag_ind[BT_HFP_AG_CALL_SETUP_IND].min, + ag_ind[BT_HFP_AG_CALL_SETUP_IND].connector, + ag_ind[BT_HFP_AG_CALL_SETUP_IND].max, ag_ind[BT_HFP_AG_CALL_HELD_IND].name, + ag_ind[BT_HFP_AG_CALL_HELD_IND].min, + ag_ind[BT_HFP_AG_CALL_HELD_IND].connector, + ag_ind[BT_HFP_AG_CALL_HELD_IND].max, ag_ind[BT_HFP_AG_SIGNAL_IND].name, + ag_ind[BT_HFP_AG_SIGNAL_IND].min, ag_ind[BT_HFP_AG_SIGNAL_IND].connector, + ag_ind[BT_HFP_AG_SIGNAL_IND].max, ag_ind[BT_HFP_AG_ROAM_IND].name, + ag_ind[BT_HFP_AG_ROAM_IND].min, ag_ind[BT_HFP_AG_ROAM_IND].connector, + ag_ind[BT_HFP_AG_ROAM_IND].max, ag_ind[BT_HFP_AG_BATTERY_IND].name, + ag_ind[BT_HFP_AG_BATTERY_IND].min, ag_ind[BT_HFP_AG_BATTERY_IND].connector, + ag_ind[BT_HFP_AG_BATTERY_IND].max); + } else { + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+CIND:%d,%d,%d,%d,%d,%d,%d\r\n", + ag->indicator_value[BT_HFP_AG_SERVICE_IND], + ag->indicator_value[BT_HFP_AG_CALL_IND], + ag->indicator_value[BT_HFP_AG_CALL_SETUP_IND], + ag->indicator_value[BT_HFP_AG_CALL_HELD_IND], + ag->indicator_value[BT_HFP_AG_SIGNAL_IND], + ag->indicator_value[BT_HFP_AG_ROAM_IND], + ag->indicator_value[BT_HFP_AG_BATTERY_IND]); + } + + return err; +} + +static void bt_hfp_ag_set_in_band_ring(struct bt_hfp_ag *ag, void *user_data) +{ + if ((ag->ag_features & BT_HFP_AG_FEATURE_INBAND_RINGTONE) != 0) { + int err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BSIR:1\r\n"); + + atomic_set_bit_to(ag->flags, BT_HFP_AG_INBAND_RING, err == 0); + } +} + +static int bt_hfp_ag_cmer_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + uint32_t number; + int err; + static const uint32_t command_line_prefix[] = {3, 0, 0}; + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + for (int i = 0; i < ARRAY_SIZE(command_line_prefix); i++) { + err = get_number(buf, &number); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, ',')) { + return -ENOTSUP; + } + + if (command_line_prefix[i] != number) { + return -ENOTSUP; + } + } + + err = get_number(buf, &number); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (number == 1) { + atomic_set_bit(ag->flags, BT_HFP_AG_CMER_ENABLE); + bt_hfp_ag_set_state(ag, BT_HFP_CONNECTED); + err = hfp_ag_next_step(ag, bt_hfp_ag_set_in_band_ring, NULL); + return err; + } else if (number == 0) { + atomic_clear_bit(ag->flags, BT_HFP_AG_CMER_ENABLE); + } else { + return -ENOTSUP; + } + + return 0; +} + +static int bt_hfp_ag_chld_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + return -EOPNOTSUPP; +} + +static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + uint32_t indicator; + uint32_t hf_indicators = 0U; + int err; + char *data; + uint32_t len; + + if (!((ag->ag_features & BT_HFP_AG_FEATURE_HF_IND) && + (ag->hf_features & BT_HFP_HF_FEATURE_HF_IND))) { + return -EOPNOTSUPP; + } + + if (is_char(buf, '?')) { + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + hf_indicators = ag->hf_indicators_of_hf & ag->hf_indicators_of_ag; + len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX + : (sizeof(hf_indicators) * 8); + for (int i = 1; i < len; i++) { + if (BIT(i) & hf_indicators) { + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BIND:%d,%d\r\n", i, 1); + } else { + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BIND:%d,%d\r\n", i, 0); + } + if (err < 0) { + return err; + } + if (hf_indicators == 0) { + break; + } + } + return 0; + } + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + if (is_char(buf, '?')) { + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + data = &ag->buffer[0]; + *data = '('; + data++; + hf_indicators = ag->hf_indicators_of_ag; + len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX + : (sizeof(hf_indicators) * 8); + for (int i = 1; (i < len) && (hf_indicators != 0); i++) { + if (BIT(i) & hf_indicators) { + int length = snprintk( + data, (char *)&ag->buffer[HF_MAX_BUF_LEN - 1] - data - 3, + "%d", i); + data += length; + hf_indicators &= ~BIT(i); + } + if (hf_indicators != 0) { + *data = ','; + data++; + } + } + *data = ')'; + data++; + *data = '\r'; + data++; + *data = '\0'; + data++; + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BIND:%s\r\n", &ag->buffer[0]); + return err; + } + + while (buf->len > 0) { + err = get_number(buf, &indicator); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, ',')) { + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + } + + if (indicator < (sizeof(hf_indicators) * 8)) { + hf_indicators |= BIT(indicator); + } + } + + ag->hf_indicators_of_hf = hf_indicators; + + return 0; +} + +static int bt_hfp_ag_cmee_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + uint32_t cmee; + int err; + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + err = get_number(buf, &cmee); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (cmee > 1) { + return -ENOTSUP; + } + + atomic_set_bit_to(ag->flags, BT_HFP_AG_CMEE_ENABLE, cmee == 1); + + return 0; +} + +static int hfp_ag_update_indicator(struct bt_hfp_ag *ag, enum bt_hfp_ag_indicator index, + uint8_t value, bt_hfp_ag_tx_cb_t cb, void *user_data) +{ + int err; + uint8_t old_value; + + hfp_ag_lock(ag); + old_value = ag->indicator_value[index]; + if (value == old_value) { + LOG_ERR("Duplicate value setting, indicator %d, old %d -> new %d", index, old_value, + value); + hfp_ag_unlock(ag); + return -EINVAL; + } + + ag->indicator_value[index] = value; + hfp_ag_unlock(ag); + + LOG_DBG("indicator %d, old %d -> new %d", index, old_value, value); + + err = hfp_ag_send_data(ag, cb, user_data, "\r\n+CIEV:%d,%d\r\n", (uint8_t)index + 1, value); + if (err) { + hfp_ag_lock(ag); + ag->indicator_value[index] = old_value; + hfp_ag_unlock(ag); + LOG_ERR("Fail to update indicator %d, current %d", index, old_value); + } + + return err; +} + +static void hfp_ag_close_sco(struct bt_hfp_ag *ag) +{ + LOG_DBG(""); + if (NULL != ag->sco_chan.sco) { + LOG_DBG("Disconnect sco %p", ag->sco_chan.sco); + bt_conn_disconnect(ag->sco_chan.sco, BT_HCI_ERR_LOCALHOST_TERM_CONN); + ag->sco_chan.sco = NULL; + } +} + +static void bt_hfp_ag_reject_cb(struct bt_hfp_ag *ag, void *user_data) +{ + hfp_ag_close_sco(ag); + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_TERMINATE); + + if (bt_ag && bt_ag->reject) { + bt_ag->reject(ag); + } +} + +static void bt_hfp_ag_call_reject(struct bt_hfp_ag *ag, void *user_data) +{ + int err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_reject_cb, user_data); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } +} + +static void bt_hfp_ag_terminate_cb(struct bt_hfp_ag *ag, void *user_data) +{ + hfp_ag_close_sco(ag); + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_TERMINATE); + + if (bt_ag && bt_ag->terminate) { + bt_ag->terminate(ag); + } +} + +static void bt_hfp_ag_unit_call_terminate(struct bt_hfp_ag *ag, void *user_data) +{ + int err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, + user_data); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } +} + +static int bt_hfp_ag_chup_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (ag->call_state == BT_HFP_CALL_ALERTING) { + if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return -ENOTSUP; + } + err = hfp_ag_next_step(ag, bt_hfp_ag_call_reject, NULL); + } else if ((ag->call_state == BT_HFP_CALL_ACTIVE) || (ag->call_state == BT_HFP_CALL_HOLD)) { + err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL); + } else { + return -ENOTSUP; + } + return err; +} + +static uint8_t bt_hfp_get_call_state(struct bt_hfp_ag *ag) +{ + uint8_t status = HFP_AG_CLCC_STATUS_INVALID; + + switch (ag->call_state) { + case BT_HFP_CALL_TERMINATE: + break; + case BT_HFP_CALL_OUTGOING: + status = HFP_AG_CLCC_STATUS_DIALING; + break; + case BT_HFP_CALL_INCOMING: + status = HFP_AG_CLCC_STATUS_INCOMING; + break; + case BT_HFP_CALL_ALERTING: + if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + status = HFP_AG_CLCC_STATUS_WAITING; + } else { + status = HFP_AG_CLCC_STATUS_ALERTING; + } + break; + case BT_HFP_CALL_ACTIVE: + status = HFP_AG_CLCC_STATUS_ACTIVE; + break; + case BT_HFP_CALL_HOLD: + status = HFP_AG_CLCC_STATUS_HELD; + break; + default: + break; + } + + return status; +} + +static int bt_hfp_ag_clcc_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + uint8_t dir; + uint8_t status; + uint8_t mode; + uint8_t mpty; + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (ag->call_state == BT_HFP_CALL_TERMINATE) { + /* AG shall always send OK response to HF */ + return 0; + } + + dir = atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL) ? 1 : 0; + status = bt_hfp_get_call_state(ag); + mode = 0; + mpty = 0; + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+CLCC:%d,%d,%d,%d,%d\r\n", 1, dir, status, mode, + mpty); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + /* AG shall always send OK response to HF */ + return 0; +} + +static int bt_hfp_ag_bia_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + uint32_t number; + int err; + int index = 0; + uint32_t indicator = ag->indicator; + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + while (buf->len > 0) { + err = get_number(buf, &number); + if (err == 0) { + /* Valid number */ + if (number) { + indicator |= BIT(index); + } else { + indicator &= ~BIT(index); + } + } + + if (is_char(buf, ',')) { + index++; + } else { + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + if (buf->len != 0) { + return -ENOTSUP; + } + } + } + + /* Force call, call setup and held call indicators are enabled. */ + indicator = BIT(BT_HFP_AG_CALL_IND) | BIT(BT_HFP_AG_CALL_SETUP_IND) | + BIT(BT_HFP_AG_CALL_HELD_IND); + ag->indicator = indicator; + + return 0; +} + +static void bt_hfp_ag_accept_cb(struct bt_hfp_ag *ag, void *user_data) +{ + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ACTIVE); + + if (bt_ag && bt_ag->accept) { + bt_ag->accept(ag); + } +} + +static void bt_hfp_ag_call_ringing_cb(struct bt_hfp_ag *ag, bool in_bond) +{ + if (bt_ag && bt_ag->ringing) { + bt_ag->ringing(ag, in_bond); + } +} + +static void hfp_ag_sco_connected(struct bt_sco_chan *chan) +{ + struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan); + + if (ag->call_state == BT_HFP_CALL_INCOMING) { + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ALERTING); + bt_hfp_ag_call_ringing_cb(ag, true); + } + + if ((bt_ag) && bt_ag->sco_connected) { + bt_ag->sco_connected(ag, chan->sco); + } +} + +static void hfp_ag_sco_disconnected(struct bt_sco_chan *chan, uint8_t reason) +{ + struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan); + + if ((bt_ag) && bt_ag->sco_disconnected) { + bt_ag->sco_disconnected(ag); + } + + if ((ag->call_state == BT_HFP_CALL_INCOMING) || (ag->call_state == BT_HFP_CALL_OUTGOING)) { + bt_hfp_ag_call_reject(ag, NULL); + } +} + +static struct bt_conn *bt_hfp_ag_create_sco(struct bt_hfp_ag *ag) +{ + struct bt_conn *sco_conn; + + static struct bt_sco_chan_ops ops = { + .connected = hfp_ag_sco_connected, + .disconnected = hfp_ag_sco_disconnected, + }; + + LOG_DBG(""); + + if (ag->sco_chan.sco == NULL) { + ag->sco_chan.ops = &ops; + + /* create SCO connection*/ + sco_conn = bt_conn_create_sco(&ag->acl_conn->br.dst, &ag->sco_chan); + if (sco_conn != NULL) { + LOG_DBG("Created sco %p", sco_conn); + bt_conn_unref(sco_conn); + } + } else { + sco_conn = ag->sco_chan.sco; + } + + return sco_conn; +} + +static int hfp_ag_open_sco(struct bt_hfp_ag *ag) +{ + if (ag->sco_chan.sco == NULL) { + struct bt_conn *sco_conn = bt_hfp_ag_create_sco(ag); + + if (sco_conn == NULL) { + LOG_ERR("Fail to create sco connection!"); + return -ENOTCONN; + } + + LOG_DBG("SCO connection created (%p)", sco_conn); + } + + return 0; +} + +static int bt_hfp_ag_codec_select(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag->selected_codec_id == 0) { + LOG_ERR("Codec is invalid"); + return -EINVAL; + } + + if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) { + LOG_ERR("Codec is unsupported (codec id %d)", ag->selected_codec_id); + return -EINVAL; + } + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BCS:%d\r\n", ag->selected_codec_id); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + return err; +} + +static int bt_hfp_ag_create_audio_connection(struct bt_hfp_ag *ag) +{ + int err; + + if ((ag->hf_codec_ids != 0) && atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED)) { + atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CONN); + err = bt_hfp_ag_codec_select(ag); + } else { + err = hfp_ag_open_sco(ag); + } + + return err; +} + +static void bt_hfp_ag_audio_connection(struct bt_hfp_ag *ag, void *user_data) +{ + int err; + + err = bt_hfp_ag_create_audio_connection(ag); + if (err) { + bt_hfp_ag_unit_call_terminate(ag, user_data); + } +} + +static void bt_hfp_ag_unit_call_accept(struct bt_hfp_ag *ag, void *user_data) +{ + int err; + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 1, bt_hfp_ag_accept_cb, user_data); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_audio_connection, user_data); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } +} + +static int bt_hfp_ag_ata_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (ag->call_state != BT_HFP_CALL_ALERTING) { + return -ENOTSUP; + } + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return -ENOTSUP; + } + + err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_accept, NULL); + + return err; +} + +static int bt_hfp_ag_cops_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + uint32_t number; + + if (is_char(buf, '=')) { + static const uint32_t command_line_prefix[] = {3, 0}; + + for (int i = 0; i < ARRAY_SIZE(command_line_prefix); i++) { + err = get_number(buf, &number); + if (err != 0) { + return -ENOTSUP; + } + + if (command_line_prefix[i] != number) { + return -ENOTSUP; + } + + if (!is_char(buf, ',')) { + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + } + } + + atomic_set_bit(ag->flags, BT_HFP_AG_COPS_SET); + return 0; + } + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_COPS_SET)) { + return -ENOTSUP; + } + + if (!is_char(buf, '?')) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+COPS:%d,%d,\"%s\"\r\n", 0, 0, ag->operator); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + return err; +} + +static int bt_hfp_ag_bcc_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (ag->selected_codec_id == 0) { + return -ENOTSUP; + } + + if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) { + return -ENOTSUP; + } + + if (ag->call_state == BT_HFP_CALL_TERMINATE) { + return -ENOTSUP; + } + + if (ag->sco_chan.sco != NULL) { + return -ENOTSUP; + } + + err = hfp_ag_next_step(ag, bt_hfp_ag_audio_connection, NULL); + + return 0; +} + +static void bt_hfp_ag_unit_codec_conn_setup(struct bt_hfp_ag *ag, void *user_data) +{ + int err = hfp_ag_open_sco(ag); + + if (err) { + bt_hfp_ag_call_reject(ag, user_data); + } +} + +static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + uint32_t number; + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + err = get_number(buf, &number); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CONN)) { + return -ESRCH; + } + + if (ag->selected_codec_id != number) { + LOG_ERR("Received codec id %d is not aligned with selected %d", + number, ag->selected_codec_id); + err = -ENOTSUP; + } else if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) { + LOG_ERR("Selected codec id %d is unsupported %d", + ag->selected_codec_id, ag->hf_codec_ids); + err = -ENOTSUP; + } + + atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CONN); + atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED); + + if (err == 0) { + err = hfp_ag_next_step(ag, bt_hfp_ag_unit_codec_conn_setup, NULL); + } else { + if (ag->call_state != BT_HFP_CALL_TERMINATE) { + (void)hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL); + } + } + + return err; +} + +static void bt_hfp_ag_unit_call_outgoing(struct bt_hfp_ag *ag, void *user_data) +{ + int err = bt_hfp_ag_outgoing(ag, ag->number); + + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } +} + +static int bt_hfp_ag_atd_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + char *number = NULL; + bool is_memory_dial = false; + size_t len; + + if (buf->data[buf->len - 1] != '\r') { + return -ENOTSUP; + } + + if (is_char(buf, '>')) { + is_memory_dial = true; + } + + if ((buf->len - 1) > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN) { + return -ENAMETOOLONG; + } + + buf->data[buf->len - 1] = '\0'; + + if (is_memory_dial) { + if (bt_ag && bt_ag->memory_dial) { + err = bt_ag->memory_dial(ag, &buf->data[0], &number); + if ((err != 0) || (number == NULL)) { + return -ENOTSUP; + } + } else { + return -ENOTSUP; + } + } else { + number = &buf->data[0]; + } + + len = strlen(number); + if (len == 0) { + return -ENOTSUP; + } + + if (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN) { + return -ENAMETOOLONG; + } + + if (ag->call_state != BT_HFP_CALL_TERMINATE) { + return -EBUSY; + } + + /* Copy number to ag->number including null-character */ + memcpy(ag->number, number, len + 1); + + err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL); + + return err; +} + +static int bt_hfp_ag_bldn_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (strlen(ag->number) == 0) { + return -ENOSR; + } + + if (ag->call_state != BT_HFP_CALL_TERMINATE) { + return -EBUSY; + } + + err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL); + + return err; +} + +static int bt_hfp_ag_clip_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + uint32_t clip; + + err = get_number(buf, &clip); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + if (clip > 1) { + return -ENOTSUP; + } + + atomic_set_bit_to(ag->flags, BT_HFP_AG_CLIP_ENABLE, clip == 1); + + return err; +} + +static struct bt_hfp_ag_at_cmd_handler cmd_handlers[] = { + {"AT+BRSF", bt_hfp_ag_brsf_handler}, {"AT+BAC", bt_hfp_ag_bac_handler}, + {"AT+CIND", bt_hfp_ag_cind_handler}, {"AT+CMER", bt_hfp_ag_cmer_handler}, + {"AT+CHLD", bt_hfp_ag_chld_handler}, {"AT+BIND", bt_hfp_ag_bind_handler}, + {"AT+CMEE", bt_hfp_ag_cmee_handler}, {"AT+CHUP", bt_hfp_ag_chup_handler}, + {"AT+CLCC", bt_hfp_ag_clcc_handler}, {"AT+BIA", bt_hfp_ag_bia_handler}, + {"ATA", bt_hfp_ag_ata_handler}, {"AT+COPS", bt_hfp_ag_cops_handler}, + {"AT+BCC", bt_hfp_ag_bcc_handler}, {"AT+BCS", bt_hfp_ag_bcs_handler}, + {"ATD", bt_hfp_ag_atd_handler}, {"AT+BLDN", bt_hfp_ag_bldn_handler}, + {"AT+CLIP", bt_hfp_ag_clip_handler}, +}; + +static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc) +{ + struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc); + + bt_hfp_ag_set_state(ag, BT_HFP_CONFIG); + + LOG_DBG("AG %p", ag); +} + +static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc) +{ + struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc); + + bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTED); + + if ((ag->call_state == BT_HFP_CALL_ALERTING) || (ag->call_state == BT_HFP_CALL_ACTIVE) || + (ag->call_state == BT_HFP_CALL_HOLD)) { + bt_hfp_ag_terminate_cb(ag, NULL); + } + + LOG_DBG("AG %p", ag); +} + +static void hfp_ag_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf) +{ + struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc); + uint8_t *data = buf->data; + uint16_t len = buf->len; + enum at_cme cme_err; + int err = -EOPNOTSUPP; + + LOG_HEXDUMP_DBG(data, len, "Received:"); + + for (uint32_t index = 0; index < ARRAY_SIZE(cmd_handlers); index++) { + if (strlen(cmd_handlers[index].cmd) > len) { + continue; + } + if (strncmp((char *)data, cmd_handlers[index].cmd, + strlen(cmd_handlers[index].cmd)) != 0) { + continue; + } + if (NULL != cmd_handlers[index].handler) { + (void)net_buf_pull(buf, strlen(cmd_handlers[index].cmd)); + err = cmd_handlers[index].handler(ag, buf); + LOG_DBG("AT commander is handled (err %d)", err); + break; + } + } + + if ((err != 0) && atomic_test_bit(ag->flags, BT_HFP_AG_CMEE_ENABLE)) { + cme_err = bt_hfp_ag_get_cme_err(err); + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+CME ERROR:%d\r\n", (uint32_t)cme_err); + } else { + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n%s\r\n", (err == 0) ? "OK" : "ERROR"); + } + + if (err != 0) { + LOG_ERR("HFP AG send response err :(%d)", err); + } +} + +static void bt_hfp_ag_thread(void *p1, void *p2, void *p3) +{ + struct bt_ag_tx *tx; + bt_hfp_ag_tx_cb_t cb; + struct bt_hfp_ag *ag; + void *user_data; + + while (true) { + tx = (struct bt_ag_tx *)k_fifo_get(&ag_tx_notify, K_FOREVER); + + if (tx == NULL) { + continue; + } + + cb = tx->cb; + ag = tx->ag; + user_data = tx->user_data; + + bt_ag_tx_free(tx); + + if (cb) { + cb(ag, user_data); + } + } +} + +static void hfp_ag_sent(struct bt_rfcomm_dlc *dlc, struct net_buf *buf, int err) +{ + struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc); + struct bt_ag_tx *t, *tmp, *tx = NULL; + bool found; + + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ag->tx_pending, t, tmp, node) { + if (t->buf == buf) { + tx = t; + break; + } + } + + if (tx == NULL) { + LOG_ERR("Node %p is not found", tx); + return; + } + + hfp_ag_lock(ag); + found = sys_slist_find_and_remove(&ag->tx_pending, &tx->node); + hfp_ag_unlock(ag); + + if (!found) { + LOG_ERR("Node %p is not found", tx); + } + + k_fifo_put(&ag_tx_notify, tx); +} + +static void bt_ag_deferred_work_cb(struct bt_hfp_ag *ag, void *user_data) +{ + int err; + + LOG_DBG(""); + + switch (ag->call_state) { + case BT_HFP_CALL_TERMINATE: + break; + case BT_HFP_CALL_ACTIVE: + break; + case BT_HFP_CALL_HOLD: + break; + case BT_HFP_CALL_OUTGOING: + __fallthrough; + case BT_HFP_CALL_INCOMING: + __fallthrough; + case BT_HFP_CALL_ALERTING: + __fallthrough; + default: + if (ag->indicator_value[BT_HFP_AG_CALL_SETUP_IND] && + ag->indicator_value[BT_HFP_AG_CALL_IND]) { + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, + BT_HFP_CALL_SETUP_NONE, NULL, NULL); + if (err) { + LOG_ERR("Fail to send indicator"); + bt_hfp_ag_terminate_cb(ag, NULL); + } else { + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, + bt_hfp_ag_terminate_cb, NULL); + if (err) { + LOG_ERR("Fail to send indicator"); + bt_hfp_ag_terminate_cb(ag, NULL); + } + } + } else if (ag->indicator_value[BT_HFP_AG_CALL_SETUP_IND]) { + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, + BT_HFP_CALL_SETUP_NONE, bt_hfp_ag_reject_cb, + NULL); + if (err) { + LOG_ERR("Fail to send indicator"); + bt_hfp_ag_terminate_cb(ag, NULL); + } + } else if (ag->indicator_value[BT_HFP_AG_CALL_IND]) { + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, + bt_hfp_ag_terminate_cb, NULL); + if (err) { + LOG_ERR("Fail to send indicator"); + bt_hfp_ag_terminate_cb(ag, NULL); + } + } + break; + } +} + +static void bt_ag_deferred_work(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct bt_hfp_ag *ag = CONTAINER_OF(dwork, struct bt_hfp_ag, deferred_work); + + (void)hfp_ag_next_step(ag, bt_ag_deferred_work_cb, NULL); +} + +static void bt_ag_ringing_work_cb(struct bt_hfp_ag *ag, void *user_data) +{ + int err; + + LOG_DBG(""); + + if (ag->call_state == BT_HFP_CALL_ALERTING) { + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return; + } + + k_work_reschedule(&ag->ringing_work, + K_SECONDS(CONFIG_BT_HFP_AG_RING_NOTIFY_INTERVAL)); + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\nRING\r\n"); + if (err) { + LOG_ERR("Fail to send RING %d", err); + } else { + if (atomic_test_bit(ag->flags, BT_HFP_AG_CLIP_ENABLE)) { + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+CLIP:\"%s\",%d\r\n", + ag->number, 0); + if (err) { + LOG_ERR("Fail to send CLIP %d", err); + } + } + } + } +} + +static void bt_ag_ringing_work(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct bt_hfp_ag *ag = CONTAINER_OF(dwork, struct bt_hfp_ag, ringing_work); + + (void)hfp_ag_next_step(ag, bt_ag_ringing_work_cb, NULL); +} + +int bt_hfp_ag_connect(struct bt_conn *conn, struct bt_hfp_ag **ag, uint8_t channel) +{ + int i; + int err; + + static struct bt_rfcomm_dlc_ops ops = { + .connected = hfp_ag_connected, + .disconnected = hfp_ag_disconnected, + .recv = hfp_ag_recv, + .sent = hfp_ag_sent, + }; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + *ag = NULL; + + if (ag_thread_id == NULL) { + + k_fifo_init(&ag_tx_free); + k_fifo_init(&ag_tx_notify); + + for (i = 0; i < ARRAY_SIZE(ag_tx); i++) { + k_fifo_put(&ag_tx_free, &ag_tx[i]); + } + + ag_thread_id = k_thread_create( + &ag_thread, ag_thread_stack, K_KERNEL_STACK_SIZEOF(ag_thread_stack), + bt_hfp_ag_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_HFP_AG_THREAD_PRIO), 0, K_NO_WAIT); + if (ag_thread_id == NULL) { + return -ENOMEM; + } + k_thread_name_set(ag_thread_id, "HFP AG"); + } + + for (i = 0; i < ARRAY_SIZE(bt_hfp_ag_pool); i++) { + struct bt_hfp_ag *_ag = &bt_hfp_ag_pool[i]; + + if (_ag->rfcomm_dlc.session) { + continue; + } + + (void)memset(_ag, 0, sizeof(struct bt_hfp_ag)); + + sys_slist_init(&_ag->tx_pending); + + k_sem_init(&_ag->lock, 1, 1); + + _ag->rfcomm_dlc.ops = &ops; + _ag->rfcomm_dlc.mtu = BT_HFP_MAX_MTU; + + /* Set the supported features*/ + _ag->ag_features = BT_HFP_AG_SUPPORTED_FEATURES; + + /* If supported codec ids cannot be notified, disable codec negotiation. */ + if (!(bt_ag && bt_ag->codec)) { + _ag->ag_features &= ~BT_HFP_AG_FEATURE_CODEC_NEG; + } + + _ag->hf_features = 0; + _ag->hf_codec_ids = 0; + + _ag->acl_conn = conn; + + /* Set AG indicator value */ + _ag->indicator_value[BT_HFP_AG_SERVICE_IND] = 0; + _ag->indicator_value[BT_HFP_AG_CALL_IND] = 0; + _ag->indicator_value[BT_HFP_AG_CALL_SETUP_IND] = 0; + _ag->indicator_value[BT_HFP_AG_CALL_HELD_IND] = 0; + _ag->indicator_value[BT_HFP_AG_SIGNAL_IND] = 0; + _ag->indicator_value[BT_HFP_AG_ROAM_IND] = 0; + _ag->indicator_value[BT_HFP_AG_BATTERY_IND] = 0; + + /* Set AG indicator status */ + _ag->indicator = BIT(BT_HFP_AG_SERVICE_IND) | BIT(BT_HFP_AG_CALL_IND) | + BIT(BT_HFP_AG_CALL_SETUP_IND) | BIT(BT_HFP_AG_CALL_HELD_IND) | + BIT(BT_HFP_AG_SIGNAL_IND) | BIT(BT_HFP_AG_ROAM_IND) | + BIT(BT_HFP_AG_BATTERY_IND); + + /* Set AG operator */ + memcpy(_ag->operator, "UNKNOWN", sizeof("UNKNOWN")); + + /* Set Codec ID*/ + _ag->selected_codec_id = BT_HFP_AG_CODEC_CVSD; + + /* Init delay work */ + k_work_init_delayable(&_ag->deferred_work, bt_ag_deferred_work); + + k_work_init_delayable(&_ag->ringing_work, bt_ag_ringing_work); + + atomic_set_bit(_ag->flags, BT_HFP_AG_CODEC_CHANGED); + + *ag = _ag; + } + + if (*ag == NULL) { + return -ENOMEM; + } + + err = bt_rfcomm_dlc_connect(conn, &(*ag)->rfcomm_dlc, channel); + if (err != 0) { + (void)memset(*ag, 0, sizeof(struct bt_hfp_ag)); + *ag = NULL; + } else { + bt_hfp_ag_set_state(*ag, BT_HFP_CONNECTING); + } + + return err; +} + +int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTING); + + if ((ag->call_state == BT_HFP_CALL_ACTIVE) || (ag->call_state == BT_HFP_CALL_HOLD)) { + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, + NULL); + if (err != 0) { + LOG_ERR("HFP AG send response err :(%d)", err); + } + return err; + } else if (ag->call_state != BT_HFP_CALL_TERMINATE) { + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_reject_cb, NULL); + if (err != 0) { + LOG_ERR("HFP AG send response err :(%d)", err); + } + return err; + } + + return bt_rfcomm_dlc_disconnect(&ag->rfcomm_dlc); +} + +int bt_hfp_ag_register(struct bt_hfp_ag_cb *cb) +{ + if (!cb) { + return -EINVAL; + } + + if (bt_ag) { + return -EALREADY; + } + + bt_ag = cb; + + return 0; +} + +static void bt_hfp_ag_incoming_cb(struct bt_hfp_ag *ag, void *user_data) +{ + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_INCOMING); + + if (bt_ag && bt_ag->incoming) { + bt_ag->incoming(ag, ag->number); + } + + if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) { + int err; + + err = bt_hfp_ag_create_audio_connection(ag); + if (err) { + bt_hfp_ag_call_reject(ag, NULL); + } + } else { + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ALERTING); + bt_hfp_ag_call_ringing_cb(ag, false); + } +} + +int bt_hfp_ag_remote_incoming(struct bt_hfp_ag *ag, const char *number) +{ + int err = 0; + size_t len; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if (ag->call_state != BT_HFP_CALL_TERMINATE) { + return -EBUSY; + } + + len = strlen(number); + if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) { + return -EINVAL; + } + + /* Copy number to ag->number including null-character */ + memcpy(ag->number, number, len + 1); + + atomic_set_bit(ag->flags, BT_HFP_AG_INCOMING_CALL); + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_INCOMING, + bt_hfp_ag_incoming_cb, NULL); + if (err != 0) { + atomic_clear_bit(ag->flags, BT_HFP_AG_INCOMING_CALL); + } + + return err; +} + +int bt_hfp_ag_reject(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_INCOMING)) { + return -EINVAL; + } + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_reject_cb, NULL); + + return err; +} + +int bt_hfp_ag_accept(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if (ag->call_state != BT_HFP_CALL_ALERTING) { + return -EINVAL; + } + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 1, bt_hfp_ag_accept_cb, NULL); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_audio_connection, NULL); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + return err; +} + +int bt_hfp_ag_terminate(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) { + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL); + + return err; +} + +static void bt_hfp_ag_outgoing_cb(struct bt_hfp_ag *ag, void *user_data) +{ + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_OUTGOING); + + if (bt_ag && bt_ag->outgoing) { + bt_ag->outgoing(ag, ag->number); + } + + if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) { + int err; + + err = bt_hfp_ag_create_audio_connection(ag); + if (err) { + bt_hfp_ag_call_reject(ag, NULL); + } + } +} + +int bt_hfp_ag_outgoing(struct bt_hfp_ag *ag, const char *number) +{ + int err = 0; + size_t len; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if (ag->call_state != BT_HFP_CALL_TERMINATE) { + return -EBUSY; + } + + len = strlen(number); + if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) { + return -EINVAL; + } + + /* Copy number to ag->number including null-character */ + memcpy(ag->number, number, len + 1); + + atomic_clear_bit(ag->flags, BT_HFP_AG_INCOMING_CALL); + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_OUTGOING, + bt_hfp_ag_outgoing_cb, NULL); + + return err; +} + +static void bt_hfp_ag_ringing_cb(struct bt_hfp_ag *ag, void *user_data) +{ + bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ALERTING); + + if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) { + bt_hfp_ag_call_ringing_cb(ag, true); + } else { + bt_hfp_ag_call_ringing_cb(ag, false); + } +} + +int bt_hfp_ag_remote_ringing(struct bt_hfp_ag *ag) +{ + int err = 0; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if (BT_HFP_CALL_OUTGOING != ag->call_state) { + return -EBUSY; + } + + if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) { + if (ag->sco_chan.sco == NULL) { + return -ENOTCONN; + } + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, + BT_HFP_CALL_SETUP_REMOTE_ALERTING, bt_hfp_ag_ringing_cb, + NULL); + + return err; +} + +int bt_hfp_ag_remote_reject(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_OUTGOING)) { + return -EINVAL; + } + + if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_reject_cb, NULL); + + return err; +} + +int bt_hfp_ag_remote_accept(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if (ag->call_state != BT_HFP_CALL_ALERTING) { + return -EINVAL; + } + + if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 1, bt_hfp_ag_accept_cb, NULL); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, + bt_hfp_ag_audio_connection, NULL); + if (err != 0) { + LOG_ERR("Fail to send err :(%d)", err); + } + + return err; +} + +int bt_hfp_ag_remote_terminate(struct bt_hfp_ag *ag) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) { + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL); + + return err; +} + +int bt_hfp_ag_set_indicator(struct bt_hfp_ag *ag, enum bt_hfp_ag_indicator index, uint8_t value) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + switch (index) { + case BT_HFP_AG_SERVICE_IND: + __fallthrough; + case BT_HFP_AG_SIGNAL_IND: + __fallthrough; + case BT_HFP_AG_ROAM_IND: + __fallthrough; + case BT_HFP_AG_BATTERY_IND: + if ((ag_ind[(uint8_t)index].min > value) || (ag_ind[(uint8_t)index].max < value)) { + return -EINVAL; + } + break; + case BT_HFP_AG_CALL_IND: + __fallthrough; + case BT_HFP_AG_CALL_SETUP_IND: + __fallthrough; + case BT_HFP_AG_CALL_HELD_IND: + __fallthrough; + default: + return -EINVAL; + } + + err = hfp_ag_update_indicator(ag, index, value, NULL, NULL); + + return err; +} + +int bt_hfp_ag_set_operator(struct bt_hfp_ag *ag, char *name) +{ + int len; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + len = strlen(name); + len = MIN(sizeof(ag->operator) - 1, len); + memcpy(ag->operator, name, len); + ag->operator[len] = '\0'; + + return 0; +} + +int bt_hfp_ag_select_codec(struct bt_hfp_ag *ag, uint8_t id) +{ + int err; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + if (ag->state != BT_HFP_CONNECTED) { + return -ENOTCONN; + } + + if (!(ag->hf_codec_ids && BIT(id))) { + return -ENOTSUP; + } + + if (atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CONN)) { + return -EBUSY; + } + + ag->selected_codec_id = id; + atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED); + + err = bt_hfp_ag_create_audio_connection(ag); + + return err; +} diff --git a/subsys/bluetooth/host/classic/hfp_ag_internal.h b/subsys/bluetooth/host/classic/hfp_ag_internal.h new file mode 100644 index 00000000000000..82b3aa88131d1c --- /dev/null +++ b/subsys/bluetooth/host/classic/hfp_ag_internal.h @@ -0,0 +1,135 @@ +/** @file + * @brief Internal APIs for Bluetooth Handsfree profile handling. + */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* HFP AG Supported features */ +#define BT_HFP_AG_SUPPORTED_FEATURES (BT_HFP_AG_FEATURE_INBAND_RINGTONE | BT_HFP_AG_FEATURE_EXT_ERR) + +/* bt_hfp_ag flags: the flags defined here represent HFP AG parameters */ +enum { + BT_HFP_AG_CMEE_ENABLE, /* Extended Audio Gateway Error Result Code */ + BT_HFP_AG_CMER_ENABLE, /* Indicator Events Reporting */ + BT_HFP_AG_CLIP_ENABLE, /* Calling Line Identification notification */ + BT_HFP_AG_INBAND_RING, /* In-band ring */ + BT_HFP_AG_COPS_SET, /* Query Operator selection */ + BT_HFP_AG_INCOMING_CALL, /* Incoming call */ + BT_HFP_AG_CODEC_CONN, /* Codec connection is ongoing */ + BT_HFP_AG_CODEC_CHANGED, /* Codec Id Changed */ + + /* Total number of flags - must be at the end of the enum */ + BT_HFP_AG_NUM_FLAGS, +}; + +/* HFP HF Indicators */ +enum { + HFP_HF_ENHANCED_SAFETY_IND = 1, /* Enhanced Safety */ + HFP_HF_BATTERY_LEVEL_IND = 2, /* Remaining level of Battery */ + HFP_HF_IND_MAX +}; + +typedef enum __packed { + /** Session disconnected */ + BT_HFP_DISCONNECTED, + /** Session in connecting state */ + BT_HFP_CONNECTING, + /** Session in config state, HFP configuration */ + BT_HFP_CONFIG, + /** Session ready for upper layer traffic on it */ + BT_HFP_CONNECTED, + /** Session in disconnecting state */ + BT_HFP_DISCONNECTING, +} bt_hfp_state_t; + +typedef enum __packed { + /** Call terminate */ + BT_HFP_CALL_TERMINATE, + /** Call outgoing */ + BT_HFP_CALL_OUTGOING, + /** Call incoming */ + BT_HFP_CALL_INCOMING, + /** Call alerting */ + BT_HFP_CALL_ALERTING, + /** Call active */ + BT_HFP_CALL_ACTIVE, + /** Call hold */ + BT_HFP_CALL_HOLD, +} bt_hfp_call_state_t; + +#define AT_COPS_OPERATOR_MAX_LEN 16 + +struct bt_hfp_ag { + struct bt_rfcomm_dlc rfcomm_dlc; + char buffer[HF_MAX_BUF_LEN]; + uint32_t hf_features; + uint32_t ag_features; + + /* HF Supported Codec Ids*/ + uint32_t hf_codec_ids; + uint8_t selected_codec_id; + + ATOMIC_DEFINE(flags, BT_HFP_AG_NUM_FLAGS); + + /* ACL Connection Object */ + struct bt_conn *acl_conn; + + /* HFP Connection state */ + bt_hfp_state_t state; + + /* HFP Call state */ + bt_hfp_call_state_t call_state; + + /* Delayed work deferred tasks: + * - call status cleanup. + */ + struct k_work_delayable deferred_work; + + /* AG Indicators */ + uint8_t indicator_value[BT_HFP_AG_IND_MAX]; + uint32_t indicator; + + /* HF Indicators */ + uint32_t hf_indicators_of_ag; + uint32_t hf_indicators_of_hf; + uint8_t hf_indicator_value[HFP_HF_IND_MAX]; + + /* operator */ + char operator[AT_COPS_OPERATOR_MAX_LEN + 1]; + + /* SCO Connection Object */ + struct bt_sco_chan sco_chan; + /* HFP TX pending */ + sys_slist_t tx_pending; + + /* Dial number or incoming number */ + char number[CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN + 1]; + + /* Calling Line Identification notification */ + struct k_work_delayable ringing_work; + + /* Critical locker */ + struct k_sem lock; +}; + +/* Active */ +#define HFP_AG_CLCC_STATUS_ACTIVE 0 +/* Held */ +#define HFP_AG_CLCC_STATUS_HELD 1 +/* Dialing (outgoing calls only) */ +#define HFP_AG_CLCC_STATUS_DIALING 2 +/* Alerting (outgoing calls only) */ +#define HFP_AG_CLCC_STATUS_ALERTING 3 +/* Incoming (incoming calls only) */ +#define HFP_AG_CLCC_STATUS_INCOMING 4 +/* Waiting (incoming calls only) */ +#define HFP_AG_CLCC_STATUS_WAITING 5 +/* Call held by Response and Hold */ +#define HFP_AG_CLCC_STATUS_CALL_HELD_HOLD 6 +/* Invalid status */ +#define HFP_AG_CLCC_STATUS_INVALID 0xFFU diff --git a/subsys/bluetooth/host/classic/hfp_internal.h b/subsys/bluetooth/host/classic/hfp_internal.h index 50c883fedec1ba..116807187046e9 100644 --- a/subsys/bluetooth/host/classic/hfp_internal.h +++ b/subsys/bluetooth/host/classic/hfp_internal.h @@ -8,41 +8,44 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define BT_HFP_MAX_MTU 140 -#define BT_HF_CLIENT_MAX_PDU BT_HFP_MAX_MTU +#define BT_HFP_MAX_MTU 140 +#define BT_HF_CLIENT_MAX_PDU BT_HFP_MAX_MTU /* HFP AG Features */ -#define BT_HFP_AG_FEATURE_3WAY_CALL 0x00000001 /* Three-way calling */ -#define BT_HFP_AG_FEATURE_ECNR 0x00000002 /* EC and/or NR function */ -#define BT_HFP_AG_FEATURE_VOICE_RECG 0x00000004 /* Voice recognition */ -#define BT_HFP_AG_INBAND_RING_TONE 0x00000008 /* In-band ring capability */ -#define BT_HFP_AG_VOICE_TAG 0x00000010 /* Attach no. to voice tag */ -#define BT_HFP_AG_FEATURE_REJECT_CALL 0x00000020 /* Ability to reject call */ -#define BT_HFP_AG_FEATURE_ECS 0x00000040 /* Enhanced call status */ -#define BT_HFP_AG_FEATURE_ECC 0x00000080 /* Enhanced call control */ -#define BT_HFP_AG_FEATURE_EXT_ERR 0x00000100 /* Extended error codes */ -#define BT_HFP_AG_FEATURE_CODEC_NEG 0x00000200 /* Codec negotiation */ -#define BT_HFP_AG_FEATURE_HF_IND 0x00000400 /* HF Indicators */ -#define BT_HFP_AG_FEARTURE_ESCO_S4 0x00000800 /* eSCO S4 Settings */ +#define BT_HFP_AG_FEATURE_3WAY_CALL 0x00000001 /* Three-way calling */ +#define BT_HFP_AG_FEATURE_ECNR 0x00000002 /* EC and/or NR function */ +#define BT_HFP_AG_FEATURE_VOICE_RECG 0x00000004 /* Voice recognition */ +#define BT_HFP_AG_FEATURE_INBAND_RINGTONE 0x00000008 /* In-band ring capability */ +#define BT_HFP_AG_FEATURE_VOICE_TAG 0x00000010 /* Attach no. to voice tag */ +#define BT_HFP_AG_FEATURE_REJECT_CALL 0x00000020 /* Ability to reject call */ +#define BT_HFP_AG_FEATURE_ECS 0x00000040 /* Enhanced call status */ +#define BT_HFP_AG_FEATURE_ECC 0x00000080 /* Enhanced call control */ +#define BT_HFP_AG_FEATURE_EXT_ERR 0x00000100 /* Extended error codes */ +#define BT_HFP_AG_FEATURE_CODEC_NEG 0x00000200 /* Codec negotiation */ +#define BT_HFP_AG_FEATURE_HF_IND 0x00000400 /* HF Indicators */ +#define BT_HFP_AG_FEATURE_ESCO_S4 0x00000800 /* eSCO S4 Settings */ +#define BT_HFP_AG_FEATURE_ENH_VOICE_RECG 0x00001000 /* Enhanced Voice Recognition Status */ +#define BT_HFP_AG_FEATURE_VOICE_RECG_TEXT 0x00002000 /* Voice Recognition Text */ /* HFP HF Features */ -#define BT_HFP_HF_FEATURE_ECNR 0x00000001 /* EC and/or NR */ -#define BT_HFP_HF_FEATURE_3WAY_CALL 0x00000002 /* Three-way calling */ -#define BT_HFP_HF_FEATURE_CLI 0x00000004 /* CLI presentation */ -#define BT_HFP_HF_FEATURE_VOICE_RECG 0x00000008 /* Voice recognition */ -#define BT_HFP_HF_FEATURE_VOLUME 0x00000010 /* Remote volume control */ -#define BT_HFP_HF_FEATURE_ECS 0x00000020 /* Enhanced call status */ -#define BT_HFP_HF_FEATURE_ECC 0x00000040 /* Enhanced call control */ -#define BT_HFP_HF_FEATURE_CODEC_NEG 0x00000080 /* CODEC Negotiation */ -#define BT_HFP_HF_FEATURE_HF_IND 0x00000100 /* HF Indicators */ -#define BT_HFP_HF_FEATURE_ESCO_S4 0x00000200 /* eSCO S4 Settings */ +#define BT_HFP_HF_FEATURE_ECNR 0x00000001 /* EC and/or NR function */ +#define BT_HFP_HF_FEATURE_3WAY_CALL 0x00000002 /* Three-way calling */ +#define BT_HFP_HF_FEATURE_CLI 0x00000004 /* CLI presentation */ +#define BT_HFP_HF_FEATURE_VOICE_RECG 0x00000008 /* Voice recognition */ +#define BT_HFP_HF_FEATURE_VOLUME 0x00000010 /* Remote volume control */ +#define BT_HFP_HF_FEATURE_ECS 0x00000020 /* Enhanced call status */ +#define BT_HFP_HF_FEATURE_ECC 0x00000040 /* Enhanced call control */ +#define BT_HFP_HF_FEATURE_CODEC_NEG 0x00000080 /* CODEC Negotiation */ +#define BT_HFP_HF_FEATURE_HF_IND 0x00000100 /* HF Indicators */ +#define BT_HFP_HF_FEATURE_ESCO_S4 0x00000200 /* eSCO S4 Settings */ +#define BT_HFP_HF_FEATURE_ENH_VOICE_RECG 0x00000400 /* Enhanced Voice Recognition Status */ +#define BT_HFP_HF_FEATURE_VOICE_RECG_TEXT 0x00000800 /* Voice Recognition Text */ /* HFP HF Supported features */ -#define BT_HFP_HF_SUPPORTED_FEATURES (BT_HFP_HF_FEATURE_CLI | \ - BT_HFP_HF_FEATURE_VOLUME) +#define BT_HFP_HF_SUPPORTED_FEATURES (BT_HFP_HF_FEATURE_CLI | BT_HFP_HF_FEATURE_VOLUME) -#define HF_MAX_BUF_LEN BT_HF_CLIENT_MAX_PDU -#define HF_MAX_AG_INDICATORS 20 +#define HF_MAX_BUF_LEN BT_HF_CLIENT_MAX_PDU +#define HF_MAX_AG_INDICATORS 20 struct bt_hfp_hf { struct bt_rfcomm_dlc rfcomm_dlc; @@ -66,3 +69,9 @@ enum hfp_hf_ag_indicators { HF_ROAM_IND, HF_BATTERY_IND }; + +/* HFP call setup status */ +#define BT_HFP_CALL_SETUP_NONE 0 +#define BT_HFP_CALL_SETUP_INCOMING 1 +#define BT_HFP_CALL_SETUP_OUTGOING 2 +#define BT_HFP_CALL_SETUP_REMOTE_ALERTING 3 From 813b9e7871e7488a9b672750358206f4466837e7 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0769/1389] include: Bluetooth: Add BT COD macros to hci_types.h Add macros to get Major Service Classes, Major Device Class and Minor Device Class. Define Major Device Class code. Define Minor Device Class field for Computer Major Class. Define Minor Device Class field for Phone Major Class. Define Minor Device Class field for Audio/Video Major Class. Signed-off-by: Lyle Zhu --- include/zephyr/bluetooth/hci_types.h | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index cbcbf4ea503be7..2e91eda5c13c86 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -567,6 +567,66 @@ struct bt_hci_rp_write_conn_accept_timeout { #define BT_BREDR_SCAN_INQUIRY 0x01 #define BT_BREDR_SCAN_PAGE 0x02 +#define BT_COD(major_service, major_device, minor_device) \ + (((uint32_t)major_service << 13) | ((uint32_t)major_device << 8) | \ + ((uint32_t)minor_device << 2)) +#define BT_COD_VALID(cod) ((0 == (cod[0] & (BIT(0) | BIT(1)))) ? true : false) +#define BT_COD_MAJOR_SERVICE_CLASSES(cod) \ + ((((uint32_t)cod[2] & 0xFF) >> 5) | (((uint32_t)cod[1] & 0xD0) >> 5)) +#define BT_COD_MAJOR_DEVICE_CLASS(cod) ((((uint32_t)cod[1]) & 0x1FUL)) +#define BT_COD_MINOR_DEVICE_CLASS(cod) (((((uint32_t)cod[0]) & 0xFF) >> 2)) + +#define BT_COD_MAJOR_MISC 0x00 +#define BT_COD_MAJOR_COMPUTER 0x01 +#define BT_COD_MAJOR_PHONE 0x02 +#define BT_COD_MAJOR_LAN_NETWORK_AP 0x03 +#define BT_COD_MAJOR_AUDIO_VIDEO 0x04 +#define BT_COD_MAJOR_PERIPHERAL 0x05 +#define BT_COD_MAJOR_IMAGING 0x06 +#define BT_COD_MAJOR_WEARABLE 0x07 +#define BT_COD_MAJOR_TOY 0x08 +#define BT_COD_MAJOR_HEALTH 0x09 +#define BT_COD_MAJOR_UNCATEGORIZED 0x1F + +/* Minor Device Class field - Computer Major Class */ +#define BT_COD_MAJOR_COMPUTER_MINOR_UNCATEGORIZED 0x00 +#define BT_COD_MAJOR_COMPUTER_MINOR_DESKTOP 0x01 +#define BT_COD_MAJOR_COMPUTER_MINOR_SERVER_CLASS_COMPUTER 0x02 +#define BT_COD_MAJOR_COMPUTER_MINOR_LAPTOP 0x03 +#define BT_COD_MAJOR_COMPUTER_MINOR_HANDHELD_PC_PDA 0x04 +#define BT_COD_MAJOR_COMPUTER_MINOR_PALM_SIZE_PC_PDA 0x05 +#define BT_COD_MAJOR_COMPUTER_MINOR_WEARABLE_COMPUTER 0x06 +#define BT_COD_MAJOR_COMPUTER_MINOR_TABLET 0x07 + +/* Minor Device Class field - Phone Major Class */ +#define BT_COD_MAJOR_PHONE_MINOR_UNCATEGORIZED 0x00 +#define BT_COD_MAJOR_PHONE_MINOR_CELLULAR 0x01 +#define BT_COD_MAJOR_PHONE_MINOR_CORDLESS 0x02 +#define BT_COD_MAJOR_PHONE_MINOR_SMARTPHONE 0x03 +#define BT_COD_MAJOR_PHONE_MINOR_WIRED_MODEM_VOICE_GATEWAY 0x04 +#define BT_COD_MAJOR_PHONE_MINOR_ISDN 0x05 + +/* Minor Device Class field - Audio/Video Major Class */ +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_UNCATEGORIZED 0x00 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_WEARABLE_HEADSET 0x01 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HANDS_FREE 0x02 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_RFU 0x03 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_MICROPHONE 0x04 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_LOUDSPEAKER 0x05 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HEADPHONES 0x06 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_PORTABLE_AUDIO 0x07 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_CAR_AUDIO 0x08 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_SET_TOP_BOX 0x09 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HIFI_AUDIO 0x0A +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VCR 0x0B +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_CAMERA 0x0C +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_CAMCORDER 0x0D +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_MONITOR 0x0E +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_DISPLAY_LOUDSPEAKER 0x0F +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_CONFERENCING 0x10 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_RFU2 0x11 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_GAME_TOY 0x12 + #define BT_HCI_OP_WRITE_CLASS_OF_DEVICE BT_OP(BT_OGF_BASEBAND, 0x0024) /* 0x0c24 */ struct bt_hci_cp_write_class_of_device { uint8_t class_of_device[3]; From 8f272766f86bd1fb3c91abe74a90f53154c17fbd Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0770/1389] samples: Bluetooth: HFP_AG: Initialize version Add a new example handsfree_ag to demonstrate usage of the handsfree audio gateway APIs. Signed-off-by: Lyle Zhu --- samples/bluetooth/handsfree_ag/CMakeLists.txt | 10 + samples/bluetooth/handsfree_ag/Kconfig | 24 ++ samples/bluetooth/handsfree_ag/README.rst | 23 ++ samples/bluetooth/handsfree_ag/prj.conf | 6 + samples/bluetooth/handsfree_ag/sample.yaml | 13 + samples/bluetooth/handsfree_ag/src/main.c | 384 ++++++++++++++++++ 6 files changed, 460 insertions(+) create mode 100644 samples/bluetooth/handsfree_ag/CMakeLists.txt create mode 100644 samples/bluetooth/handsfree_ag/Kconfig create mode 100644 samples/bluetooth/handsfree_ag/README.rst create mode 100644 samples/bluetooth/handsfree_ag/prj.conf create mode 100644 samples/bluetooth/handsfree_ag/sample.yaml create mode 100644 samples/bluetooth/handsfree_ag/src/main.c diff --git a/samples/bluetooth/handsfree_ag/CMakeLists.txt b/samples/bluetooth/handsfree_ag/CMakeLists.txt new file mode 100644 index 00000000000000..af90adf8b82e29 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/CMakeLists.txt @@ -0,0 +1,10 @@ +#SPDX - License - Identifier : Apache - 2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(handsfree_ag) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/handsfree_ag/Kconfig b/samples/bluetooth/handsfree_ag/Kconfig new file mode 100644 index 00000000000000..f3a1edbcdc9b15 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/Kconfig @@ -0,0 +1,24 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +mainmenu "Bluetooth: handsfree AG" + +config BT_HFP_AG_DISCOVER_RESULT_COUNT + int "Maximum result count per device discovery" + default 10 + +config BT_HFP_AG_CALL_OUTGOING + bool "The simulate call: outgoing (y), incoming (n)" + +config BT_HFP_AG_START_CALL_DELAY_TIME + int "The delay time used to start simulating a call after AG connection" + default 5000 + help + The Delay time is used to wait for the peer to start dialing. If the + peer does not dial within the timeout period, AG satrt simulating a + call. The unit is ms. + +source "Kconfig.zephyr" diff --git a/samples/bluetooth/handsfree_ag/README.rst b/samples/bluetooth/handsfree_ag/README.rst new file mode 100644 index 00000000000000..9d2e2d9343aca3 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/README.rst @@ -0,0 +1,23 @@ +.. _bt_handsfree_ag: + +Bluetooth: Handsfree Audio Gateway +################################## + +Overview +******** + +Application demonstrating usage of the Hands-free Audio Gateway (AG) APIs. + +Requirements +************ + +* Running on the host with Bluetooth BR/EDR (Classic) support, or +* A board with Bluetooth BR/EDR (Classic) support + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/bluetooth/handsfree_ag` in +the Zephyr tree. + +See :ref:`bluetooth samples section ` for details. diff --git a/samples/bluetooth/handsfree_ag/prj.conf b/samples/bluetooth/handsfree_ag/prj.conf new file mode 100644 index 00000000000000..cd315ed26b8b7f --- /dev/null +++ b/samples/bluetooth/handsfree_ag/prj.conf @@ -0,0 +1,6 @@ +CONFIG_BT=y +CONFIG_BT_CLASSIC=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_HFP_AG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_DEVICE_NAME="Handsfree-ag" diff --git a/samples/bluetooth/handsfree_ag/sample.yaml b/samples/bluetooth/handsfree_ag/sample.yaml new file mode 100644 index 00000000000000..416834fc191e89 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/sample.yaml @@ -0,0 +1,13 @@ +sample: + name: Bluetooth Handsfree Audio Gateway +tests: + sample.bluetooth.handsfree.ag: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + tags: bluetooth + integration_platforms: + - qemu_cortex_m3 + extra_configs: + - CONFIG_BT_HFP_AG_CALL_OUTGOING=y diff --git a/samples/bluetooth/handsfree_ag/src/main.c b/samples/bluetooth/handsfree_ag/src/main.c new file mode 100644 index 00000000000000..03c76eb0805b5b --- /dev/null +++ b/samples/bluetooth/handsfree_ag/src/main.c @@ -0,0 +1,384 @@ +/* main.c - Application main entry point */ + +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static struct bt_conn *default_conn; +struct bt_hfp_ag *hfp_ag; + +static struct bt_br_discovery_param br_discover; + +static struct bt_br_discovery_param br_discover; +static struct bt_br_discovery_result scan_result[CONFIG_BT_HFP_AG_DISCOVER_RESULT_COUNT]; + +struct k_work discover_work; +struct k_work_delayable call_connect_work; +struct k_work_delayable call_disconnect_work; + +struct k_work_delayable call_remote_ringing_work; +struct k_work_delayable call_remote_accept_work; + +NET_BUF_POOL_DEFINE(sdp_discover_pool, 10, BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static void ag_connected(struct bt_hfp_ag *ag) +{ + printk("HFP AG connected!\n"); + k_work_schedule(&call_connect_work, K_MSEC(CONFIG_BT_HFP_AG_START_CALL_DELAY_TIME)); +} + +static void ag_disconnected(struct bt_hfp_ag *ag) +{ + printk("HFP AG disconnected!\n"); +} + +static void ag_sco_connected(struct bt_hfp_ag *ag, struct bt_conn *sco_conn) +{ + printk("HFP AG SCO connected!\n"); +} + +static void ag_sco_disconnected(struct bt_hfp_ag *ag) +{ + printk("HFP AG SCO disconnected!\n"); +} + +static void ag_ringing(struct bt_hfp_ag *ag, bool in_band) +{ + printk("Ringing (in bond? %s)\n", in_band ? "Yes" : "No"); +} + +static void ag_accept(struct bt_hfp_ag *ag) +{ + printk("Call Accepted\n"); + k_work_schedule(&call_disconnect_work, K_SECONDS(10)); +} + +static void ag_reject(struct bt_hfp_ag *ag) +{ + printk("Call Rejected\n"); + k_work_schedule(&call_disconnect_work, K_SECONDS(1)); +} + +static void ag_terminate(struct bt_hfp_ag *ag) +{ + printk("Call terminated\n"); + k_work_schedule(&call_disconnect_work, K_SECONDS(1)); +} + +static void ag_outgoing(struct bt_hfp_ag *ag, const char *number) +{ + printk("Call outgoing, remote number %s\n", number); + k_work_cancel_delayable(&call_connect_work); + k_work_schedule(&call_remote_ringing_work, K_SECONDS(1)); +} + +static void ag_incoming(struct bt_hfp_ag *ag, const char *number) +{ + printk("Incoming call, remote number %s\n", number); + k_work_cancel_delayable(&call_connect_work); +} + +static struct bt_hfp_ag_cb ag_cb = { + .connected = ag_connected, + .disconnected = ag_disconnected, + .sco_connected = ag_sco_connected, + .sco_disconnected = ag_sco_disconnected, + .outgoing = ag_outgoing, + .incoming = ag_incoming, + .ringing = ag_ringing, + .accept = ag_accept, + .reject = ag_reject, + .terminate = ag_terminate, +}; + +static uint8_t sdp_discover_cb(struct bt_conn *conn, struct bt_sdp_client_result *result) +{ + int err; + uint16_t value; + + printk("Discover done\n"); + + if (result->resp_buf != NULL) { + err = bt_sdp_get_proto_param(result->resp_buf, BT_SDP_PROTO_RFCOMM, &value); + + if (err != 0) { + printk("Fail to parser RFCOMM the SDP response!\n"); + } else { + printk("The server channel is %d\n", value); + err = bt_hfp_ag_connect(conn, &hfp_ag, value); + if (err != 0) { + printk("Fail to create hfp AG connection (err %d)\n", err); + } + } + } + + return BT_SDP_DISCOVER_UUID_STOP; +} + +static struct bt_sdp_discover_params sdp_discover = { + .func = sdp_discover_cb, + .pool = &sdp_discover_pool, + .uuid = BT_UUID_DECLARE_16(BT_SDP_HANDSFREE_SVCLASS), +}; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + int res; + + if (err) { + if (default_conn != NULL) { + default_conn = NULL; + } + printk("Connection failed (err 0x%02x)\n", err); + } else { + if (default_conn == conn) { + struct bt_conn_info info; + + bt_conn_get_info(conn, &info); + if (info.type != BT_CONN_TYPE_BR) { + return; + } + + /* + * Do an SDP Query on Successful ACL connection complete with the + * required device + */ + res = bt_sdp_discover(default_conn, &sdp_discover); + if (res) { + printk("SDP discovery failed (err %d)\r\n", res); + } else { + printk("SDP discovery started\r\n"); + } + printk("Connected\n"); + } + } +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + printk("Disconnected (reason 0x%02x)\n", reason); + + if (default_conn != conn) { + return; + } + + if (default_conn) { + default_conn = NULL; + } else { + return; + } +} + +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + struct bt_conn_info info; + + bt_conn_get_info(conn, &info); + + bt_addr_to_str(info.br.dst, addr, sizeof(addr)); + + printk("Security changed: %s level %u (err %d)\n", addr, level, err); +} + +static struct bt_conn_cb conn_callbacks = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed, +}; + +static void scan_discovery_cb(struct bt_br_discovery_result *results, size_t count) +{ + char addr[BT_ADDR_LE_STR_LEN]; + uint8_t *eir; + bool cod_hf = false; + static uint8_t temp[240]; + size_t len = sizeof(results->eir); + uint8_t major_device; + uint8_t minor_device; + size_t i; + + for (i = 0; i < count; i++) { + bt_addr_to_str(&results[i].addr, addr, sizeof(addr)); + printk("Device[%d]: %s, rssi %d, cod 0x%X%X%X", i, addr, results[i].rssi, + results[i].cod[0], results[i].cod[1], results[i].cod[2]); + + major_device = (uint8_t)BT_COD_MAJOR_DEVICE_CLASS(results[i].cod); + minor_device = (uint8_t)BT_COD_MINOR_DEVICE_CLASS(results[i].cod); + + if ((major_device & BT_COD_MAJOR_AUDIO_VIDEO) && + (minor_device & BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HANDS_FREE)) { + cod_hf = true; + } + + eir = results[i].eir; + + while ((eir[0] > 2) && (len > eir[0])) { + switch (eir[1]) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + memcpy(temp, &eir[2], eir[0] - 1); + temp[eir[0] - 1] = '\0'; /* Set end flag */ + printk(", name %s", temp); + break; + } + len = len - eir[0] - 1; + eir = eir + eir[0] + 1; + } + printk("\n"); + + if (cod_hf) { + break; + } + } + + if (!cod_hf) { + (void)k_work_submit(&discover_work); + } else { + (void)k_work_cancel(&discover_work); + default_conn = bt_conn_create_br(&results[i].addr, BT_BR_CONN_PARAM_DEFAULT); + + if (default_conn == NULL) { + printk("Fail to create the connecton\n"); + } else { + bt_conn_unref(default_conn); + } + } +} + +static void discover_work_handler(struct k_work *work) +{ + int err; + + br_discover.length = 10; + br_discover.limited = false; + + err = bt_br_discovery_start(&br_discover, scan_result, + CONFIG_BT_HFP_AG_DISCOVER_RESULT_COUNT, scan_discovery_cb); + if (err) { + printk("Fail to start discovery (err %d)\n", err); + return; + } +} + +static void call_connect_work_handler(struct k_work *work) +{ +#if CONFIG_BT_HFP_AG_CALL_OUTGOING + int err; + + printk("Dialing\n"); + + err = bt_hfp_ag_outgoing(hfp_ag, "test_hf"); + + if (err != 0) { + printk("Fail to dial a call (err %d)\n", err); + } +#else + int err = bt_hfp_ag_remote_incoming(hfp_ag, "test_hf"); + + if (err != 0) { + printk("Fail to set remote incoming call (err %d)\n", err); + } +#endif /* CONFIG_BT_HFP_AG_CALL_OUTGOING */ +} + +static void call_disconnect_work_handler(struct k_work *work) +{ + int err; + + if (default_conn != NULL) { + err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + + if (err != 0) { + printk("Fail to disconnect acl connection (err %d)\n", err); + } + } +} + +static void call_remote_ringing_work_handler(struct k_work *work) +{ + int err; + + printk("Remote starts ringing\n"); + + err = bt_hfp_ag_remote_ringing(hfp_ag); + + if (err != 0) { + printk("Fail to notify hfp unit that the remote starts ringing (err %d)\n", err); + } else { + k_work_schedule(&call_remote_accept_work, K_SECONDS(1)); + } +} + +static void call_remote_accept_work_handler(struct k_work *work) +{ + int err; + + printk("Remote accepts the call\n"); + + err = bt_hfp_ag_remote_accept(hfp_ag); + + if (err != 0) { + printk("Fail to notify hfp unit that the remote accepts call (err %d)\n", err); + } +} + +static void bt_ready(int err) +{ + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return; + } + + if (IS_ENABLED(CONFIG_SETTINGS)) { + settings_load(); + } + + printk("Bluetooth initialized\n"); + + bt_conn_cb_register(&conn_callbacks); + + bt_hfp_ag_register(&ag_cb); + + k_work_init(&discover_work, discover_work_handler); + + (void)k_work_submit(&discover_work); + + k_work_init_delayable(&call_connect_work, call_connect_work_handler); + k_work_init_delayable(&call_disconnect_work, call_disconnect_work_handler); + + k_work_init_delayable(&call_remote_ringing_work, call_remote_ringing_work_handler); + k_work_init_delayable(&call_remote_accept_work, call_remote_accept_work_handler); +} + +int main(void) +{ + int err; + + printk("Bluetooth Handsfree AG demo start...\n"); + + err = bt_enable(bt_ready); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + } + return 0; +} From 0e9c0d52d44f3a743d6ae62f6736f39a0d395927 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0771/1389] Bluetooth: Kconfig: Set BT_BUF_EVT_RX_SIZE to 255 for BR/EDR The maximum data length of event packet is 255 for BR/EDR. Such as the data length of event Remote Name Request Complete is 255. Set BT_BUF_EVT_RX_SIZE to 255 to avoid error "Not enough space in buffer" from bt_hci driver. Signed-off-by: Lyle Zhu --- subsys/bluetooth/common/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index d7d0d579609634..9ccd4e184f6f8d 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -96,7 +96,7 @@ config BT_BUF_ACL_RX_COUNT config BT_BUF_EVT_RX_SIZE int "Maximum supported HCI Event buffer length" - default 255 if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX + default 255 if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX || BT_CLASSIC # LE Read Supported Commands command complete event. default 68 range 68 255 From dc871817c76467b8bfa9e1ee97f2863b8d028ed6 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0772/1389] Bluetooth: host: Kconfig: Change default value of BT_RFCOMM_TX_MAX To avoid the case that CONN_TX is available but RFCOMM_TX is unavailable, set the default value of BT_RFCOMM_TX_MAX to BT_CONN_TX_MAX. Signed-off-by: Lyle Zhu --- subsys/bluetooth/host/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 9c0e53e80e135e..4005d7752df094 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -1033,8 +1033,8 @@ config BT_RFCOMM_L2CAP_MTU config BT_RFCOMM_TX_MAX int "Maximum number of pending TX buffers for RFCOMM" - default BT_MAX_CONN - range BT_MAX_CONN 255 + default BT_CONN_TX_MAX + range BT_CONN_TX_MAX 255 help Maximum number of pending TX buffers that have an associated sending buf. Normally this can be left to the default value, which From c393999ef15bc2af8e0d27beb86bfe065250bf71 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0773/1389] Bluetooth: RFCOMM: Kconfig: Add configure BT_RFCOMM_DLC_STACK_SIZE The default stack size of RFCOMM DLC is 256. The default value is sufficient for basic operation. If more stack space is used (such as call function printk) in context of callback disconnected of RFCOMM DLC, the default stack size is not sufficient. Add a configuration BT_RFCOMM_DLC_STACK_SIZE to configure the RFCOMM DLC stack size. Signed-off-by: Lyle Zhu --- include/zephyr/bluetooth/classic/rfcomm.h | 4 +++- subsys/bluetooth/host/Kconfig | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/zephyr/bluetooth/classic/rfcomm.h b/include/zephyr/bluetooth/classic/rfcomm.h index 5664506931c82a..3b4f7f44ddbfd7 100644 --- a/include/zephyr/bluetooth/classic/rfcomm.h +++ b/include/zephyr/bluetooth/classic/rfcomm.h @@ -104,7 +104,9 @@ struct bt_rfcomm_dlc { /* Stack & kernel data for TX thread */ struct k_thread tx_thread; - K_KERNEL_STACK_MEMBER(stack, 256); +#if defined(CONFIG_BT_RFCOMM_DLC_STACK_SIZE) + K_KERNEL_STACK_MEMBER(stack, CONFIG_BT_RFCOMM_DLC_STACK_SIZE); +#endif /* CONFIG_BT_RFCOMM_DLC_STACK_SIZE */ }; struct bt_rfcomm_server { diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 4005d7752df094..a5d16a986b7ef3 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -1040,6 +1040,18 @@ config BT_RFCOMM_TX_MAX sending buf. Normally this can be left to the default value, which is equal to the number of session in the stack-internal pool. +config BT_RFCOMM_DLC_STACK_SIZE + int "Stack size of DLC for RFCOMM" + default 512 if BT_HFP_AG + default 256 + help + Stack size of DLC for RFCOMM. This is the context from which + all sending datas of upper layer are sent and disconnect + callback to the upper layer. The default value is sufficient + for basic operation, but if the application needs to do + advanced things in its callbacks that require extra stack + space, this value can be increased to accommodate for that. + config BT_HFP_HF bool "Bluetooth Handsfree profile HF Role support [EXPERIMENTAL]" depends on PRINTK From 1b722a056ffe7d45097306dae5a6847e5086fb27 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0774/1389] Bluetooth: classic: Kconfig: Move Kconfig of classic to classic/Kconfig Create classic/Kconfig, and move all of classic from Kconfig to classic/Kconfig. Signed-off-by: Lyle Zhu --- subsys/bluetooth/host/Kconfig | 166 +----------------------- subsys/bluetooth/host/classic/Kconfig | 175 ++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 165 deletions(-) create mode 100644 subsys/bluetooth/host/classic/Kconfig diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index a5d16a986b7ef3..f880ed805d99b2 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -996,171 +996,7 @@ config BT_CONN_DISABLE_SECURITY WARNING: This option enables anyone to snoop on-air traffic. Use of this feature in production is strongly discouraged. -config BT_CLASSIC - bool "Bluetooth BR/EDR support [EXPERIMENTAL]" - depends on BT_HCI_HOST - select BT_PERIPHERAL - select BT_CENTRAL - select BT_SMP - select BT_L2CAP_DYNAMIC_CHANNEL - select EXPERIMENTAL - help - This option enables Bluetooth BR/EDR support - -if BT_CLASSIC -config BT_MAX_SCO_CONN - int "Maximum number of simultaneous SCO connections" - default 1 - range 1 3 - help - Maximum number of simultaneous Bluetooth synchronous connections - supported. The minimum (and default) number is 1. - -config BT_RFCOMM - bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]" - select EXPERIMENTAL - help - This option enables Bluetooth RFCOMM support - -config BT_RFCOMM_L2CAP_MTU - int "L2CAP MTU for RFCOMM frames" - depends on BT_RFCOMM - # RX MTU will be truncated to account for the L2CAP PDU header. - default BT_BUF_ACL_RX_SIZE - range 23 32767 - help - Maximum size of L2CAP PDU for RFCOMM frames. - -config BT_RFCOMM_TX_MAX - int "Maximum number of pending TX buffers for RFCOMM" - default BT_CONN_TX_MAX - range BT_CONN_TX_MAX 255 - help - Maximum number of pending TX buffers that have an associated - sending buf. Normally this can be left to the default value, which - is equal to the number of session in the stack-internal pool. - -config BT_RFCOMM_DLC_STACK_SIZE - int "Stack size of DLC for RFCOMM" - default 512 if BT_HFP_AG - default 256 - help - Stack size of DLC for RFCOMM. This is the context from which - all sending datas of upper layer are sent and disconnect - callback to the upper layer. The default value is sufficient - for basic operation, but if the application needs to do - advanced things in its callbacks that require extra stack - space, this value can be increased to accommodate for that. - -config BT_HFP_HF - bool "Bluetooth Handsfree profile HF Role support [EXPERIMENTAL]" - depends on PRINTK - select BT_RFCOMM - select EXPERIMENTAL - help - This option enables Bluetooth HF support - -config BT_HFP_AG - bool "Bluetooth Handsfree profile AG Role support [EXPERIMENTAL]" - depends on PRINTK - select BT_RFCOMM - select EXPERIMENTAL - help - This option enables Bluetooth AG support - -if BT_HFP_AG -config BT_HFP_AG_TX_BUF_COUNT - int "Maximum number of TX buffers for HFP AG [EXPERIMENTAL]" - default BT_RFCOMM_TX_MAX - range BT_RFCOMM_TX_MAX 255 - help - Maximum number of pending TX buffers that have an associated - sending buf. Normally this can be left to the default value, which - is equal to the number of session in the stack-internal pool. - -config BT_HFP_AG_THREAD_STACK_SIZE - int "Size of the HFP AG thread stack [EXPERIMENTAL]" - default 1024 - help - Stack size needed for executing thread for HFP AG. - -config BT_HFP_AG_THREAD_PRIO - # Hidden option for HFP AG thread priority - int - default 6 - -config BT_HFP_AG_OUTGOING_TIMEOUT - int "Call outgoing timeout value for HFP AG [EXPERIMENTAL]" - default 3 - range 1 10 - help - The option sets the timeout of call outgoing. If the call does - not switch to alerting state before timeout, it will be - stopped by the HFP AG. The unit is seconds. - -config BT_HFP_AG_INCOMING_TIMEOUT - int "Incoming call timeout value for HFP AG [EXPERIMENTAL]" - default 3 - range 1 10 - help - The option sets the timeout of incoming call. If the call does - not switch to ringing state before timeout, it will be - stopped by the HFP AG. The unit is seconds. - -config BT_HFP_AG_ALERTING_TIMEOUT - int "Call alerting/ringing timeout value for HFP AG [EXPERIMENTAL]" - default 60 - range 10 60 - help - The option sets the timeout of call alerting/ringing. If the - call is not active before timeout, it will be stopped - by the HFP AG. The unit is seconds. - -config BT_HFP_AG_PHONE_NUMBER_MAX_LEN - int "Supported max length of phone number for HFP AG [EXPERIMENTAL]" - default 32 - range 1 255 - help - Supported max length of phone number for HFP AG. - -config BT_HFP_AG_RING_NOTIFY_INTERVAL - int "Ring notification interval [EXPERIMENTAL]" - default 3 - help - Ring notification interval if the call is in alert state. - The unit is seconds. -endif # BT_HFP_AG - -config BT_AVDTP - bool "Bluetooth AVDTP protocol support [EXPERIMENTAL]" - select EXPERIMENTAL - help - This option enables Bluetooth AVDTP support - -config BT_A2DP - bool "Bluetooth A2DP Profile [EXPERIMENTAL]" - select BT_AVDTP - select EXPERIMENTAL - help - This option enables the A2DP profile - -config BT_PAGE_TIMEOUT - hex "Bluetooth Page Timeout" - default 0x2000 - range 0x0001 0xffff - help - This option sets the page timeout value. Value is selected as - (N * 0.625) ms. - -config BT_COD - hex "Bluetooth Class of Device(CoD)" - default 0 - help - This option sets the class of device.For the list of possible values please - consult the following link: - https://www.bluetooth.com/specifications/assigned-numbers - -endif # BT_CLASSIC +rsource "./classic/Kconfig" config BT_HCI_VS_EVT_USER bool "User Vendor-Specific event handling" diff --git a/subsys/bluetooth/host/classic/Kconfig b/subsys/bluetooth/host/classic/Kconfig new file mode 100644 index 00000000000000..2869978f9c78c4 --- /dev/null +++ b/subsys/bluetooth/host/classic/Kconfig @@ -0,0 +1,175 @@ +# Bluetooth Calssic configuration options + +# Copyright (c) 2016-2020 Nordic Semiconductor ASA +# Copyright (c) 2015-2016 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +menu "Bluetooth Classic Options" + +config BT_CLASSIC + bool "Bluetooth BR/EDR support [EXPERIMENTAL]" + depends on BT_HCI_HOST + select BT_PERIPHERAL + select BT_CENTRAL + select BT_SMP + select BT_L2CAP_DYNAMIC_CHANNEL + select EXPERIMENTAL + help + This option enables Bluetooth BR/EDR support + +if BT_CLASSIC +config BT_MAX_SCO_CONN + int "Maximum number of simultaneous SCO connections" + default 1 + range 1 3 + help + Maximum number of simultaneous Bluetooth synchronous connections + supported. The minimum (and default) number is 1. + +config BT_RFCOMM + bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]" + select EXPERIMENTAL + help + This option enables Bluetooth RFCOMM support + +config BT_RFCOMM_L2CAP_MTU + int "L2CAP MTU for RFCOMM frames" + depends on BT_RFCOMM + default BT_BUF_ACL_RX_SIZE + range 23 32767 + help + Maximum size of L2CAP PDU for RFCOMM frames. + RX MTU will be truncated to account for the L2CAP PDU header. + +config BT_RFCOMM_TX_MAX + int "Maximum number of pending TX buffers for RFCOMM" + default BT_CONN_TX_MAX + range BT_CONN_TX_MAX 255 + help + Maximum number of pending TX buffers that have an associated + sending buf. Normally this can be left to the default value, which + is equal to the number of session in the stack-internal pool. + +config BT_RFCOMM_DLC_STACK_SIZE + int "Stack size of DLC for RFCOMM" + default 512 if BT_HFP_AG + default 256 + help + Stack size of DLC for RFCOMM. This is the context from which + all datas of upper layer are sent and disconnect + callback to the upper layer. The default value is sufficient + for basic operation, but if the application needs to do + advanced things in its callbacks that require extra stack + space, this value can be increased to accommodate for that. + +config BT_HFP_HF + bool "Bluetooth Handsfree profile HF Role support [EXPERIMENTAL]" + depends on PRINTK + select BT_RFCOMM + select EXPERIMENTAL + help + This option enables Bluetooth HF support + +config BT_HFP_AG + bool "Bluetooth Handsfree profile AG Role support [EXPERIMENTAL]" + depends on PRINTK + select BT_RFCOMM + select EXPERIMENTAL + help + This option enables Bluetooth AG support + +if BT_HFP_AG +config BT_HFP_AG_TX_BUF_COUNT + int "Maximum number of TX buffers for HFP AG [EXPERIMENTAL]" + default BT_RFCOMM_TX_MAX + range BT_RFCOMM_TX_MAX 255 + help + Maximum number of pending TX buffers that have an associated + sending buf. Normally this can be left to the default value, which + is equal to the number of session in the stack-internal pool. + +config BT_HFP_AG_THREAD_STACK_SIZE + int "Size of the HFP AG thread stack [EXPERIMENTAL]" + default 1024 + help + Stack size needed for executing thread for HFP AG. + +config BT_HFP_AG_THREAD_PRIO + # Hidden option for HFP AG thread priority + int + default 6 + +config BT_HFP_AG_OUTGOING_TIMEOUT + int "Call outgoing timeout value for HFP AG [EXPERIMENTAL]" + default 3 + range 1 10 + help + The option sets the timeout of call outgoing. If the call does + not switch to alerting state before timeout, it will be + stopped by the HFP AG. The unit is seconds. + +config BT_HFP_AG_INCOMING_TIMEOUT + int "Incoming call timeout value for HFP AG [EXPERIMENTAL]" + default 3 + range 1 10 + help + The option sets the timeout of incoming call. If the call does + not switch to ringing state before timeout, it will be + stopped by the HFP AG. The unit is seconds. + +config BT_HFP_AG_ALERTING_TIMEOUT + int "Call alerting/ringing timeout value for HFP AG [EXPERIMENTAL]" + default 60 + range 10 60 + help + The option sets the timeout of call alerting/ringing. If the + call is not active before timeout, it will be stopped + by the HFP AG. The unit is seconds. + +config BT_HFP_AG_PHONE_NUMBER_MAX_LEN + int "Supported max length of phone number for HFP AG [EXPERIMENTAL]" + default 32 + range 1 255 + help + Supported max length of phone number for HFP AG. + +config BT_HFP_AG_RING_NOTIFY_INTERVAL + int "Ring notification interval [EXPERIMENTAL]" + default 3 + help + Ring notification interval if the call is in alert state. + The unit is seconds. +endif # BT_HFP_AG + +config BT_AVDTP + bool "Bluetooth AVDTP protocol support [EXPERIMENTAL]" + select EXPERIMENTAL + help + This option enables Bluetooth AVDTP support + +config BT_A2DP + bool "Bluetooth A2DP Profile [EXPERIMENTAL]" + select BT_AVDTP + select EXPERIMENTAL + help + This option enables the A2DP profile + +config BT_PAGE_TIMEOUT + hex "Bluetooth Page Timeout" + default 0x2000 + range 0x0001 0xffff + help + This option sets the page timeout value. Value is selected as + (N * 0.625) ms. + +config BT_COD + hex "Bluetooth Class of Device(CoD)" + default 0 + help + This option sets the class of device.For the list of possible values please + consult the following link: + https://www.bluetooth.com/specifications/assigned-numbers + +endif # BT_CLASSIC + +endmenu From 7df7aaeed0824c3414fbcffe5738ffbb3e06d43e Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0775/1389] Bluetooth: HFP_AG: Protect the consistency of AG state/value Use hfp_ag_lock/hfp_ag_unlock to protect the consistency of AG state or value. Signed-off-by: Lyle Zhu --- subsys/bluetooth/host/classic/hfp_ag.c | 221 +++++++++++++++++++++---- 1 file changed, 188 insertions(+), 33 deletions(-) diff --git a/subsys/bluetooth/host/classic/hfp_ag.c b/subsys/bluetooth/host/classic/hfp_ag.c index eaf06d088051f3..034cd324b6ae24 100644 --- a/subsys/bluetooth/host/classic/hfp_ag.c +++ b/subsys/bluetooth/host/classic/hfp_ag.c @@ -135,7 +135,9 @@ static void bt_hfp_ag_set_state(struct bt_hfp_ag *ag, bt_hfp_state_t state) { LOG_DBG("update state %p, old %d -> new %d", ag, ag->state, state); + hfp_ag_lock(ag); ag->state = state; + hfp_ag_unlock(ag); switch (state) { case BT_HFP_DISCONNECTED: @@ -162,9 +164,14 @@ static void bt_hfp_ag_set_state(struct bt_hfp_ag *ag, bt_hfp_state_t state) static void bt_hfp_ag_set_call_state(struct bt_hfp_ag *ag, bt_hfp_call_state_t call_state) { + bt_hfp_state_t state; + LOG_DBG("update call state %p, old %d -> new %d", ag, ag->call_state, call_state); + hfp_ag_lock(ag); ag->call_state = call_state; + state = ag->state; + hfp_ag_unlock(ag); switch (call_state) { case BT_HFP_CALL_TERMINATE: @@ -192,7 +199,7 @@ static void bt_hfp_ag_set_call_state(struct bt_hfp_ag *ag, bt_hfp_call_state_t c break; } - if (ag->state == BT_HFP_DISCONNECTING) { + if (state == BT_HFP_DISCONNECTING) { int err = bt_rfcomm_dlc_disconnect(&ag->rfcomm_dlc); if (err) { @@ -387,7 +394,9 @@ static int bt_hfp_ag_brsf_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENOTSUP; } + hfp_ag_lock(ag); ag->hf_features = hf_features; + hfp_ag_unlock(ag); return hfp_ag_send_data(ag, NULL, NULL, "\r\n+BRSF:%d\r\n", ag->ag_features); } @@ -402,10 +411,13 @@ static int bt_hfp_ag_bac_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENOTSUP; } + hfp_ag_lock(ag); if (!(ag->hf_features & BT_HFP_HF_FEATURE_CODEC_NEG) || !(ag->ag_features & BT_HFP_AG_FEATURE_CODEC_NEG)) { + hfp_ag_unlock(ag); return -EOPNOTSUPP; } + hfp_ag_unlock(ag); while (err == 0) { err = get_number(buf, &codec); @@ -424,7 +436,9 @@ static int bt_hfp_ag_bac_handler(struct bt_hfp_ag *ag, struct net_buf *buf) } } + hfp_ag_lock(ag); ag->hf_codec_ids = codec_ids; + hfp_ag_unlock(ag); if (bt_ag && bt_ag->codec) { bt_ag->codec(ag, ag->hf_codec_ids); @@ -487,7 +501,13 @@ static int bt_hfp_ag_cind_handler(struct bt_hfp_ag *ag, struct net_buf *buf) static void bt_hfp_ag_set_in_band_ring(struct bt_hfp_ag *ag, void *user_data) { - if ((ag->ag_features & BT_HFP_AG_FEATURE_INBAND_RINGTONE) != 0) { + bool is_inband_ringtone; + + hfp_ag_lock(ag); + is_inband_ringtone = (ag->ag_features & BT_HFP_AG_FEATURE_INBAND_RINGTONE) ? true : false; + hfp_ag_unlock(ag); + + if (is_inband_ringtone) { int err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BSIR:1\r\n"); atomic_set_bit_to(ag->flags, BT_HFP_AG_INBAND_RING, err == 0); @@ -555,17 +575,22 @@ static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf) char *data; uint32_t len; + hfp_ag_lock(ag); if (!((ag->ag_features & BT_HFP_AG_FEATURE_HF_IND) && (ag->hf_features & BT_HFP_HF_FEATURE_HF_IND))) { + hfp_ag_unlock(ag); return -EOPNOTSUPP; } + hfp_ag_unlock(ag); if (is_char(buf, '?')) { if (!is_char(buf, '\r')) { return -ENOTSUP; } + hfp_ag_lock(ag); hf_indicators = ag->hf_indicators_of_hf & ag->hf_indicators_of_ag; + hfp_ag_unlock(ag); len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX : (sizeof(hf_indicators) * 8); for (int i = 1; i < len; i++) { @@ -596,7 +621,9 @@ static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf) data = &ag->buffer[0]; *data = '('; data++; + hfp_ag_lock(ag); hf_indicators = ag->hf_indicators_of_ag; + hfp_ag_unlock(ag); len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX : (sizeof(hf_indicators) * 8); for (int i = 1; (i < len) && (hf_indicators != 0); i++) { @@ -640,7 +667,9 @@ static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf) } } + hfp_ag_lock(ag); ag->hf_indicators_of_hf = hf_indicators; + hfp_ag_unlock(ag); return 0; } @@ -705,11 +734,17 @@ static int hfp_ag_update_indicator(struct bt_hfp_ag *ag, enum bt_hfp_ag_indicato static void hfp_ag_close_sco(struct bt_hfp_ag *ag) { + struct bt_conn *sco; + LOG_DBG(""); - if (NULL != ag->sco_chan.sco) { - LOG_DBG("Disconnect sco %p", ag->sco_chan.sco); - bt_conn_disconnect(ag->sco_chan.sco, BT_HCI_ERR_LOCALHOST_TERM_CONN); - ag->sco_chan.sco = NULL; + + hfp_ag_lock(ag); + sco = ag->sco_chan.sco; + ag->sco_chan.sco = NULL; + hfp_ag_unlock(ag); + if (sco != NULL) { + LOG_DBG("Disconnect sco %p", sco); + bt_conn_disconnect(sco, BT_HCI_ERR_LOCALHOST_TERM_CONN); } } @@ -754,17 +789,22 @@ static void bt_hfp_ag_unit_call_terminate(struct bt_hfp_ag *ag, void *user_data) static int bt_hfp_ag_chup_handler(struct bt_hfp_ag *ag, struct net_buf *buf) { int err; + bt_hfp_call_state_t call_state; if (!is_char(buf, '\r')) { return -ENOTSUP; } - if (ag->call_state == BT_HFP_CALL_ALERTING) { + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + + if (call_state == BT_HFP_CALL_ALERTING) { if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return -ENOTSUP; } err = hfp_ag_next_step(ag, bt_hfp_ag_call_reject, NULL); - } else if ((ag->call_state == BT_HFP_CALL_ACTIVE) || (ag->call_state == BT_HFP_CALL_HOLD)) { + } else if ((call_state == BT_HFP_CALL_ACTIVE) || (call_state == BT_HFP_CALL_HOLD)) { err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL); } else { return -ENOTSUP; @@ -776,6 +816,7 @@ static uint8_t bt_hfp_get_call_state(struct bt_hfp_ag *ag) { uint8_t status = HFP_AG_CLCC_STATUS_INVALID; + hfp_ag_lock(ag); switch (ag->call_state) { case BT_HFP_CALL_TERMINATE: break; @@ -801,6 +842,7 @@ static uint8_t bt_hfp_get_call_state(struct bt_hfp_ag *ag) default: break; } + hfp_ag_unlock(ag); return status; } @@ -817,10 +859,13 @@ static int bt_hfp_ag_clcc_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENOTSUP; } + hfp_ag_lock(ag); if (ag->call_state == BT_HFP_CALL_TERMINATE) { /* AG shall always send OK response to HF */ + hfp_ag_unlock(ag); return 0; } + hfp_ag_unlock(ag); dir = atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL) ? 1 : 0; status = bt_hfp_get_call_state(ag); @@ -841,12 +886,16 @@ static int bt_hfp_ag_bia_handler(struct bt_hfp_ag *ag, struct net_buf *buf) uint32_t number; int err; int index = 0; - uint32_t indicator = ag->indicator; + uint32_t indicator; if (!is_char(buf, '=')) { return -ENOTSUP; } + hfp_ag_lock(ag); + indicator = ag->indicator; + hfp_ag_unlock(ag); + while (buf->len > 0) { err = get_number(buf, &number); if (err == 0) { @@ -873,7 +922,10 @@ static int bt_hfp_ag_bia_handler(struct bt_hfp_ag *ag, struct net_buf *buf) /* Force call, call setup and held call indicators are enabled. */ indicator = BIT(BT_HFP_AG_CALL_IND) | BIT(BT_HFP_AG_CALL_SETUP_IND) | BIT(BT_HFP_AG_CALL_HELD_IND); + + hfp_ag_lock(ag); ag->indicator = indicator; + hfp_ag_unlock(ag); return 0; } @@ -897,8 +949,12 @@ static void bt_hfp_ag_call_ringing_cb(struct bt_hfp_ag *ag, bool in_bond) static void hfp_ag_sco_connected(struct bt_sco_chan *chan) { struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan); + bt_hfp_call_state_t call_state; - if (ag->call_state == BT_HFP_CALL_INCOMING) { + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + if (call_state == BT_HFP_CALL_INCOMING) { bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ALERTING); bt_hfp_ag_call_ringing_cb(ag, true); } @@ -911,12 +967,16 @@ static void hfp_ag_sco_connected(struct bt_sco_chan *chan) static void hfp_ag_sco_disconnected(struct bt_sco_chan *chan, uint8_t reason) { struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan); + bt_hfp_call_state_t call_state; if ((bt_ag) && bt_ag->sco_disconnected) { bt_ag->sco_disconnected(ag); } - if ((ag->call_state == BT_HFP_CALL_INCOMING) || (ag->call_state == BT_HFP_CALL_OUTGOING)) { + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + if ((call_state == BT_HFP_CALL_INCOMING) || (call_state == BT_HFP_CALL_OUTGOING)) { bt_hfp_ag_call_reject(ag, NULL); } } @@ -950,16 +1010,19 @@ static struct bt_conn *bt_hfp_ag_create_sco(struct bt_hfp_ag *ag) static int hfp_ag_open_sco(struct bt_hfp_ag *ag) { + hfp_ag_lock(ag); if (ag->sco_chan.sco == NULL) { struct bt_conn *sco_conn = bt_hfp_ag_create_sco(ag); if (sco_conn == NULL) { LOG_ERR("Fail to create sco connection!"); + hfp_ag_unlock(ag); return -ENOTCONN; } LOG_DBG("SCO connection created (%p)", sco_conn); } + hfp_ag_unlock(ag); return 0; } @@ -970,15 +1033,19 @@ static int bt_hfp_ag_codec_select(struct bt_hfp_ag *ag) LOG_DBG(""); + hfp_ag_lock(ag); if (ag->selected_codec_id == 0) { LOG_ERR("Codec is invalid"); + hfp_ag_unlock(ag); return -EINVAL; } if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) { LOG_ERR("Codec is unsupported (codec id %d)", ag->selected_codec_id); + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BCS:%d\r\n", ag->selected_codec_id); if (err != 0) { @@ -990,8 +1057,13 @@ static int bt_hfp_ag_codec_select(struct bt_hfp_ag *ag) static int bt_hfp_ag_create_audio_connection(struct bt_hfp_ag *ag) { int err; + uint32_t hf_codec_ids; + + hfp_ag_lock(ag); + hf_codec_ids = ag->hf_codec_ids; + hfp_ag_unlock(ag); - if ((ag->hf_codec_ids != 0) && atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED)) { + if ((hf_codec_ids != 0) && atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED)) { atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CONN); err = bt_hfp_ag_codec_select(ag); } else { @@ -1035,9 +1107,12 @@ static int bt_hfp_ag_ata_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENOTSUP; } + hfp_ag_lock(ag); if (ag->call_state != BT_HFP_CALL_ALERTING) { + hfp_ag_unlock(ag); return -ENOTSUP; } + hfp_ag_unlock(ag); if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return -ENOTSUP; @@ -1105,21 +1180,15 @@ static int bt_hfp_ag_bcc_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENOTSUP; } - if (ag->selected_codec_id == 0) { - return -ENOTSUP; - } - - if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) { - return -ENOTSUP; - } - - if (ag->call_state == BT_HFP_CALL_TERMINATE) { - return -ENOTSUP; - } - - if (ag->sco_chan.sco != NULL) { + hfp_ag_lock(ag); + if ((ag->selected_codec_id == 0) || + (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) || + (ag->call_state == BT_HFP_CALL_TERMINATE) || + (ag->sco_chan.sco != NULL)) { + hfp_ag_unlock(ag); return -ENOTSUP; } + hfp_ag_unlock(ag); err = hfp_ag_next_step(ag, bt_hfp_ag_audio_connection, NULL); @@ -1157,6 +1226,7 @@ static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ESRCH; } + hfp_ag_lock(ag); if (ag->selected_codec_id != number) { LOG_ERR("Received codec id %d is not aligned with selected %d", number, ag->selected_codec_id); @@ -1166,6 +1236,7 @@ static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf) ag->selected_codec_id, ag->hf_codec_ids); err = -ENOTSUP; } + hfp_ag_unlock(ag); atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CONN); atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED); @@ -1173,7 +1244,12 @@ static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf) if (err == 0) { err = hfp_ag_next_step(ag, bt_hfp_ag_unit_codec_conn_setup, NULL); } else { - if (ag->call_state != BT_HFP_CALL_TERMINATE) { + bt_hfp_call_state_t call_state; + + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + if (call_state != BT_HFP_CALL_TERMINATE) { (void)hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL); } } @@ -1233,12 +1309,15 @@ static int bt_hfp_ag_atd_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENAMETOOLONG; } + hfp_ag_lock(ag); if (ag->call_state != BT_HFP_CALL_TERMINATE) { + hfp_ag_unlock(ag); return -EBUSY; } /* Copy number to ag->number including null-character */ memcpy(ag->number, number, len + 1); + hfp_ag_unlock(ag); err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL); @@ -1253,13 +1332,17 @@ static int bt_hfp_ag_bldn_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return -ENOTSUP; } + hfp_ag_lock(ag); if (strlen(ag->number) == 0) { + hfp_ag_unlock(ag); return -ENOSR; } if (ag->call_state != BT_HFP_CALL_TERMINATE) { + hfp_ag_unlock(ag); return -EBUSY; } + hfp_ag_unlock(ag); err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL); @@ -1313,11 +1396,15 @@ static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc) static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc) { struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc); + bt_hfp_call_state_t call_state; bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTED); - if ((ag->call_state == BT_HFP_CALL_ALERTING) || (ag->call_state == BT_HFP_CALL_ACTIVE) || - (ag->call_state == BT_HFP_CALL_HOLD)) { + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + if ((call_state == BT_HFP_CALL_ALERTING) || (call_state == BT_HFP_CALL_ACTIVE) || + (call_state == BT_HFP_CALL_HOLD)) { bt_hfp_ag_terminate_cb(ag, NULL); } @@ -1420,10 +1507,15 @@ static void hfp_ag_sent(struct bt_rfcomm_dlc *dlc, struct net_buf *buf, int err) static void bt_ag_deferred_work_cb(struct bt_hfp_ag *ag, void *user_data) { int err; + bt_hfp_call_state_t call_state; LOG_DBG(""); - switch (ag->call_state) { + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + + switch (call_state) { case BT_HFP_CALL_TERMINATE: break; case BT_HFP_CALL_ACTIVE: @@ -1483,10 +1575,14 @@ static void bt_ag_deferred_work(struct k_work *work) static void bt_ag_ringing_work_cb(struct bt_hfp_ag *ag, void *user_data) { int err; + bt_hfp_call_state_t call_state; LOG_DBG(""); - if (ag->call_state == BT_HFP_CALL_ALERTING) { + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + if (call_state == BT_HFP_CALL_ALERTING) { if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return; @@ -1635,6 +1731,7 @@ int bt_hfp_ag_connect(struct bt_conn *conn, struct bt_hfp_ag **ag, uint8_t chann int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag) { int err; + bt_hfp_call_state_t call_state; LOG_DBG(""); @@ -1642,16 +1739,20 @@ int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); + call_state = ag->call_state; + hfp_ag_unlock(ag); + bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTING); - if ((ag->call_state == BT_HFP_CALL_ACTIVE) || (ag->call_state == BT_HFP_CALL_HOLD)) { + if ((call_state == BT_HFP_CALL_ACTIVE) || (call_state == BT_HFP_CALL_HOLD)) { err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL); if (err != 0) { LOG_ERR("HFP AG send response err :(%d)", err); } return err; - } else if (ag->call_state != BT_HFP_CALL_TERMINATE) { + } else if (call_state != BT_HFP_CALL_TERMINATE) { err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE, bt_hfp_ag_reject_cb, NULL); if (err != 0) { @@ -1710,21 +1811,27 @@ int bt_hfp_ag_remote_incoming(struct bt_hfp_ag *ag, const char *number) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if (ag->call_state != BT_HFP_CALL_TERMINATE) { + hfp_ag_unlock(ag); return -EBUSY; } + hfp_ag_unlock(ag); len = strlen(number); if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) { return -EINVAL; } + hfp_ag_lock(ag); /* Copy number to ag->number including null-character */ memcpy(ag->number, number, len + 1); + hfp_ag_unlock(ag); atomic_set_bit(ag->flags, BT_HFP_AG_INCOMING_CALL); @@ -1747,13 +1854,17 @@ int bt_hfp_ag_reject(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_INCOMING)) { + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return -EINVAL; @@ -1775,13 +1886,17 @@ int bt_hfp_ag_accept(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if (ag->call_state != BT_HFP_CALL_ALERTING) { + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return -EINVAL; @@ -1811,13 +1926,17 @@ int bt_hfp_ag_terminate(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) { + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL); @@ -1853,21 +1972,27 @@ int bt_hfp_ag_outgoing(struct bt_hfp_ag *ag, const char *number) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if (ag->call_state != BT_HFP_CALL_TERMINATE) { + hfp_ag_unlock(ag); return -EBUSY; } + hfp_ag_unlock(ag); len = strlen(number); if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) { return -EINVAL; } + hfp_ag_lock(ag); /* Copy number to ag->number including null-character */ memcpy(ag->number, number, len + 1); + hfp_ag_unlock(ag); atomic_clear_bit(ag->flags, BT_HFP_AG_INCOMING_CALL); @@ -1898,19 +2023,24 @@ int bt_hfp_ag_remote_ringing(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } - if (BT_HFP_CALL_OUTGOING != ag->call_state) { + if (ag->call_state != BT_HFP_CALL_OUTGOING) { + hfp_ag_unlock(ag); return -EBUSY; } if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) { if (ag->sco_chan.sco == NULL) { + hfp_ag_unlock(ag); return -ENOTCONN; } } + hfp_ag_unlock(ag); err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_REMOTE_ALERTING, bt_hfp_ag_ringing_cb, @@ -1929,13 +2059,17 @@ int bt_hfp_ag_remote_reject(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_OUTGOING)) { + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return -EINVAL; @@ -1957,13 +2091,17 @@ int bt_hfp_ag_remote_accept(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if (ag->call_state != BT_HFP_CALL_ALERTING) { + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) { return -EINVAL; @@ -1993,13 +2131,17 @@ int bt_hfp_ag_remote_terminate(struct bt_hfp_ag *ag) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) { + hfp_ag_unlock(ag); return -EINVAL; } + hfp_ag_unlock(ag); err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL); @@ -2016,9 +2158,12 @@ int bt_hfp_ag_set_indicator(struct bt_hfp_ag *ag, enum bt_hfp_ag_indicator index return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } + hfp_ag_unlock(ag); switch (index) { case BT_HFP_AG_SERVICE_IND: @@ -2057,7 +2202,9 @@ int bt_hfp_ag_set_operator(struct bt_hfp_ag *ag, char *name) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } @@ -2065,6 +2212,7 @@ int bt_hfp_ag_set_operator(struct bt_hfp_ag *ag, char *name) len = MIN(sizeof(ag->operator) - 1, len); memcpy(ag->operator, name, len); ag->operator[len] = '\0'; + hfp_ag_unlock(ag); return 0; } @@ -2079,19 +2227,26 @@ int bt_hfp_ag_select_codec(struct bt_hfp_ag *ag, uint8_t id) return -EINVAL; } + hfp_ag_lock(ag); if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); return -ENOTCONN; } if (!(ag->hf_codec_ids && BIT(id))) { + hfp_ag_unlock(ag); return -ENOTSUP; } + hfp_ag_unlock(ag); if (atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CONN)) { return -EBUSY; } + hfp_ag_lock(ag); ag->selected_codec_id = id; + hfp_ag_unlock(ag); + atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED); err = bt_hfp_ag_create_audio_connection(ag); From 99b12bdf743eb3e99ca8aa89d36949701c00f920 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0776/1389] manifest: Update hal_nxp Update NXP hal to the revision pointing to the following commit: "drivers: csi: Rework to fix the low framerate issue" Signed-off-by: Phi Bang Nguyen --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 40a896f65bc5a2..4fd16a2f7d6f0c 100644 --- a/west.yml +++ b/west.yml @@ -193,7 +193,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 8c354a918c1272b40ad9b4ffecac1d89125efbe6 + revision: abc66979c77421fb3a140ce2e4e6ea7165cdbe8f path: modules/hal/nxp groups: - hal From ec22f181d1b34fd4e7f6c620a07b6cd66fd6b068 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:07 +0200 Subject: [PATCH 0777/1389] drivers: usb: usb_dc_mcux: add case for MCXN94X SOC series Add case for MCXN94X SOC series to indicate which device controller is in use. Signed-off-by: Mahesh Mahadevan --- drivers/usb/device/usb_dc_mcux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/device/usb_dc_mcux.c b/drivers/usb/device/usb_dc_mcux.c index e36eba89182526..d62662063eec31 100644 --- a/drivers/usb/device/usb_dc_mcux.c +++ b/drivers/usb/device/usb_dc_mcux.c @@ -89,7 +89,9 @@ BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); #elif DT_NODE_HAS_STATUS(DT_NODELABEL(usbfs), okay) #define CONTROLLER_ID kUSB_ControllerLpcIp3511Fs0 #endif /* LPC55s69 */ -#elif defined(CONFIG_SOC_SERIES_IMXRT11XX) || defined(CONFIG_SOC_SERIES_IMXRT10XX) +#elif defined(CONFIG_SOC_SERIES_IMXRT11XX) || \ + defined(CONFIG_SOC_SERIES_IMXRT10XX) || \ + defined(CONFIG_SOC_SERIES_MCXNX4X) #if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) #define CONTROLLER_ID kUSB_ControllerEhci0 #elif DT_NODE_HAS_STATUS(DT_NODELABEL(usb2), okay) From 7c5868a41de707aae4c3e8af2acc2f33e42b741e Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0778/1389] dts: nxp_mcxn94x: Add USBHS support Add support for the USB High Speed controller Signed-off-by: Mahesh Mahadevan --- dts/arm/nxp/nxp_mcxn94x_common.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index 890e7d007dfd86..31e280e556e4e6 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -840,6 +840,15 @@ #io-channel-cells = <1>; clocks = <&syscon MCUX_LPADC2_CLK>; }; + + usb1: usbd@10b000 { + compatible = "nxp,ehci"; + reg = <0x10b000 0x1000>; + interrupts = <67 0>; + interrupt-names = "usb_otg"; + num-bidir-endpoints = <8>; + status = "disabled"; + }; }; &systick { From e300e953e7d8eb0ecc538c7614b69a22e81e9d25 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0779/1389] soc: n94x: Add USBHS support Add support for USBHS controller Signed-off-by: Mahesh Mahadevan --- soc/nxp/mcx/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soc/nxp/mcx/Kconfig b/soc/nxp/mcx/Kconfig index 1f310d9fa566d8..3bf1d3a881a483 100644 --- a/soc/nxp/mcx/Kconfig +++ b/soc/nxp/mcx/Kconfig @@ -39,4 +39,8 @@ config MFD default y depends on DT_HAS_NXP_LP_FLEXCOMM_ENABLED +choice USB_MCUX_CONTROLLER_TYPE + default USB_DC_NXP_EHCI +endchoice + endif # SOC_FAMILY_NXP_MCX From fd97ea9c08784f1364587d1a9a897d83748f09e9 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0780/1389] boards: frdm_mcxn947: Add USBHS support Add support for the USBHS controller Signed-off-by: Mahesh Mahadevan --- boards/nxp/frdm_mcxn947/board.c | 53 +++++++++++++++++++ boards/nxp/frdm_mcxn947/doc/index.rst | 2 + .../frdm_mcxn947_mcxn947_cpu0.dts | 4 ++ .../frdm_mcxn947_mcxn947_cpu0.yaml | 1 + 4 files changed, 60 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index b79265127b3c96..e6568204ce9f75 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -8,6 +8,15 @@ #include #include #include +#if CONFIG_USB_DC_NXP_EHCI +#include "usb_phy.h" +#include "usb.h" + +/* USB PHY condfiguration */ +#define BOARD_USB_PHY_D_CAL (0x04U) +#define BOARD_USB_PHY_TXCAL45DP (0x07U) +#define BOARD_USB_PHY_TXCAL45DM (0x07U) +#endif /* Board xtal frequency in Hz */ #define BOARD_XTAL0_CLK_HZ 24000000U @@ -95,6 +104,8 @@ static int frdm_mcxn947_init(void) /* Set AHBCLKDIV divider to value 1 */ CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); + CLOCK_SetupExtClocking(BOARD_XTAL0_CLK_HZ); + #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcomm1), okay) CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u); CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1); @@ -215,6 +226,48 @@ static int frdm_mcxn947_init(void) CLOCK_AttachClk(kFRO_HF_to_ADC0); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI + usb_phy_config_struct_t usbPhyConfig = { + BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM, + }; + + SPC0->ACTIVE_VDELAY = 0x0500; + /* Change the power DCDC to 1.8v (By default, DCDC is 1.8V), CORELDO to 1.1v (By default, + * CORELDO is 1.0V) + */ + SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK; + SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) | + SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u); + /* Wait until it is done */ + while (SPC0->SC & SPC_SC_BUSY_MASK) { + }; + if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) { + SCG0->TRIM_LOCK = 0x5a5a0001U; + SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK; + /* wait LDO ready */ + while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK)) { + }; + } + SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK | + SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK; + SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK); + /* xtal = 20 ~ 30MHz */ + SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT); + SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK; + while (1) { + if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) { + break; + } + } + SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK | + SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK; + CLOCK_EnableClock(kCLOCK_UsbHs); + CLOCK_EnableClock(kCLOCK_UsbHsPhy); + CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, BOARD_XTAL0_CLK_HZ); + CLOCK_EnableUsbhsClock(); + USB_EhciPhyInit(kUSB_ControllerEhci0, BOARD_XTAL0_CLK_HZ, &usbPhyConfig); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; diff --git a/boards/nxp/frdm_mcxn947/doc/index.rst b/boards/nxp/frdm_mcxn947/doc/index.rst index b04849a61dc25e..a7724ad69ce04e 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -88,6 +88,8 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | +-----------+------------+-------------------------------------+ +| USBHS | on-chip | USB device | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts index 338e8e520ae7c8..e3d80335db2ccd 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -161,3 +161,7 @@ &lpadc0 { status = "okay"; }; + +zephyr_udc0: &usb1 { + status = "okay"; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml index 10127d1a6693cf..ef6ea7114dc969 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml @@ -26,4 +26,5 @@ supported: - sdhc - regulator - adc + - usb_device vendor: nxp From 7aab4f1a9c02c4e4f2cd5d9a5608988e571c2c24 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0781/1389] tests: drivers: sdhc: setup SDHC IO before test Rather than relying to the alphanumeric test ordering implemented in ZTEST to ensure certain tests run first, setup the SDHC IO properties to known good values before starting any of the tests. This allows the SDHC tests to run in any order, rather than needing certain tests to run first. Signed-off-by: Daniel DeGrasse --- tests/drivers/sdhc/src/main.c | 37 ++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/tests/drivers/sdhc/src/main.c b/tests/drivers/sdhc/src/main.c index 1ee9b7a1ba9157..205b367a74174f 100644 --- a/tests/drivers/sdhc/src/main.c +++ b/tests/drivers/sdhc/src/main.c @@ -17,6 +17,27 @@ static struct sdhc_io io; K_SEM_DEFINE(card_sem, 0, 1); +/* Prepare IO settings for card */ +static void *sdhc_power_on(void) +{ + int ret; + + ret = sdhc_get_host_props(sdhc_dev, &props); + zassert_equal(ret, 0, "SDHC host props api call failed"); + + io.clock = props.f_min; + io.bus_mode = SDHC_BUSMODE_PUSHPULL; + io.power_mode = SDHC_POWER_ON; + io.bus_width = SDHC_BUS_WIDTH1BIT; + io.timing = SDHC_TIMING_LEGACY; + io.signal_voltage = SD_VOL_3_3_V; + + ret = sdhc_set_io(sdhc_dev, &io); + zassert_equal(ret, 0, "Setting io configuration failed"); + k_msleep(props.power_delay); + return NULL; +} + /* Resets SD host controller, verifies API */ ZTEST(sdhc, test_reset) { @@ -33,6 +54,8 @@ ZTEST(sdhc, test_host_props) { int ret; + zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready"); + /* Set all host properties to 0xFF */ props.f_max = 0xFF; props.f_min = 0xFF; @@ -56,6 +79,8 @@ ZTEST(sdhc, test_set_io) { int ret; + zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready"); + io.clock = props.f_min; io.bus_mode = SDHC_BUSMODE_PUSHPULL; io.power_mode = SDHC_POWER_ON; @@ -88,16 +113,12 @@ void sdhc_interrupt_cb(const struct device *dev, int source, const void *data) /* * Verify that the driver can detect a present SD card - * This test must run first, to ensure the card is present. */ -ZTEST(sdhc, test_0_card_presence) +ZTEST(sdhc, test_card_presence) { int ret; - io.clock = props.f_min; - ret = sdhc_set_io(sdhc_dev, &io); - zassert_equal(ret, 0, "Setting io configuration failed"); - k_msleep(props.power_delay); + zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready"); ret = sdhc_card_present(sdhc_dev); if (ret == 0) { @@ -126,6 +147,8 @@ ZTEST(sdhc, test_card_if_cond) int ret, resp; int check_pattern = SD_IF_COND_CHECK; + zassert_true(device_is_ready(sdhc_dev), "SDHC device is not ready"); + /* Toggle power to card, to clear state */ io.power_mode = SDHC_POWER_OFF; ret = sdhc_set_io(sdhc_dev, &io); @@ -172,4 +195,4 @@ ZTEST(sdhc, test_card_if_cond) } } -ZTEST_SUITE(sdhc, NULL, NULL, NULL, NULL, NULL); +ZTEST_SUITE(sdhc, NULL, sdhc_power_on, NULL, NULL, NULL); From 084dbcd1b6ec3bd3179f3c4832e275af673f9dbb Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0782/1389] arch: riscv: reorder fatal message Print the backtrace message after the registers. Signed-off-by: Yong Cong Sin --- arch/riscv/core/fatal.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 7152da2066c726..05d7f4c99c3eda 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -81,6 +81,10 @@ static void unwind_stack(const z_arch_esf_t *esf) uintptr_t ra; struct stackframe *frame; + if (esf == NULL) { + return; + } + LOG_ERR("call trace:"); for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound((uintptr_t)fp);) { @@ -96,6 +100,8 @@ static void unwind_stack(const z_arch_esf_t *esf) } fp = frame->fp; } + + LOG_ERR(""); } #endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ @@ -144,9 +150,6 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf LOG_ERR(" mepc: " PR_REG, esf->mepc); LOG_ERR("mstatus: " PR_REG, esf->mstatus); LOG_ERR(""); -#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE - unwind_stack(esf); -#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ } if (csf != NULL) { @@ -163,6 +166,11 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf #endif /* CONFIG_RISCV_ISA_RV32E */ LOG_ERR(""); } + +#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE + unwind_stack(esf); +#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ + #endif /* CONFIG_EXCEPTION_DEBUG */ z_fatal_error(reason, esf); CODE_UNREACHABLE; From bb8baa9f8beb350bbb841ded48e3adafce7521ce Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0783/1389] tests: arch: common: stack_unwind: cleanup Kconfig Refactor to cleanup some Kconfigs that are not required by certain architectures to produce the traces. Signed-off-by: Yong Cong Sin --- tests/arch/common/stack_unwind/enable_fp.conf | 2 ++ tests/arch/common/stack_unwind/prj.conf | 3 --- tests/arch/common/stack_unwind/testcase.yaml | 4 +++- 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 tests/arch/common/stack_unwind/enable_fp.conf diff --git a/tests/arch/common/stack_unwind/enable_fp.conf b/tests/arch/common/stack_unwind/enable_fp.conf new file mode 100644 index 00000000000000..5348bd113709ea --- /dev/null +++ b/tests/arch/common/stack_unwind/enable_fp.conf @@ -0,0 +1,2 @@ +CONFIG_OVERRIDE_FRAME_POINTER_DEFAULT=y +CONFIG_OMIT_FRAME_POINTER=n diff --git a/tests/arch/common/stack_unwind/prj.conf b/tests/arch/common/stack_unwind/prj.conf index 31d2f11f46f2b8..8ac350b3c97ff9 100644 --- a/tests/arch/common/stack_unwind/prj.conf +++ b/tests/arch/common/stack_unwind/prj.conf @@ -4,8 +4,5 @@ CONFIG_LOG=y CONFIG_LOG_BUFFER_SIZE=2048 CONFIG_EXCEPTION_STACK_TRACE=y -CONFIG_OVERRIDE_FRAME_POINTER_DEFAULT=y -CONFIG_OMIT_FRAME_POINTER=n CONFIG_DEBUG=y CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_OPTIMIZATIONS=y diff --git a/tests/arch/common/stack_unwind/testcase.yaml b/tests/arch/common/stack_unwind/testcase.yaml index 7d963bed29c8bb..b935b5c596e1d3 100644 --- a/tests/arch/common/stack_unwind/testcase.yaml +++ b/tests/arch/common/stack_unwind/testcase.yaml @@ -9,6 +9,7 @@ tests: integration_platforms: - qemu_riscv32 - qemu_riscv64 + extra_args: OVERLAY_CONFIG="enable_fp.conf" harness_config: type: multi_line regex: @@ -27,11 +28,12 @@ tests: regex: - "E: call trace:" - "E: (E|R)IP: \\w+" - arch.common.stack_unwind.arm: + arch.common.stack_unwind.arm64: arch_allow: - arm64 integration_platforms: - qemu_cortex_a53 + extra_args: OVERLAY_CONFIG="enable_fp.conf" harness_config: type: multi_line regex: From 355176686691e1338451ce5ebadb28d3a62e6a20 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0784/1389] arch: riscv: remove unnecessary cast Remove unnecessary cast of `fp` into `uintptr_t`. Signed-off-by: Yong Cong Sin --- arch/riscv/core/fatal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 05d7f4c99c3eda..07809c488aaaed 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -87,11 +87,11 @@ static void unwind_stack(const z_arch_esf_t *esf) LOG_ERR("call trace:"); - for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound((uintptr_t)fp);) { + for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp);) { frame = (struct stackframe *)fp - 1; ra = frame->ra; if (in_text_region(ra)) { - LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, (uintptr_t)fp, ra); + LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, fp, ra); /* * Increment the iterator only if `ra` is within the text region to get the * most out of it From 13ac7179e259d21cb9be1ffa2422a1f04045cfe0 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0785/1389] include: zephyr: sd: sd_spec: use frequency macros Use frequency macros to define SD frequencies, this should increase readability of the file and reduce errors. Signed-off-by: Daniel DeGrasse --- include/zephyr/sd/sd_spec.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index ed61932e65516a..f75f2b9e7eb420 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -12,6 +12,7 @@ #define ZEPHYR_SUBSYS_SD_SPEC_H_ #include +#include #ifdef __cplusplus extern "C" { @@ -368,7 +369,7 @@ enum sd_group_num { /* Maximum data rate possible for SD high speed cards */ enum hs_max_data_rate { - HS_MAX_DTR = 50000000, + HS_MAX_DTR = MHZ(50), }; /** @@ -411,16 +412,16 @@ enum sd_timing_mode { * Controls the SD host controller clock speed on the SD bus. */ enum sdhc_clock_speed { - SDMMC_CLOCK_400KHZ = 400000U, - SD_CLOCK_25MHZ = 25000000U, - SD_CLOCK_50MHZ = 50000000U, - SD_CLOCK_100MHZ = 100000000U, - SD_CLOCK_208MHZ = 208000000U, - MMC_CLOCK_26MHZ = 26000000U, - MMC_CLOCK_52MHZ = 52000000U, - MMC_CLOCK_DDR52 = 52000000U, - MMC_CLOCK_HS200 = 200000000U, - MMC_CLOCK_HS400 = 200000000U, /* Same clock freq as HS200, just DDR */ + SDMMC_CLOCK_400KHZ = KHZ(400), + SD_CLOCK_25MHZ = MHZ(25), + SD_CLOCK_50MHZ = MHZ(50), + SD_CLOCK_100MHZ = MHZ(100), + SD_CLOCK_208MHZ = MHZ(208), + MMC_CLOCK_26MHZ = MHZ(26), + MMC_CLOCK_52MHZ = MHZ(52), + MMC_CLOCK_DDR52 = MHZ(52), + MMC_CLOCK_HS200 = MHZ(200), + MMC_CLOCK_HS400 = MHZ(200), /* Same clock freq as HS200, just DDR */ }; /** From fa77a666a623ebac11eb7370ef3c3af0d3ce7d6c Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0786/1389] include: zephyr: sd: sd_spec: add UNSUPPORTED frequency for HS mode Add UNSUPPORTED frequency macro for HS mode frequencies, used when a card does not support any high speed mode frequencies Signed-off-by: Daniel DeGrasse --- include/zephyr/sd/sd_spec.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index f75f2b9e7eb420..88de0153f3f8e7 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -369,6 +369,7 @@ enum sd_group_num { /* Maximum data rate possible for SD high speed cards */ enum hs_max_data_rate { + HS_UNSUPPORTED = 0, HS_MAX_DTR = MHZ(50), }; From 030bcbc912f2fa5c96d3ff3f7f7a004ab518f52b Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0787/1389] sd: sdmmc: add DEFAULT and HIGH_SPEED bus speeds Add DEFAULT and HIGH_SPEED bus speeds to SD spec definition, for non UHS cards. Signed-off-by: Daniel DeGrasse --- include/zephyr/sd/sd_spec.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index 88de0153f3f8e7..4724eb26253458 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -381,6 +381,7 @@ enum hs_max_data_rate { */ enum sd_bus_speed { UHS_SDR12_BUS_SPEED = BIT(0), + DEFAULT_BUS_SPEED = BIT(0), HIGH_SPEED_BUS_SPEED = BIT(1), UHS_SDR25_BUS_SPEED = BIT(1), UHS_SDR50_BUS_SPEED = BIT(2), @@ -395,10 +396,14 @@ enum sd_bus_speed { * controller to identify timing of card. */ enum sd_timing_mode { + SD_TIMING_DEFAULT = 0U, + /*!< Default Mode */ SD_TIMING_SDR12 = 0U, - /*!< Default mode & SDR12 */ + /*!< SDR12 mode */ + SD_TIMING_HIGH_SPEED = 1U, + /*!< High speed mode */ SD_TIMING_SDR25 = 1U, - /*!< High speed mode & SDR25 */ + /*!< SDR25 mode */ SD_TIMING_SDR50 = 2U, /*!< SDR50 mode*/ SD_TIMING_SDR104 = 3U, From 32f20d7e83ddc62f95e9dc9dd2a078138c7bffec Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0788/1389] sd: sdmmc: rework frequency and timing selection logic SDMMC framework frequency and timing selection logic has several longstanding issues, including: - requiring that SD hosts support the maximum frequency possible for a given UHS mode in order to apply that timing - selecting SDHC_TIMING_SDR25 for high speed mode, when SDHC_TIMING_HS would be correct Rework the frequency and timing selection logic within the SD framework to resolve these issues. Fixes #52589 Fixes #67943 Signed-off-by: Daniel DeGrasse --- include/zephyr/sd/sd_spec.h | 12 +++- subsys/sd/sdmmc.c | 139 ++++++++++++++++++++++++------------ 2 files changed, 104 insertions(+), 47 deletions(-) diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index 4724eb26253458..7e08488805c558 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -373,6 +373,16 @@ enum hs_max_data_rate { HS_MAX_DTR = MHZ(50), }; +/* Maximum data rate possible for SD uhs cards */ +enum uhs_max_data_rate { + UHS_UNSUPPORTED = 0, + UHS_SDR12_MAX_DTR = MHZ(25), + UHS_SDR25_MAX_DTR = MHZ(50), + UHS_SDR50_MAX_DTR = MHZ(100), + UHS_SDR104_MAX_DTR = MHZ(208), + UHS_DDR50_MAX_DTR = MHZ(50), +}; + /** * @brief SD bus speed support bit flags * @@ -494,7 +504,7 @@ enum sd_driver_strength { */ struct sd_switch_caps { enum hs_max_data_rate hs_max_dtr; - enum sdhc_clock_speed uhs_max_dtr; + enum uhs_max_data_rate uhs_max_dtr; enum sd_bus_speed bus_speed; enum sd_driver_type sd_drv_type; enum sd_current_limit sd_current_limit; diff --git a/subsys/sd/sdmmc.c b/subsys/sd/sdmmc.c index 5b9854cc95bfeb..ed7acaf439bbce 100644 --- a/subsys/sd/sdmmc.c +++ b/subsys/sd/sdmmc.c @@ -332,8 +332,25 @@ static int sdmmc_read_switch(struct sd_card *card) * Bit n being set in support bit field indicates support for function * number n on the card. (So 0x3 indicates support for functions 0 and 1) */ + /* Determine HS speed support, if any */ if (status[13] & HIGH_SPEED_BUS_SPEED) { card->switch_caps.hs_max_dtr = HS_MAX_DTR; + } else { + card->switch_caps.hs_max_dtr = HS_UNSUPPORTED; + } + /* Determine UHS speed support, if any */ + if (status[13] & UHS_SDR104_BUS_SPEED) { + card->switch_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; + } else if (status[13] & UHS_DDR50_BUS_SPEED) { + card->switch_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; + } else if (status[13] & UHS_SDR50_BUS_SPEED) { + card->switch_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; + } else if (status[13] & UHS_SDR25_BUS_SPEED) { + card->switch_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; + } else if (status[13] & UHS_SDR12_BUS_SPEED) { + card->switch_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; + } else { + card->switch_caps.uhs_max_dtr = UHS_UNSUPPORTED; } if (card->sd_version >= SD_SPEC_VER3_0) { card->switch_caps.bus_speed = status[13]; @@ -349,22 +366,31 @@ static inline void sdmmc_select_bus_speed(struct sd_card *card) * Note that function support is defined using bitfields, but function * selection is defined using values 0x0-0xF. */ - if (card->host_props.host_caps.sdr104_support && - (card->switch_caps.bus_speed & UHS_SDR104_BUS_SPEED) && - (card->host_props.f_max >= SD_CLOCK_208MHZ)) { - card->card_speed = SD_TIMING_SDR104; - } else if (card->host_props.host_caps.ddr50_support && - (card->switch_caps.bus_speed & UHS_DDR50_BUS_SPEED) && - (card->host_props.f_max >= SD_CLOCK_50MHZ)) { - card->card_speed = SD_TIMING_DDR50; - } else if (card->host_props.host_caps.sdr50_support && - (card->switch_caps.bus_speed & UHS_SDR50_BUS_SPEED) && - (card->host_props.f_max >= SD_CLOCK_100MHZ)) { - card->card_speed = SD_TIMING_SDR50; - } else if (card->host_props.host_caps.high_spd_support && - (card->switch_caps.bus_speed & UHS_SDR12_BUS_SPEED) && - (card->host_props.f_max >= SD_CLOCK_25MHZ)) { - card->card_speed = SD_TIMING_SDR12; + if ((card->flags & SD_1800MV_FLAG) && sdmmc_host_uhs(&card->host_props) && + !(card->host_props.is_spi) && IS_ENABLED(CONFIG_SD_UHS_PROTOCOL)) { + /* Select UHS mode timing */ + if (card->host_props.host_caps.sdr104_support && + (card->switch_caps.bus_speed & UHS_SDR104_BUS_SPEED)) { + card->card_speed = SD_TIMING_SDR104; + } else if (card->host_props.host_caps.ddr50_support && + (card->switch_caps.bus_speed & UHS_DDR50_BUS_SPEED)) { + card->card_speed = SD_TIMING_DDR50; + } else if (card->host_props.host_caps.sdr50_support && + (card->switch_caps.bus_speed & UHS_SDR50_BUS_SPEED)) { + card->card_speed = SD_TIMING_SDR50; + } else if (card->switch_caps.bus_speed & UHS_SDR12_BUS_SPEED) { + card->card_speed = SD_TIMING_SDR25; + } else { + card->card_speed = SD_TIMING_SDR12; + } + } else { + /* Select HS mode timing */ + if (card->host_props.host_caps.high_spd_support && + (card->switch_caps.bus_speed & HIGH_SPEED_BUS_SPEED)) { + card->card_speed = SD_TIMING_HIGH_SPEED; + } else { + card->card_speed = SD_TIMING_DEFAULT; + } } } @@ -432,34 +458,52 @@ static int sdmmc_set_current_limit(struct sd_card *card) static int sdmmc_set_bus_speed(struct sd_card *card) { int ret; - int timing = 0; uint8_t *status = card->card_buffer; + enum sdhc_timing_mode timing; + uint32_t card_clock; - switch (card->card_speed) { - /* Set bus clock speed */ - case SD_TIMING_SDR104: - card->switch_caps.uhs_max_dtr = SD_CLOCK_208MHZ; - timing = SDHC_TIMING_SDR104; - break; - case SD_TIMING_DDR50: - card->switch_caps.uhs_max_dtr = SD_CLOCK_50MHZ; - timing = SDHC_TIMING_DDR50; - break; - case SD_TIMING_SDR50: - card->switch_caps.uhs_max_dtr = SD_CLOCK_100MHZ; - timing = SDHC_TIMING_SDR50; - break; - case SD_TIMING_SDR25: - card->switch_caps.uhs_max_dtr = SD_CLOCK_50MHZ; - timing = SDHC_TIMING_SDR25; - break; - case SD_TIMING_SDR12: - card->switch_caps.uhs_max_dtr = SD_CLOCK_25MHZ; - timing = SDHC_TIMING_SDR12; - break; - default: - /* No need to change bus speed */ - return 0; + /* Set card clock and host timing. Since the card's maximum clock + * was calculated within sdmmc_read_switch(), we can safely use the + * minimum between that clock and the host's highest clock supported. + */ + if ((card->flags & SD_1800MV_FLAG) && sdmmc_host_uhs(&card->host_props) && + !(card->host_props.is_spi) && IS_ENABLED(CONFIG_SD_UHS_PROTOCOL)) { + /* UHS mode */ + card_clock = MIN(card->host_props.f_max, card->switch_caps.uhs_max_dtr); + switch (card->card_speed) { + case SD_TIMING_SDR104: + timing = SDHC_TIMING_SDR104; + break; + case SD_TIMING_DDR50: + timing = SDHC_TIMING_DDR50; + break; + case SD_TIMING_SDR50: + timing = SDHC_TIMING_SDR50; + break; + case SD_TIMING_SDR25: + timing = SDHC_TIMING_SDR25; + break; + case SD_TIMING_SDR12: + timing = SDHC_TIMING_SDR12; + break; + default: + /* No need to change bus speed */ + return 0; + } + } else { + /* High speed/default mode */ + card_clock = MIN(card->host_props.f_max, card->switch_caps.hs_max_dtr); + switch (card->card_speed) { + case SD_TIMING_HIGH_SPEED: + timing = SDHC_TIMING_HS; + break; + case SD_TIMING_DEFAULT: + timing = SDHC_TIMING_LEGACY; + break; + default: + /* No need to change bus speed */ + return 0; + } } /* Switch bus speed */ @@ -473,7 +517,7 @@ static int sdmmc_set_bus_speed(struct sd_card *card) } else { /* Change host bus speed */ card->bus_io.timing = timing; - card->bus_io.clock = card->switch_caps.uhs_max_dtr; + card->bus_io.clock = card_clock; LOG_DBG("Setting bus clock to: %d", card->bus_io.clock); ret = sdhc_set_io(card->sdhc, &card->bus_io); if (ret) { @@ -533,12 +577,15 @@ static int sdmmc_init_hs(struct sd_card *card) { int ret; - if ((!card->host_props.host_caps.high_spd_support) || (card->sd_version < SD_SPEC_VER1_1) || - (card->switch_caps.hs_max_dtr == 0)) { + if ((!card->host_props.host_caps.high_spd_support) || + (card->sd_version < SD_SPEC_VER1_1) || + (card->switch_caps.hs_max_dtr == HS_UNSUPPORTED)) { /* No high speed support. Leave card untouched */ return 0; } - card->card_speed = SD_TIMING_SDR25; + /* Select bus speed for card depending on host and card capability*/ + sdmmc_select_bus_speed(card); + /* Apply selected bus speed */ ret = sdmmc_set_bus_speed(card); if (ret) { LOG_ERR("Failed to switch card to HS mode"); From f292895bc6186aa68e6f998d11320c063a4c98fc Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0789/1389] sd: sdio: rework frequency and timing selection logic Reword frequency and timing selection logic for SDIO framework so that the maximum supported timing mode between the card and host will be selected, even if the maximum frequency supported by the host is not equal to the maximum frequency for that mode. Also, resolve an issue where a host and card combo only supporting HS mode or worse would still use legacy timing mode, because the CCCR flags were not being checked when checking if HS bus speed could be used. Signed-off-by: Daniel DeGrasse --- subsys/sd/sdio.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/subsys/sd/sdio.c b/subsys/sd/sdio.c index 64c813b1090b09..a81403c5f82c1c 100644 --- a/subsys/sd/sdio.c +++ b/subsys/sd/sdio.c @@ -450,23 +450,23 @@ static int sdio_set_bus_width(struct sd_card *card, enum sdhc_bus_width width) static inline void sdio_select_bus_speed(struct sd_card *card) { if (card->host_props.host_caps.sdr104_support && - (card->cccr_flags & SDIO_SUPPORT_SDR104) && - (card->host_props.f_max >= SD_CLOCK_208MHZ)) { + (card->cccr_flags & SDIO_SUPPORT_SDR104)) { card->card_speed = SD_TIMING_SDR104; + card->switch_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; } else if (card->host_props.host_caps.ddr50_support && - (card->cccr_flags & SDIO_SUPPORT_DDR50) && - (card->host_props.f_max >= SD_CLOCK_50MHZ)) { + (card->cccr_flags & SDIO_SUPPORT_DDR50)) { card->card_speed = SD_TIMING_DDR50; + card->switch_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; } else if (card->host_props.host_caps.sdr50_support && - (card->cccr_flags & SDIO_SUPPORT_SDR50) && - (card->host_props.f_max >= SD_CLOCK_100MHZ)) { + (card->cccr_flags & SDIO_SUPPORT_SDR50)) { card->card_speed = SD_TIMING_SDR50; + card->switch_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; } else if (card->host_props.host_caps.high_spd_support && - (card->switch_caps.bus_speed & SDIO_SUPPORT_HS) && - (card->host_props.f_max >= SD_CLOCK_50MHZ)) { - card->card_speed = SD_TIMING_SDR25; + (card->cccr_flags & SDIO_SUPPORT_HS)) { + card->card_speed = SD_TIMING_HIGH_SPEED; + card->switch_caps.hs_max_dtr = HS_MAX_DTR; } else { - card->card_speed = SD_TIMING_SDR12; + card->card_speed = SD_TIMING_DEFAULT; } } @@ -474,34 +474,35 @@ static inline void sdio_select_bus_speed(struct sd_card *card) static int sdio_set_bus_speed(struct sd_card *card) { int ret, timing, retries = CONFIG_SD_RETRY_COUNT; + uint32_t bus_clock; uint8_t speed_reg, target_speed; switch (card->card_speed) { /* Set bus clock speed */ case SD_TIMING_SDR104: - card->switch_caps.uhs_max_dtr = SD_CLOCK_208MHZ; + bus_clock = MIN(card->host_props.f_max, card->switch_caps.uhs_max_dtr); target_speed = SDIO_CCCR_SPEED_SDR104; timing = SDHC_TIMING_SDR104; break; case SD_TIMING_DDR50: - card->switch_caps.uhs_max_dtr = SD_CLOCK_50MHZ; + bus_clock = MIN(card->host_props.f_max, card->switch_caps.uhs_max_dtr); target_speed = SDIO_CCCR_SPEED_DDR50; timing = SDHC_TIMING_DDR50; break; case SD_TIMING_SDR50: - card->switch_caps.uhs_max_dtr = SD_CLOCK_100MHZ; + bus_clock = MIN(card->host_props.f_max, card->switch_caps.uhs_max_dtr); target_speed = SDIO_CCCR_SPEED_SDR50; timing = SDHC_TIMING_SDR50; break; - case SD_TIMING_SDR25: - card->switch_caps.uhs_max_dtr = SD_CLOCK_50MHZ; + case SD_TIMING_HIGH_SPEED: + bus_clock = MIN(card->host_props.f_max, card->switch_caps.hs_max_dtr); target_speed = SDIO_CCCR_SPEED_SDR25; - timing = SDHC_TIMING_SDR25; + timing = SDHC_TIMING_HS; break; - case SD_TIMING_SDR12: - card->switch_caps.uhs_max_dtr = SD_CLOCK_25MHZ; + case SD_TIMING_DEFAULT: + bus_clock = MIN(card->host_props.f_max, MHZ(25)); target_speed = SDIO_CCCR_SPEED_SDR12; - timing = SDHC_TIMING_SDR12; + timing = SDHC_TIMING_LEGACY; break; default: /* No need to change bus speed */ @@ -530,7 +531,7 @@ static int sdio_set_bus_speed(struct sd_card *card) } else { /* Set card bus clock and timing */ card->bus_io.timing = timing; - card->bus_io.clock = card->switch_caps.uhs_max_dtr; + card->bus_io.clock = bus_clock; LOG_DBG("Setting bus clock to: %d", card->bus_io.clock); ret = sdhc_set_io(card->sdhc, &card->bus_io); if (ret) { From 52d282a7a1ae08bde78e2beb6ad7cf9bae6446b4 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0790/1389] tests: subsys: sd: report bus frequency, report timing correctly Report bus frequency, and use correct names for the timing modes when SD cards do not support UHS modes. Signed-off-by: Daniel DeGrasse --- tests/subsys/sd/sdmmc/src/main.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/subsys/sd/sdmmc/src/main.c b/tests/subsys/sd/sdmmc/src/main.c index 84c07bb3998e35..1bae0941041e3c 100644 --- a/tests/subsys/sd/sdmmc/src/main.c +++ b/tests/subsys/sd/sdmmc/src/main.c @@ -200,23 +200,41 @@ ZTEST(sd_stack, test_card_config) zassert_equal(card.status, CARD_INITIALIZED, "Card status is not OK"); switch (card.card_speed) { case SD_TIMING_SDR12: - TC_PRINT("Card timing: SDR12\n"); + if (card.flags & SD_1800MV_FLAG) { + TC_PRINT("Card timing: SDR12\n"); + } else { + /* Card uses non UHS mode timing */ + TC_PRINT("Card timing: Legacy\n"); + } break; case SD_TIMING_SDR25: - TC_PRINT("Card timing: SDR25\n"); + if (card.flags & SD_1800MV_FLAG) { + TC_PRINT("Card timing: SDR25\n"); + } else { + /* Card uses non UHS mode timing */ + TC_PRINT("Card timing: High Speed\n"); + } break; case SD_TIMING_SDR50: TC_PRINT("Card timing: SDR50\n"); + zassert_true(card.flags & SD_1800MV_FLAG, + "Card must support UHS mode for this timing"); break; case SD_TIMING_SDR104: TC_PRINT("Card timing: SDR104\n"); + zassert_true(card.flags & SD_1800MV_FLAG, + "Card must support UHS mode for this timing"); break; case SD_TIMING_DDR50: TC_PRINT("Card timing: DDR50\n"); + zassert_true(card.flags & SD_1800MV_FLAG, + "Card must support UHS mode for this timing"); break; default: zassert_unreachable("Card timing is not known value"); } + zassert_not_equal(card.bus_io.clock, 0, "Bus should have nonzero clock"); + TC_PRINT("Bus Frequency: %d Hz\n", card.bus_io.clock); switch (card.type) { case CARD_SDIO: TC_PRINT("Card type: SDIO\n"); From 97482b2a369b52c196c492b771e1643dac8a27be Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0791/1389] drivers: sdhc: rcar_mmc: remove frequency correction code RCAR MMC driver previously had to report inaccurate maximum supported frequency to SD subsystem so that the subsystem would select SDR104 mode timing. Remove this logic, as it should no longer be needed. Signed-off-by: Daniel DeGrasse --- drivers/sdhc/rcar_mmc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/sdhc/rcar_mmc.c b/drivers/sdhc/rcar_mmc.c index 2e5d20ee86adfa..8d637f0fd577e0 100644 --- a/drivers/sdhc/rcar_mmc.c +++ b/drivers/sdhc/rcar_mmc.c @@ -28,15 +28,6 @@ LOG_MODULE_REGISTER(rcar_mmc, CONFIG_LOG_DEFAULT_LEVEL); #define MMC_POLL_FLAGS_TIMEOUT_US 100000 #define MMC_POLL_FLAGS_ONE_CYCLE_TIMEOUT_US 1 #define MMC_BUS_CLOCK_FREQ 800000000 -/* - * SD/MMC clock for Gen3/Gen4 R-car boards can't be equal to 208 MHz, - * but we can run SDR104 on lower frequencies: - * "SDR104: UHS-I 1.8V signaling, Frequency up to 208 MHz" - * so according to SD card standard it is possible to use lower frequencies, - * and we need to pass check of frequency in sdmmc in order to use sdr104 mode. - * This is the reason why it is needed this correction. - */ -#define MMC_MAX_FREQ_CORRECTION 8000000 #ifdef CONFIG_RCAR_MMC_DMA_SUPPORT #define ALIGN_BUF_DMA __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT) @@ -1941,7 +1932,7 @@ static void rcar_mmc_init_host_props(const struct device *dev) /* Note: init only properties that are used for mmc/sdhc */ - props->f_max = cfg->max_frequency + MMC_MAX_FREQ_CORRECTION; + props->f_max = cfg->max_frequency; /* * note: actually, it's possible to get lower frequency * if we use divider from cpg too From 7d36e2a3b3f311db560218c1a478c21da0f12ca9 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0792/1389] sd: sd_ops: remove additional unlock call within card_read() SD ops card_read() implementation does not need to unlock mutex, as this is managed by the calling function card_write_blocks. Remove this stray k_mutex_unlock() call. Fixes #72287 Signed-off-by: Daniel DeGrasse --- subsys/sd/sd_ops.c | 1 - 1 file changed, 1 deletion(-) diff --git a/subsys/sd/sd_ops.c b/subsys/sd/sd_ops.c index 7d4ebf11dd3c32..debf80f46551b4 100644 --- a/subsys/sd/sd_ops.c +++ b/subsys/sd/sd_ops.c @@ -535,7 +535,6 @@ static int card_read(struct sd_card *card, uint8_t *rbuf, uint32_t start_block, ret = sdmmc_wait_ready(card); if (ret) { LOG_ERR("Card did not return to ready state"); - k_mutex_unlock(&card->lock); return -ETIMEDOUT; } return 0; From 8c484950731cf3590d6474049e3f0aa2df9b7919 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sun, 26 May 2024 22:39:08 +0200 Subject: [PATCH 0793/1389] west: twister: Fix default options setup Fix missing change to run Twister with default options setup. Should be implemented together with #72399 Signed-off-by: Dmitrii Golovanov --- scripts/west_commands/twister_cmd.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/west_commands/twister_cmd.py b/scripts/west_commands/twister_cmd.py index b10aae71d438d4..266b60d2bf2ec7 100644 --- a/scripts/west_commands/twister_cmd.py +++ b/scripts/west_commands/twister_cmd.py @@ -56,8 +56,9 @@ def do_run(self, args, remainder): "args: {} remainder: {}".format(args, remainder), level=log.VERBOSE_EXTREME ) - options = self._parse_arguments(args=remainder, options=args) - ret = main(options) + options = parse_arguments(self.parser, args=remainder, options=args) + default_options = parse_arguments(self.parser, args=[], on_init=False) + ret = main(options, default_options) sys.exit(ret) def _parse_arguments(self, args, options): From c1a982012f3f4073f7d555326042d041c2e80ce9 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0794/1389] drivers: can: set default initial bitrates via Kconfig Set the default initial bitrates globally via Kconfig. The initial bitrates can still be overridden using the "bus-speed" and "bus-speed-data" devicetree properties. Signed-off-by: Henrik Brix Andersen --- drivers/can/Kconfig | 15 +++++++++++++++ dts/bindings/can/can-controller.yaml | 4 ++-- dts/bindings/can/can-fd-controller.yaml | 4 ++-- include/zephyr/drivers/can.h | 5 +++-- samples/modules/canopennode/src/main.c | 3 ++- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index 4f929ba32f83e7..7f6b12453a2c52 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -23,6 +23,21 @@ config CAN_INIT_PRIORITY help CAN driver device initialization priority. +config CAN_DEFAULT_BITRATE + int "Default CAN bitrate" + default 125000 + help + Default initial CAN bitrate in bits/s. This can be overridden per CAN controller using the + "bus-speed" devicetree property. + +config CAN_DEFAULT_BITRATE_DATA + int "Default CAN data phase bitrate" + default 1000000 + depends on CAN_FD_MODE + help + Default initial CAN data phase bitrate in bits/s. This can be overridden per CAN controller + using the "bus-speed-data" devicetree property. + config CAN_SHELL bool "CAN shell" depends on SHELL diff --git a/dts/bindings/can/can-controller.yaml b/dts/bindings/can/can-controller.yaml index adc738d7319f28..55322b50a21e9d 100644 --- a/dts/bindings/can/can-controller.yaml +++ b/dts/bindings/can/can-controller.yaml @@ -5,9 +5,9 @@ include: base.yaml properties: bus-speed: type: int - required: true description: | - Initial bitrate in bit/s. + Initial bitrate in bit/s. If this is unset, the initial bitrate is set to + CONFIG_CAN_DEFAULT_BITRATE. sample-point: type: int description: | diff --git a/dts/bindings/can/can-fd-controller.yaml b/dts/bindings/can/can-fd-controller.yaml index 46fab559d2a039..9efc7823f94fd4 100644 --- a/dts/bindings/can/can-fd-controller.yaml +++ b/dts/bindings/can/can-fd-controller.yaml @@ -5,9 +5,9 @@ include: can-controller.yaml properties: bus-speed-data: type: int - required: true description: | - Initial data phase bitrate in bit/s. + Initial data phase bitrate in bit/s. If this is unset, the initial data phase bitrate is set + to CONFIG_CAN_DEFAULT_BITRATE_DATA. sample-point-data: type: int description: | diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 8a26b407ccbb0f..3b0e323dff93ef 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -374,10 +374,11 @@ struct can_driver_config { .phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \ .min_bitrate = DT_CAN_TRANSCEIVER_MIN_BITRATE(node_id, _min_bitrate), \ .max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, _max_bitrate), \ - .bus_speed = DT_PROP(node_id, bus_speed), \ + .bus_speed = DT_PROP_OR(node_id, bus_speed, CONFIG_CAN_DEFAULT_BITRATE), \ .sample_point = DT_PROP_OR(node_id, sample_point, 0), \ IF_ENABLED(CONFIG_CAN_FD_MODE, \ - (.bus_speed_data = DT_PROP_OR(node_id, bus_speed_data, 0), \ + (.bus_speed_data = DT_PROP_OR(node_id, bus_speed_data, \ + CONFIG_CAN_DEFAULT_BITRATE_DATA), \ .sample_point_data = DT_PROP_OR(node_id, sample_point_data, 0),)) \ } diff --git a/samples/modules/canopennode/src/main.c b/samples/modules/canopennode/src/main.c index c470e1f1732161..60c3ebaa6dfe6f 100644 --- a/samples/modules/canopennode/src/main.c +++ b/samples/modules/canopennode/src/main.c @@ -15,7 +15,8 @@ LOG_MODULE_REGISTER(app); #define CAN_INTERFACE DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)) -#define CAN_BITRATE (DT_PROP(DT_CHOSEN(zephyr_canbus), bus_speed) / 1000) +#define CAN_BITRATE (DT_PROP_OR(DT_CHOSEN(zephyr_canbus), bus_speed, \ + CONFIG_CAN_DEFAULT_BITRATE) / 1000) static struct gpio_dt_spec led_green_gpio = GPIO_DT_SPEC_GET_OR( DT_ALIAS(green_led), gpios, {0}); From 403ca536454c26c6c0030f1280d5a86e46d30c36 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0795/1389] drivers: can: remove initial bus-speed/bus-speed-data properties Remove all CAN controller "bus-speed" and "bus-speed-data" properties. These all use the default bitrates set via Kconfig. Signed-off-by: Henrik Brix Andersen --- .../giga_r1/arduino_giga_r1_stm32h747xx_m7.dts | 2 -- .../sam_e70_xplained/sam_e70_xplained-common.dtsi | 3 --- .../atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi | 3 --- boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts | 6 ------ boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts | 1 - .../esp32s3_devkitc/esp32s3_devkitc_procpu.dts | 1 - .../esp32s3_devkitm/esp32s3_devkitm_procpu.dts | 1 - .../heltec_wireless_stick_lite_v3_procpu.dts | 1 - boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts | 1 - .../esp32c3_luatos_core/esp32c3_luatos_core.dtsi | 1 - .../esp32s3_luatos_core/esp32s3_luatos_core.dtsi | 1 - boards/m5stack/stamp_c3/stamp_c3.dts | 1 - boards/native/native_sim/native_sim.dts | 2 -- boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts | 2 -- boards/nxp/frdm_k64f/frdm_k64f.dts | 1 - .../nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi | 2 -- .../nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi | 2 -- boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts | 2 -- boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts | 1 - boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts | 2 -- boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts | 4 ---- boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts | 1 - .../mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts | 2 -- .../mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts | 2 -- boards/nxp/mr_canhubk3/mr_canhubk3.dts | 12 ------------ boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts | 2 -- boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi | 4 ---- boards/nxp/twr_ke18f/twr_ke18f.dts | 1 - boards/nxp/ucans32k1sic/ucans32k1sic.dts | 4 ---- boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts | 6 ------ .../olimex_esp32_evb/olimex_esp32_evb_procpu.dts | 1 - boards/olimex/olimexino_stm32/olimexino_stm32.dts | 1 - boards/olimex/stm32_p405/olimex_stm32_p405.dts | 1 - boards/others/black_f407ve/black_f407ve.dts | 2 -- boards/others/black_f407zg_pro/black_f407zg_pro.dts | 2 -- boards/pjrc/teensy4/teensy40.dts | 11 +---------- boards/qemu/x86/qemu_x86.dts | 1 - .../renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts | 1 - .../rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts | 1 - boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts | 1 - boards/seeed/xiao_esp32c3/xiao_esp32c3.dts | 1 - boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts | 1 - .../shields/mcp2515/adafruit_can_picowbell.overlay | 1 - boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay | 1 - .../mcp2515/keyestudio_can_bus_ks0411.overlay | 1 - .../mikroe_mcp2518fd_click.overlay | 2 -- boards/shields/tcan4550evm/tcan4550evm.overlay | 2 -- boards/st/nucleo_f091rc/nucleo_f091rc.dts | 1 - boards/st/nucleo_f303re/nucleo_f303re.dts | 1 - boards/st/nucleo_f446re/nucleo_f446re.dts | 2 -- boards/st/nucleo_f446ze/nucleo_f446ze.dts | 1 - boards/st/nucleo_f722ze/nucleo_f722ze.dts | 1 - boards/st/nucleo_f746zg/nucleo_f746zg.dts | 1 - boards/st/nucleo_f767zi/nucleo_f767zi.dts | 1 - boards/st/nucleo_g0b1re/nucleo_g0b1re.dts | 4 ---- boards/st/nucleo_g474re/nucleo_g474re.dts | 2 -- boards/st/nucleo_h743zi/nucleo_h743zi.dts | 2 -- boards/st/nucleo_h753zi/nucleo_h753zi.dts | 2 -- boards/st/nucleo_l432kc/nucleo_l432kc.dts | 1 - boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts | 1 - boards/st/nucleo_l452re/nucleo_l452re_common.dtsi | 1 - .../st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi | 2 -- .../st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi | 2 -- boards/st/stm32f072b_disco/stm32f072b_disco.dts | 1 - boards/st/stm32f3_disco/stm32f3_disco.dts | 1 - boards/st/stm32f4_disco/stm32f4_disco.dts | 2 -- boards/st/stm32h573i_dk/stm32h573i_dk.dts | 2 -- boards/st/stm32h735g_disco/stm32h735g_disco.dts | 6 ------ .../stm32h745i_disco_stm32h745xx_m7.dts | 4 ---- boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts | 2 -- boards/waveshare/open103z/waveshare_open103z.dts | 1 - doc/hardware/porting/board_porting.rst | 1 - dts/bindings/can/microchip,mcp251xfd.yaml | 2 -- dts/bindings/can/nxp,flexcan-fd.yaml | 2 -- dts/bindings/can/nxp,flexcan.yaml | 1 - dts/bindings/can/ti,tcan4x5x.yaml | 2 -- tests/drivers/can/api/twai-enable.overlay | 1 - tests/drivers/can/shell/app.overlay | 2 -- tests/lib/devicetree/api/app.overlay | 4 ---- 79 files changed, 1 insertion(+), 163 deletions(-) diff --git a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts index 4459780243b1b4..0ffb4f75380fb9 100644 --- a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts +++ b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts @@ -141,8 +141,6 @@ pinctrl-names = "default"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flash0 { diff --git a/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi b/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi index 93dc9b1f356840..ded3866acfe67f 100644 --- a/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi +++ b/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi @@ -206,9 +206,6 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi b/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi index 9864c7ae50a1f1..f6981455b51224 100644 --- a/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi +++ b/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi @@ -331,9 +331,6 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts index 79ff5b90ecfd76..3827dc104d993c 100644 --- a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts +++ b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts @@ -162,9 +162,6 @@ pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; @@ -174,9 +171,6 @@ pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts b/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts index e636089ba03e3d..f1d9481a8b7571 100644 --- a/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts +++ b/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts @@ -94,7 +94,6 @@ status = "disabled"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &flash0 { diff --git a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts index 253731fc7212b7..4538c41fa5f791 100644 --- a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts +++ b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts @@ -112,7 +112,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { diff --git a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts index e0d4461a33bc02..0cb8b962829a63 100644 --- a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts +++ b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts @@ -112,7 +112,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts index 38d870a6fbb260..255fc34c051a9e 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts +++ b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts @@ -142,7 +142,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { diff --git a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts index df37b32e3c781f..a7b50692c07524 100644 --- a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts +++ b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts @@ -207,7 +207,6 @@ &can_node1 { status = "okay"; - bus-speed = <125000>; input-src = "RXDC"; pinctrl-0 = <&can_tx_p1_12_node1 &can_rx_p1_13_node1>; pinctrl-names = "default"; diff --git a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi index 2972e4725f1d2e..bf83c33898c3d5 100644 --- a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi +++ b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi @@ -94,7 +94,6 @@ status = "disabled"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &flash0 { diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi index efaded4d02d6f8..849dd35bd67196 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi @@ -85,7 +85,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { diff --git a/boards/m5stack/stamp_c3/stamp_c3.dts b/boards/m5stack/stamp_c3/stamp_c3.dts index 56353da3d8135c..812c2aeaa86d84 100644 --- a/boards/m5stack/stamp_c3/stamp_c3.dts +++ b/boards/m5stack/stamp_c3/stamp_c3.dts @@ -93,7 +93,6 @@ status = "disabled"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &flash0 { diff --git a/boards/native/native_sim/native_sim.dts b/boards/native/native_sim/native_sim.dts index aa4f2eab0c818b..5ed512dd05e48c 100644 --- a/boards/native/native_sim/native_sim.dts +++ b/boards/native/native_sim/native_sim.dts @@ -190,7 +190,6 @@ can_loopback0: can_loopback0 { status = "okay"; compatible = "zephyr,can-loopback"; - bus-speed = <125000>; }; can0: can { @@ -200,7 +199,6 @@ * name, e.g.: sudo ip link property add dev vcan0 altname zcan0 */ host-interface = "zcan0"; - bus-speed = <125000>; }; rtc: rtc { diff --git a/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts b/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts index 28db9b9265a113..69b0aa3fafc92f 100644 --- a/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts +++ b/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts @@ -111,8 +111,6 @@ }; &canfd0 { - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&canfd0_default>; pinctrl-names = "default"; status = "okay"; diff --git a/boards/nxp/frdm_k64f/frdm_k64f.dts b/boards/nxp/frdm_k64f/frdm_k64f.dts index 6fb7def19730b1..4c42385a794edb 100644 --- a/boards/nxp/frdm_k64f/frdm_k64f.dts +++ b/boards/nxp/frdm_k64f/frdm_k64f.dts @@ -286,7 +286,6 @@ zephyr_udc0: &usbotg { status = "okay"; pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &edma0 { diff --git a/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi b/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi index aa2373b829ccf8..42849ac568bf1d 100644 --- a/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi +++ b/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi @@ -151,8 +151,6 @@ &can0 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_can0>; pinctrl-names = "default"; diff --git a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi index 1b68d976f3e8a2..d081a79b96913e 100644 --- a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi +++ b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi @@ -147,8 +147,6 @@ &can0 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_can0>; pinctrl-names = "default"; diff --git a/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts b/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts index be2b16c27f7503..42b48e8c203f4a 100644 --- a/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts +++ b/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts @@ -126,8 +126,6 @@ }; &can0 { - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_mcan_can0>; pinctrl-names = "default"; status = "okay"; diff --git a/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts b/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts index 472cd02630193d..c2c90d85996833 100644 --- a/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts +++ b/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts @@ -168,7 +168,6 @@ arduino_serial: &lpuart2 { &flexcan1 { status = "okay"; - bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts index 43a440994307ef..08eb8541432c44 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts @@ -242,8 +242,6 @@ zephyr_udc0: &usb1 { &flexcan3 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; diff --git a/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts b/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts index 73b9e9704050d6..85a53c07f298af 100644 --- a/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts +++ b/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts @@ -109,7 +109,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <5000000>; }; @@ -119,7 +118,6 @@ status = "disabled"; pinctrl-0 = <&pinmux_flexcan2>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <5000000>; }; @@ -129,8 +127,6 @@ status = "disabled"; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts index 387b116d601544..7351659dd87ff4 100644 --- a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts +++ b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts @@ -310,7 +310,6 @@ zephyr_udc0: &usb1 { &flexcan2 { status = "okay"; - bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan2>; pinctrl-names = "default"; diff --git a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts index 9bdf8f088b1db6..2f4e842873f082 100644 --- a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts +++ b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts @@ -45,8 +45,6 @@ &flexcan3 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts index d4400dea0f4ffc..95eff6eb715f58 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts @@ -74,8 +74,6 @@ zephyr_mipi_dsi: &mipi_dsi { &flexcan3 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/nxp/mr_canhubk3/mr_canhubk3.dts b/boards/nxp/mr_canhubk3/mr_canhubk3.dts index 65f6c86d56942e..ba74e255f625e2 100644 --- a/boards/nxp/mr_canhubk3/mr_canhubk3.dts +++ b/boards/nxp/mr_canhubk3/mr_canhubk3.dts @@ -358,8 +358,6 @@ pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; phys = <&can_phy0>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; @@ -367,40 +365,30 @@ pinctrl-0 = <&flexcan1_default>; pinctrl-names = "default"; phys = <&can_phy1>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan2 { pinctrl-0 = <&flexcan2_default>; pinctrl-names = "default"; phys = <&can_phy2>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan3 { pinctrl-0 = <&flexcan3_default>; pinctrl-names = "default"; phys = <&can_phy3>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan4 { pinctrl-0 = <&flexcan4_default>; pinctrl-names = "default"; phys = <&can_phy4>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan5 { pinctrl-0 = <&flexcan5_default>; pinctrl-names = "default"; phys = <&can_phy5>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &lpi2c0 { diff --git a/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts b/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts index 2399766c0c2f29..8d2b01c44ba130 100644 --- a/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts +++ b/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts @@ -281,7 +281,6 @@ zephyr_udc0: &usbotg { status = "okay"; pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver0>; }; @@ -289,7 +288,6 @@ zephyr_udc0: &usbotg { status = "okay"; pinctrl-0 = <&flexcan1_default>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver1>; }; diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi index 297b4926d11e11..1270676c77a56f 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi @@ -34,14 +34,10 @@ &can0 { pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; &can1 { pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; diff --git a/boards/nxp/twr_ke18f/twr_ke18f.dts b/boards/nxp/twr_ke18f/twr_ke18f.dts index 5bc591f0726c15..e0f3e1d242c0ea 100644 --- a/boards/nxp/twr_ke18f/twr_ke18f.dts +++ b/boards/nxp/twr_ke18f/twr_ke18f.dts @@ -293,7 +293,6 @@ &flexcan0 { status = "okay"; - bus-speed = <125000>; pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; diff --git a/boards/nxp/ucans32k1sic/ucans32k1sic.dts b/boards/nxp/ucans32k1sic/ucans32k1sic.dts index 57ca5dd43b3106..77b9523634386c 100644 --- a/boards/nxp/ucans32k1sic/ucans32k1sic.dts +++ b/boards/nxp/ucans32k1sic/ucans32k1sic.dts @@ -179,8 +179,6 @@ pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; phys = <&can_phy0>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; @@ -188,7 +186,5 @@ pinctrl-0 = <&flexcan1_default>; pinctrl-names = "default"; phys = <&can_phy1>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts index 9c44e8d874e853..c2ea2f474967b6 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts +++ b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts @@ -175,8 +175,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -186,8 +184,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan2>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -197,8 +193,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts index 11747f1a7b6e91..63070f08e1cd1d 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts @@ -100,7 +100,6 @@ uext_spi: &spi2 {}; status = "okay"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/boards/olimex/olimexino_stm32/olimexino_stm32.dts b/boards/olimex/olimexino_stm32/olimexino_stm32.dts index 931012548fd6a7..8c3a3b1491a100 100644 --- a/boards/olimex/olimexino_stm32/olimexino_stm32.dts +++ b/boards/olimex/olimexino_stm32/olimexino_stm32.dts @@ -166,7 +166,6 @@ zephyr_udc0: &usb { &can1 { pinctrl-0 = <&can_rx_remap1_pb8 &can_tx_remap1_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver0>; status = "okay"; }; diff --git a/boards/olimex/stm32_p405/olimex_stm32_p405.dts b/boards/olimex/stm32_p405/olimex_stm32_p405.dts index 866a8318f3e8fc..776bf4a3827c5c 100644 --- a/boards/olimex/stm32_p405/olimex_stm32_p405.dts +++ b/boards/olimex/stm32_p405/olimex_stm32_p405.dts @@ -87,7 +87,6 @@ &can1 { pinctrl-0 = <&can1_rx_pb8 &can1_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; can-transceiver { diff --git a/boards/others/black_f407ve/black_f407ve.dts b/boards/others/black_f407ve/black_f407ve.dts index 6a76109ce84446..539f9838fbf4bc 100644 --- a/boards/others/black_f407ve/black_f407ve.dts +++ b/boards/others/black_f407ve/black_f407ve.dts @@ -126,14 +126,12 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "disabled"; }; &can2 { pinctrl-0 = <&can2_rx_pb12 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/others/black_f407zg_pro/black_f407zg_pro.dts b/boards/others/black_f407zg_pro/black_f407zg_pro.dts index 45a311c50307d2..2d96ce6a4fbb3e 100644 --- a/boards/others/black_f407zg_pro/black_f407zg_pro.dts +++ b/boards/others/black_f407zg_pro/black_f407zg_pro.dts @@ -125,14 +125,12 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "disabled"; }; &can2 { pinctrl-0 = <&can2_rx_pb12 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/pjrc/teensy4/teensy40.dts b/boards/pjrc/teensy4/teensy40.dts index 4b676664956cc2..63775c3d1c618e 100644 --- a/boards/pjrc/teensy4/teensy40.dts +++ b/boards/pjrc/teensy4/teensy40.dts @@ -66,11 +66,6 @@ zephyr_udc0: &usb1 { current-speed = < 115200 >; }; -&flexcan1 { - status = "okay"; - bus-speed = < 125000 >; -}; - &edma0 { status = "okay"; }; @@ -98,11 +93,7 @@ zephyr_udc0: &usb1 { &flexcan1 { pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; -}; - -&flexcan1 { - pinctrl-0 = <&pinmux_flexcan1>; - pinctrl-names = "default"; + status = "okay"; }; &flexcan2 { diff --git a/boards/qemu/x86/qemu_x86.dts b/boards/qemu/x86/qemu_x86.dts index fbe6042c1781cb..023c551eb47acf 100644 --- a/boards/qemu/x86/qemu_x86.dts +++ b/boards/qemu/x86/qemu_x86.dts @@ -61,7 +61,6 @@ device-id = <0x8406>; interrupts = <11 IRQ_TYPE_LOWEST_LEVEL_LOW 3>; interrupt-parent = <&intc>; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts index a5a23e779d819f..cadd4dc9799746 100644 --- a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts +++ b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts @@ -63,7 +63,6 @@ pinctrl-0 = <&can0_data_a_tx_default &can0_data_a_rx_default>; pinctrl-names = "default"; status = "okay"; - bus-speed = <125000>; can-transceiver { max-bitrate = <5000000>; diff --git a/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts b/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts index ce5c046f54ad9e..d0db253f127347 100644 --- a/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts +++ b/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts @@ -75,7 +75,6 @@ pinctrl-0 = <&can0_data_a_tx_default &can0_data_a_rx_default>; pinctrl-names = "default"; status = "okay"; - bus-speed = <125000>; }; &scif1 { diff --git a/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts b/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts index 79577593ddbf51..bfd1fc3c30bdbd 100644 --- a/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts +++ b/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts @@ -177,7 +177,6 @@ zephyr_udc0: &usb { &can1 { pinctrl-0 = <&can_rx_pb8 &can_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver0>; status = "okay"; }; diff --git a/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts b/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts index 5cea1004af625e..8475709095b16b 100644 --- a/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts +++ b/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts @@ -83,7 +83,6 @@ status = "okay"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &wifi { diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts index 99d7f0deb75fb5..ae232f4d228107 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts @@ -91,7 +91,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { diff --git a/boards/shields/mcp2515/adafruit_can_picowbell.overlay b/boards/shields/mcp2515/adafruit_can_picowbell.overlay index 8a9d719e641abf..9e86a3236d35a2 100644 --- a/boards/shields/mcp2515/adafruit_can_picowbell.overlay +++ b/boards/shields/mcp2515/adafruit_can_picowbell.overlay @@ -15,7 +15,6 @@ status = "okay"; reg = <0x0>; osc-freq = <16000000>; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay b/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay index e520218830ec53..290522d8c921fd 100644 --- a/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay +++ b/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay @@ -15,7 +15,6 @@ status = "okay"; reg = <0x0>; osc-freq = <16000000>; - bus-speed = <125000>; can-transceiver { min-bitrate = <60000>; diff --git a/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay b/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay index e4136cf577bf30..d1f988f281ed7a 100644 --- a/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay +++ b/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay @@ -15,7 +15,6 @@ status = "okay"; reg = <0x0>; osc-freq = <16000000>; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay b/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay index 43094d1d72ae77..522017c81eac64 100644 --- a/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay +++ b/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay @@ -10,8 +10,6 @@ reg = <0x0>; osc-freq = <40000000>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; }; diff --git a/boards/shields/tcan4550evm/tcan4550evm.overlay b/boards/shields/tcan4550evm/tcan4550evm.overlay index d25d8ff0e62088..7aeb3022a9a2d2 100644 --- a/boards/shields/tcan4550evm/tcan4550evm.overlay +++ b/boards/shields/tcan4550evm/tcan4550evm.overlay @@ -28,8 +28,6 @@ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_HIGH>; /* D8 */ int-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ bosch,mram-cfg = <0x0 15 15 7 7 0 10 10>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; can-transceiver { diff --git a/boards/st/nucleo_f091rc/nucleo_f091rc.dts b/boards/st/nucleo_f091rc/nucleo_f091rc.dts index b7a94b29e9e833..b24435909182a2 100644 --- a/boards/st/nucleo_f091rc/nucleo_f091rc.dts +++ b/boards/st/nucleo_f091rc/nucleo_f091rc.dts @@ -116,7 +116,6 @@ &can1 { pinctrl-0 = <&can_rx_pa11 &can_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f303re/nucleo_f303re.dts b/boards/st/nucleo_f303re/nucleo_f303re.dts index 7259a9f34af0e4..af1bea6d92ac74 100644 --- a/boards/st/nucleo_f303re/nucleo_f303re.dts +++ b/boards/st/nucleo_f303re/nucleo_f303re.dts @@ -94,7 +94,6 @@ &can1 { pinctrl-0 = <&can_rx_pb8 &can_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f446re/nucleo_f446re.dts b/boards/st/nucleo_f446re/nucleo_f446re.dts index 6afc2996acc6ce..3674692ec97633 100644 --- a/boards/st/nucleo_f446re/nucleo_f446re.dts +++ b/boards/st/nucleo_f446re/nucleo_f446re.dts @@ -147,14 +147,12 @@ /* CAUTION: PB8 and PB9 may conflict with same pins of I2C1 */ pinctrl-0 = <&can1_rx_pb8 &can1_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; &can2 { pinctrl-0 = <&can2_rx_pb12 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f446ze/nucleo_f446ze.dts b/boards/st/nucleo_f446ze/nucleo_f446ze.dts index d6c7dd4be456a2..5eaad0ca83db5b 100644 --- a/boards/st/nucleo_f446ze/nucleo_f446ze.dts +++ b/boards/st/nucleo_f446ze/nucleo_f446ze.dts @@ -180,7 +180,6 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f722ze/nucleo_f722ze.dts b/boards/st/nucleo_f722ze/nucleo_f722ze.dts index 47bce02573291b..988a1204a9fdd9 100644 --- a/boards/st/nucleo_f722ze/nucleo_f722ze.dts +++ b/boards/st/nucleo_f722ze/nucleo_f722ze.dts @@ -123,7 +123,6 @@ &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f746zg/nucleo_f746zg.dts b/boards/st/nucleo_f746zg/nucleo_f746zg.dts index db57eb734dc20b..90c4b4409a0eb6 100644 --- a/boards/st/nucleo_f746zg/nucleo_f746zg.dts +++ b/boards/st/nucleo_f746zg/nucleo_f746zg.dts @@ -166,7 +166,6 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f767zi/nucleo_f767zi.dts b/boards/st/nucleo_f767zi/nucleo_f767zi.dts index 8ae863248f2261..4125f4e6bde13b 100644 --- a/boards/st/nucleo_f767zi/nucleo_f767zi.dts +++ b/boards/st/nucleo_f767zi/nucleo_f767zi.dts @@ -165,7 +165,6 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts b/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts index ec79bd3575d319..d86d7c6ae8eea6 100644 --- a/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts +++ b/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts @@ -183,8 +183,6 @@ zephyr_udc0: &usb { <&rcc STM32_SRC_PLL_Q FDCAN_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; @@ -193,8 +191,6 @@ zephyr_udc0: &usb { <&rcc STM32_SRC_PLL_Q FDCAN_SEL(1)>; pinctrl-0 = <&fdcan2_rx_pb0 &fdcan2_tx_pb1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_g474re/nucleo_g474re.dts b/boards/st/nucleo_g474re/nucleo_g474re.dts index 74b0308d706daf..a91ec3ccb60347 100644 --- a/boards/st/nucleo_g474re/nucleo_g474re.dts +++ b/boards/st/nucleo_g474re/nucleo_g474re.dts @@ -223,8 +223,6 @@ stm32_lp_tick_source: &lptim1 { <&rcc STM32_SRC_HSE FDCAN_SEL(0)>; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_h743zi/nucleo_h743zi.dts b/boards/st/nucleo_h743zi/nucleo_h743zi.dts index fd1a5a8b29ff8d..f410d6f956e9d4 100644 --- a/boards/st/nucleo_h743zi/nucleo_h743zi.dts +++ b/boards/st/nucleo_h743zi/nucleo_h743zi.dts @@ -172,8 +172,6 @@ zephyr_udc0: &usbotg_fs { pinctrl-names = "default"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_h753zi/nucleo_h753zi.dts b/boards/st/nucleo_h753zi/nucleo_h753zi.dts index d8cc922acada28..e3b52c2b50cfe8 100644 --- a/boards/st/nucleo_h753zi/nucleo_h753zi.dts +++ b/boards/st/nucleo_h753zi/nucleo_h753zi.dts @@ -149,8 +149,6 @@ zephyr_udc0: &usbotg_fs { &fdcan1 { pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_l432kc/nucleo_l432kc.dts b/boards/st/nucleo_l432kc/nucleo_l432kc.dts index 370cfe3a0d87b2..f6a3d56891399d 100644 --- a/boards/st/nucleo_l432kc/nucleo_l432kc.dts +++ b/boards/st/nucleo_l432kc/nucleo_l432kc.dts @@ -99,7 +99,6 @@ &can1 { pinctrl-0 = <&can1_rx_pa11 &can1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts b/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts index 3c58b14302df26..4e483b55f002bf 100644 --- a/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts +++ b/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts @@ -118,7 +118,6 @@ &can1 { pinctrl-0 = <&can1_rx_pa11 &can1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi b/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi index 3da0ae94b9993d..8f0d76d9a8651e 100644 --- a/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi +++ b/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi @@ -102,7 +102,6 @@ &can1 { pinctrl-0 = <&can1_rx_pa11 &can1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi index 26069f4b73f54a..bd8dc8453e0913 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi @@ -183,8 +183,6 @@ zephyr_udc0: &usbotg_fs { <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi index 14a5b1de80fe00..a08d7b47ce2a45 100644 --- a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi +++ b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi @@ -175,8 +175,6 @@ <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/stm32f072b_disco/stm32f072b_disco.dts b/boards/st/stm32f072b_disco/stm32f072b_disco.dts index 363e5a565c565d..de73e11af6f99a 100644 --- a/boards/st/stm32f072b_disco/stm32f072b_disco.dts +++ b/boards/st/stm32f072b_disco/stm32f072b_disco.dts @@ -118,7 +118,6 @@ &can1 { pinctrl-0 = <&can_rx_pb8 &can_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/stm32f3_disco/stm32f3_disco.dts b/boards/st/stm32f3_disco/stm32f3_disco.dts index f90c10cf71cc11..44a66f038be73c 100644 --- a/boards/st/stm32f3_disco/stm32f3_disco.dts +++ b/boards/st/stm32f3_disco/stm32f3_disco.dts @@ -185,7 +185,6 @@ zephyr_udc0: &usb { pinctrl-0 = <&can_rx_pd0 &can_tx_pd1>; pinctrl-names = "default"; status = "okay"; - bus-speed = <125000>; }; &flash0 { diff --git a/boards/st/stm32f4_disco/stm32f4_disco.dts b/boards/st/stm32f4_disco/stm32f4_disco.dts index 2847c2fcfdb155..163612aaf0759c 100644 --- a/boards/st/stm32f4_disco/stm32f4_disco.dts +++ b/boards/st/stm32f4_disco/stm32f4_disco.dts @@ -129,13 +129,11 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pb8 &can1_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "disabled"; }; &can2 { pinctrl-0 = <&can2_rx_pb5 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.dts b/boards/st/stm32h573i_dk/stm32h573i_dk.dts index 05f13c64f4602f..721cea3ab6aeb8 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.dts +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.dts @@ -247,8 +247,6 @@ <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/stm32h735g_disco/stm32h735g_disco.dts b/boards/st/stm32h735g_disco/stm32h735g_disco.dts index 4843e98a709d2f..41e67e551c2c2e 100644 --- a/boards/st/stm32h735g_disco/stm32h735g_disco.dts +++ b/boards/st/stm32h735g_disco/stm32h735g_disco.dts @@ -216,8 +216,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <8000000>; @@ -230,8 +228,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <8000000>; @@ -245,8 +241,6 @@ <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; /* Solder bridges SB29 and SB30 need to be closed for this to work */ status = "disabled"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <8000000>; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts index 227cb9ab8c266f..e140f6d22bc0d4 100644 --- a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts @@ -202,8 +202,6 @@ status = "okay"; pinctrl-0 = <&fdcan1_tx_ph13 &fdcan1_rx_ph14>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; sample-point = <875>; sample-point-data = <875>; @@ -216,8 +214,6 @@ status = "okay"; pinctrl-0 = <&fdcan2_tx_pb13 &fdcan2_rx_pb5>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; sample-point = <875>; sample-point-data = <875>; diff --git a/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts b/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts index 1567585b2fd535..88685817706858 100644 --- a/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts +++ b/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts @@ -156,8 +156,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; phys = <&transceiver0>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/waveshare/open103z/waveshare_open103z.dts b/boards/waveshare/open103z/waveshare_open103z.dts index 6d2e47595488cd..72dd744c4c21bb 100644 --- a/boards/waveshare/open103z/waveshare_open103z.dts +++ b/boards/waveshare/open103z/waveshare_open103z.dts @@ -156,7 +156,6 @@ * reference: RM0008 rev20 page 205 */ status = "disabled"; - bus-speed = <125000>; }; zephyr_udc0: &usb { diff --git a/doc/hardware/porting/board_porting.rst b/doc/hardware/porting/board_porting.rst index 7543e062ada3fa..a2b7796ebfae5f 100644 --- a/doc/hardware/porting/board_porting.rst +++ b/doc/hardware/porting/board_porting.rst @@ -488,7 +488,6 @@ controller and sets the bus speed: &can0 { status = "okay"; - bus-speed = <125000>; }; The ``&can0 { ... };`` syntax adds/overrides properties on the node with label diff --git a/dts/bindings/can/microchip,mcp251xfd.yaml b/dts/bindings/can/microchip,mcp251xfd.yaml index e4350760594751..168314547eff54 100644 --- a/dts/bindings/can/microchip,mcp251xfd.yaml +++ b/dts/bindings/can/microchip,mcp251xfd.yaml @@ -19,8 +19,6 @@ description: | reg = <0x0>; osc-freq = <40000000>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; }; diff --git a/dts/bindings/can/nxp,flexcan-fd.yaml b/dts/bindings/can/nxp,flexcan-fd.yaml index f55eb780c2d6e3..ce65192812374e 100644 --- a/dts/bindings/can/nxp,flexcan-fd.yaml +++ b/dts/bindings/can/nxp,flexcan-fd.yaml @@ -15,8 +15,6 @@ description: | interrupt-names = "common"; clocks = <&ccm IMX_CCM_CAN_CLK 0x84 6>; clk-source = <2>; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; diff --git a/dts/bindings/can/nxp,flexcan.yaml b/dts/bindings/can/nxp,flexcan.yaml index 736382d68bd0eb..045c09974fcddf 100644 --- a/dts/bindings/can/nxp,flexcan.yaml +++ b/dts/bindings/can/nxp,flexcan.yaml @@ -13,7 +13,6 @@ description: | interrupt-names = "warning", "error", "wake-up", "mb-0-15"; clocks = <&scg KINETIS_SCG_BUS_CLK>; clk-source = <1>; - bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan0>; pinctrl-names = "default"; diff --git a/dts/bindings/can/ti,tcan4x5x.yaml b/dts/bindings/can/ti,tcan4x5x.yaml index 5c74989093ca0a..75b115d697ceed 100644 --- a/dts/bindings/can/ti,tcan4x5x.yaml +++ b/dts/bindings/can/ti,tcan4x5x.yaml @@ -16,8 +16,6 @@ description: | reset-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; int-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; bosch,mram-cfg = <0x0 15 15 5 5 0 10 10>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; can-transceiver { diff --git a/tests/drivers/can/api/twai-enable.overlay b/tests/drivers/can/api/twai-enable.overlay index c98aba18376d0a..7a4ee3b7daf4e8 100644 --- a/tests/drivers/can/api/twai-enable.overlay +++ b/tests/drivers/can/api/twai-enable.overlay @@ -9,7 +9,6 @@ status = "okay"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/tests/drivers/can/shell/app.overlay b/tests/drivers/can/shell/app.overlay index 5d9827e2f35dda..1de44e0e9c5edd 100644 --- a/tests/drivers/can/shell/app.overlay +++ b/tests/drivers/can/shell/app.overlay @@ -8,7 +8,5 @@ fake_can: fake_can { compatible = "zephyr,fake-can"; status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; }; diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay index 5ee7171d932f8c..ee3bef5db41486 100644 --- a/tests/lib/devicetree/api/app.overlay +++ b/tests/lib/devicetree/api/app.overlay @@ -528,7 +528,6 @@ test_can0: can@55553333 { compatible = "vnd,can-controller"; reg = < 0x55553333 0x1000 >; - bus-speed = <125000>; status = "okay"; phys = <&test_transceiver0>; }; @@ -536,7 +535,6 @@ test_can1: can@55554444 { compatible = "vnd,can-controller"; reg = < 0x55554444 0x1000 >; - bus-speed = <125000>; status = "okay"; can-transceiver { @@ -548,7 +546,6 @@ test_can2: can@55555555 { compatible = "vnd,can-controller"; reg = < 0x55555555 0x1000 >; - bus-speed = <125000>; status = "okay"; can-transceiver { @@ -559,7 +556,6 @@ test_can3: can@55557777 { compatible = "vnd,can-controller"; reg = < 0x55556666 0x1000 >; - bus-speed = <125000>; status = "okay"; phys = <&test_transceiver1>; }; From a1e3ad61666d67ef259899f632e2b7b3ec1e057a Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0796/1389] Bluetooth: Controller: Add missing guard for mic_state in ull_conn_iso The mic_state is a guarded field in event_done_extra where it was accessed outside of its guard. Signed-off-by: Emil Gydesen --- subsys/bluetooth/controller/ll_sw/ull_conn_iso.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index 25ca59bc44f681..06f8f9f3bc520f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -470,12 +470,15 @@ void ull_conn_iso_done(struct node_rx_event_done *done) /* CIS was setup and is now expected to be going */ if (done->extra.trx_performed_bitmask & (1U << LL_CIS_IDX_FROM_HANDLE(cis->lll.handle))) { - if (done->extra.mic_state == LLL_CONN_MIC_FAIL) { + if (false) { +#if defined(CONFIG_BT_CTLR_LE_ENC) + } else if (done->extra.mic_state == LLL_CONN_MIC_FAIL) { /* MIC failure - stop CIS and defer cleanup to after * teardown. */ ull_conn_iso_cis_stop(cis, NULL, BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL); +#endif /* CONFIG_BT_CTLR_LE_ENC */ } else { cis->event_expire = 0U; } From ec4b12427bd77ab61e5b7399df25c07694433692 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0797/1389] drivers: flash: stm32 qspi driver when Dual-Flash not supported Some stm32 devices with quadspi (like stm32l47x or stm32l48x) does not support Dual-Flash Mode. Avoid building error even if the &quadspi node has a property defined. Signed-off-by: Francois Ramu --- drivers/flash/flash_stm32_qspi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index 326c1129a36385..8421d71f16ee73 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -1283,7 +1283,12 @@ static int flash_stm32_qspi_init(const struct device *dev) HAL_QSPI_Init(&dev_data->hqspi); -#if DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) +#if DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) && \ + defined(QUADSPI_CR_FSEL) + /* + * Some stm32 mcu with quadspi (like stm32l47x or stm32l48x) + * does not support Dual-Flash Mode + */ uint8_t qspi_flash_id = DT_PROP(DT_NODELABEL(quadspi), flash_id); HAL_QSPI_SetFlashID(&dev_data->hqspi, From c1511cb17d4fe3268d93af75d5affe5a48baeb86 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0798/1389] boards: st: add steval_stwinbx1 support Add board support for steval_stwinbx1 Signed-off-by: Frederic Pillon --- boards/st/steval_stwinbx1/CMakeLists.txt | 3 + boards/st/steval_stwinbx1/Kconfig.defconfig | 21 + .../steval_stwinbx1/Kconfig.steval_stwinbx1 | 5 + boards/st/steval_stwinbx1/board.c | 33 ++ boards/st/steval_stwinbx1/board.cmake | 18 + boards/st/steval_stwinbx1/board.yml | 5 + .../doc/img/steval_stwinbx1.jpg | Bin 0 -> 74848 bytes boards/st/steval_stwinbx1/doc/index.rst | 442 ++++++++++++++++++ boards/st/steval_stwinbx1/steval_stwinbx1.dts | 288 ++++++++++++ .../st/steval_stwinbx1/steval_stwinbx1.yaml | 16 + .../steval_stwinbx1/steval_stwinbx1_defconfig | 32 ++ boards/st/steval_stwinbx1/support/openocd.cfg | 44 ++ 12 files changed, 907 insertions(+) create mode 100644 boards/st/steval_stwinbx1/CMakeLists.txt create mode 100644 boards/st/steval_stwinbx1/Kconfig.defconfig create mode 100644 boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 create mode 100644 boards/st/steval_stwinbx1/board.c create mode 100644 boards/st/steval_stwinbx1/board.cmake create mode 100644 boards/st/steval_stwinbx1/board.yml create mode 100644 boards/st/steval_stwinbx1/doc/img/steval_stwinbx1.jpg create mode 100644 boards/st/steval_stwinbx1/doc/index.rst create mode 100644 boards/st/steval_stwinbx1/steval_stwinbx1.dts create mode 100644 boards/st/steval_stwinbx1/steval_stwinbx1.yaml create mode 100644 boards/st/steval_stwinbx1/steval_stwinbx1_defconfig create mode 100644 boards/st/steval_stwinbx1/support/openocd.cfg diff --git a/boards/st/steval_stwinbx1/CMakeLists.txt b/boards/st/steval_stwinbx1/CMakeLists.txt new file mode 100644 index 00000000000000..f2a184ea87fe59 --- /dev/null +++ b/boards/st/steval_stwinbx1/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_sources(board.c) diff --git a/boards/st/steval_stwinbx1/Kconfig.defconfig b/boards/st/steval_stwinbx1/Kconfig.defconfig new file mode 100644 index 00000000000000..be9fa9523a5398 --- /dev/null +++ b/boards/st/steval_stwinbx1/Kconfig.defconfig @@ -0,0 +1,21 @@ +# STEVAL_STWINBX1 Development kit board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STEVAL_STWINBX1 + +config SPI_STM32_INTERRUPT + default y + depends on SPI + +if LOG + +# Logger cannot use itself to log +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +endif # LOG + +endif # BOARD_STEVAL_STWINBX1 diff --git a/boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 b/boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 new file mode 100644 index 00000000000000..aae01c61ac7765 --- /dev/null +++ b/boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STEVAL_STWINBX1 + select SOC_STM32U585XX diff --git a/boards/st/steval_stwinbx1/board.c b/boards/st/steval_stwinbx1/board.c new file mode 100644 index 00000000000000..1d98da4aba0916 --- /dev/null +++ b/boards/st/steval_stwinbx1/board.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CONSOLE) && defined(CONFIG_UART_CONSOLE) +#if DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart) +/* + * Enable console on USB CDC_ACM + */ +static int steval_stwinbx1_usb_console_init(void) +{ + const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); + + if (!device_is_ready(dev)) { + return -ENODEV; + } + return (usb_enable(NULL)); +} + +/* needs to be done at Application */ +SYS_INIT(steval_stwinbx1_usb_console_init, APPLICATION, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#endif /* DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart) */ +#endif /* defined(CONFIG_CONSOLE) && defined (CONFIG_UART_CONSOLE) */ diff --git a/boards/st/steval_stwinbx1/board.cmake b/boards/st/steval_stwinbx1/board.cmake new file mode 100644 index 00000000000000..7b41b6115ca782 --- /dev/null +++ b/boards/st/steval_stwinbx1/board.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# By default stm32cubeprogrammer configured to use DFU upload method. +# Comment below line and uncomment the second line to use SWD upoad method. +board_runner_args(stm32cubeprogrammer "--port=usb1") +# board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +# Even if flash and start work, dfu-util return error 74. It can be ignored. +board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse") + +board_runner_args(openocd "--tcl-port=6666") +board_runner_args(openocd --cmd-pre-init "gdb_report_data_abort enable") +board_runner_args(openocd "--no-halt") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/st/steval_stwinbx1/board.yml b/boards/st/steval_stwinbx1/board.yml new file mode 100644 index 00000000000000..64319223253718 --- /dev/null +++ b/boards/st/steval_stwinbx1/board.yml @@ -0,0 +1,5 @@ +board: + name: steval_stwinbx1 + vendor: st + socs: + - name: stm32u585xx diff --git a/boards/st/steval_stwinbx1/doc/img/steval_stwinbx1.jpg b/boards/st/steval_stwinbx1/doc/img/steval_stwinbx1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed0b01c815889649a2167952acadd2659485dacc GIT binary patch literal 74848 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 literal 0 HcmV?d00001 diff --git a/boards/st/steval_stwinbx1/doc/index.rst b/boards/st/steval_stwinbx1/doc/index.rst new file mode 100644 index 00000000000000..367de5d437348d --- /dev/null +++ b/boards/st/steval_stwinbx1/doc/index.rst @@ -0,0 +1,442 @@ +.. _steval_stwinbx1_board: + +STEVAL STWINBX1 Development kit +############################### + +Overview +******** + +The STWIN.box (STEVAL-STWINBX1) is a development kit that features an Arm|reg| Cortex|reg|-M33 based STM32U585AI MCU +and is a reference design that simplifies prototyping and testing of advanced industrial sensing applications in +IoT contexts such as condition monitoring and predictive maintenance. + +The STEVAL-STWINBX1 kit consists of an STWIN.box core system, a 480mAh LiPo battery, an adapter for the ST-LINK debugger, +a plastic case, an adapter board for DIL 24 sensors and a flexible cable. + +.. image:: img/steval_stwinbx1.jpg + :align: center + :alt: STEVAL-STWINBX1 Development kit + +More information about the board can be found at the `STEVAL-STWINBX1 Development kit website`_. + + +Supported Features +****************** + +The STEVAL-STWINBX1 provides motion, environmental, and audio +sensor data through either the built-in RS485 transceiver, BLE, Wi-Fi, and +NFC or USB protocols to a host application running on a smartphone/PC to implement applications such as: + +- Multisensing wireless platform for vibration monitoring and ultrasound detection +- Baby crying detection with Cloud AI learning +- Barometer / environmental monitoring +- Vehicle / goods tracking +- Vibration monitoring +- Compass and inclinometer +- Sensor data logger + +(see `Sensing`_ section for the complete lists of available +sensors on board) + +Hardware +******** + +The STM32U585xx devices are an ultra-low-power microcontrollers family (STM32U5 +Series) based on the high-performance Arm|reg| Cortex|reg|-M33 32-bit RISC core. +They operate at a frequency of up to 160 MHz. + +- Ultra-low-power with FlexPowerControl (down to 300 nA Standby mode and 19.5 uA/MHz run mode) +- Core: ARM |reg| 32-bit Cortex |reg| -M33 CPU with TrustZone |reg| and FPU. +- Performance benchmark: + + - 1.5 DMPIS/MHz (Drystone 2.1) + - 651 CoreMark |reg| (4.07 CoreMark |reg| /MHZ) + +- Security and cryptography + + - Arm |reg| TrustZone |reg| and securable I/Os memories and peripherals + - Flexible life cycle scheme with RDP (readout protection) and password protected debug + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - Secure Firmware Installation thanks to embedded Root Secure Services + - Secure data storage with hardware unique key (HUK) + - Secure Firmware Update support with TF-M + - 2 AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - Active tampers + - True Random Number Generator NIST SP800-90B compliant + - 96-bit unique ID + - 512-byte One-Time Programmable for user data + - Active tampers + +- Clock management: + + - 4 to 50 MHz crystal oscillator + - 32 kHz crystal oscillator for RTC (LSE) + - Internal 16 MHz factory-trimmed RC ( |plusminus| 1%) + - Internal low-power 32 kHz RC ( |plusminus| 5%) + - 2 internal multispeed 100 kHz to 48 MHz oscillators, including one auto-trimmed by + LSE (better than |plusminus| 0.25 % accuracy) + - 3 PLLs for system clock, USB, audio, ADC + - Internal 48 MHz with clock recovery + +- Power management + + - Embedded regulator (LDO) + - Embedded SMPS step-down converter supporting switch on-the-fly and voltage scaling + +- RTC with HW calendar and calibration +- Up to 136 fast I/Os, most 5 V-tolerant, up to 14 I/Os with independent supply down to 1.08 V +- Up to 24 capacitive sensing channels: support touchkey, linear and rotary touch sensors +- Up to 17 timers and 2 watchdogs + + - 2x 16-bit advanced motor-control + - 2x 32-bit and 5 x 16-bit general purpose + - 4x low-power 16-bit timers (available in Stop mode) + - 2x watchdogs + - 2x SysTick timer + +- ART accelerator + + - 8-Kbyte instruction cache allowing 0-wait-state execution from Flash and + external memories: up to 160 MHz, MPU, 240 DMIPS and DSP + - 4-Kbyte data cache for external memories + +- Memories + + - 2-Mbyte Flash memory with ECC, 2 banks read-while-write, including 512 Kbytes with 100 kcycles + - 786-Kbyte SRAM with ECC OFF or 722-Kbyte SRAM including up to 322-Kbyte SRAM with ECC ON + - External memory interface supporting SRAM, PSRAM, NOR, NAND and FRAM memories + - 2 Octo-SPI memory interfaces + +- Rich analog peripherals (independent supply) + + - 14-bit ADC 2.5-Msps, resolution up to 16 bits with hardware oversampling + - 12-bit ADC 2.5-Msps, with hardware oversampling, autonomous in Stop 2 mode + - 12-bit DAC, low-power sample and hold + - 2 operational amplifiers with built-in PGA + - 2 ultra-low-power comparators + +- Up to 22 communication interfaces + + - USB Type-C / USB power delivery controller + - USB OTG 2.0 full-speed controller + - 2x SAIs (serial audio interface) + - 4x I2C FM+(1 Mbit/s), SMBus/PMBus + - 6x USARTs (ISO 7816, LIN, IrDA, modem) + - 3x SPIs (5x SPIs with dual OCTOSPI in SPI mode) + - 1x FDCAN + - 2x SDMMC interface + - 16- and 4-channel DMA controllers, functional in Stop mode + - 1 multi-function digital filter (6 filters)+ 1 audio digital filter with + sound-activity detection + +- CRC calculation unit +- Development support: serial wire debug (SWD), JTAG, Embedded Trace Macrocell |trade| +- True Random Number Generator (RNG) + +- Graphic features + + - Chrom-ART Accelerator (DMA2D) for enhanced graphic content creation + - 1 digital camera interface + +- Mathematical co-processor + + - CORDIC for trigonometric functions acceleration + - FMAC (filter mathematical accelerator) + + +More information about STM32U585AI can be found here: + +- `STM32U585 on www.st.com`_ +- `STM32U585 reference manual`_ + +Connectivity +************ + + - **BlueNRG-M2SA** Bluetooth|reg| low energy v5.2 wireless technology module + (`BlueNRG-M2 datasheet`_) + - **MXCHIP EMW3080** (802.11 b/g/n compliant Wi-Fi module) + - **ST25DV64K** dynamic NFC/RFID tag IC with 64-Kbit EEPROM + (`st25dv64k datasheet`_) + - USB Type-C|trade| connector (power supply and data) + - STDC14 programming connector for **STLINK-V3MINI** + (`stlink-v3mini`_) + - microSD card socket + +Sensing +******* + + - **ILPS22QS** MEMS pressure sensor + (`ilps22qs datasheet`_) + - **STTS22H** Digital temperature sensor + (`stts22hh datasheet`_) + - **TSV912** wide-bandwidth (8 MHz) rail-to-rail I/O op-amp + (`tsv912 datasheet`_) + - **ISM330DHCX** iNEMO IMU, 3D accelerometer and 3D gyroscope with Machine Learning Core and Finite State Machine + (`ism330dhcx datasheet`_) + - **IIS3DWB** wide bandwidth accelerometer + (`iis3dwb datasheet`_) + - **IIS2DLPC** high-performance ultra-low-power 3-axis accelerometer for industrial applications + (`iis2dlpc datasheet`_) + - **IIS2MDC** 3-axis magnetometer + (`iis2mdc datasheet`_) + - **IIS2ICLX** high-accuracy, high-resolution, low-power, 2-axis digital inclinometer with Machine Learning Core + (`iis2iclx datasheet`_) + - **IMP23ABSU** analog MEMS microphone + (`imp23absu datasheet`_) + - **IMP34DT05** digital MEMS microphone + (`imp34dt05 datasheet`_) + +Connections and IOs +******************* + +- 2x user LEDs + + - **led0** (Green) + - **led1** (Orange) + +- 4x buttons/switch + + - **User** / **boot0** button, available to user application + but useful to let the SensorTile.box PRO enter DFU mode + if found pressed after h/w reset (see **rst** button and + `Programming and Debugging`_ section) + - **RESET** button, used to reset the board + - **PWR** button, used to Power on/off the board + + +For more details please refer to `STEVAL-STWINBX1 board User Manual`_. + +System Clock +------------ + +STEVAL-STWINBX1 System Clock could be driven by an internal or external oscillator, +as well as the main PLL clock. By default the System clock is driven by the PLL clock at 160MHz, +driven by 16MHz high speed external oscillator. +The internal AHB/APB1/APB2/APB3 AMBA buses are all clocked at 160MHz. + +Serial Port +----------- + +The USART2 is connected to JTAG/SWD connector +and may be used as console. + +USB interface +------------- + +STEVAL-STWINBX1 can be connected as a USB device to a PC host through its USB-C connector. +The final application may use it to declare STEVAL-STWINBX1 device as belonging to a +certain standard or vendor class, e.g. a CDC, a mass storage or a composite device with both +functions. + +Console +------- + +There are two possible options for Zephyr console output: + +- through USART2 which is available on SWD connector (CN4). In this case a JTAG adapter + can be used to connect STEVAL-STWINBX1 and have both SWD and console lines available. + + To enable console and shell over UART + + - switch the console lines from cdc_acm to uart4 + (:file:`boards/st/steval_stwinbx1/steval_stwinbx1.dts`) + + - comment out the USB configuration macros + (:file:`boards/st/steval_stwinbx1/steval_stwinbx1_defconfig`) + +.. code-block:: dts + :caption: boards/st/steval_stwinbx1/steval_stwinbx1.dts + + / { + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + //zephyr,console = &cdc_acm_uart0; + //zephyr,shell-uart = &cdc_acm_uart0; + }; + }; + +.. code-block:: Kconfig + :caption: boards/st/steval_stwinbx1/steval_stwinbx1_defconfig + + # Comment out following USB config lines when + # switching console to UART + #CONFIG_USB_DEVICE_STACK=y + #CONFIG_USB_DEVICE_VID=0x0483 + #CONFIG_USB_DEVICE_PID=0x5740 + #CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC STEval-STWinbx1" + #CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +- through USB as USB CDC/ACM class. This is the default case present in the board dts file. + +.. code-block:: dts + :caption: boards/st/steval_stwinbx1/steval_stwinbx1.dts + + / { + chosen { + zephyr,console = &cdc_acm_uart0; + }; + }; + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; + }; + + + +Console default settings are 115200 8N1. + +Programming and Debugging +------------------------- + +There are two alternative methods of flashing ST Sensortile.box Pro board: + +1. Using DFU software tools + + This method requires to enter STM32U585 ROM bootloader DFU mode + by powering up (or reset) the board while keeping the USER (BOOT0) button pressed. + No additional hardware is required except a USB-C cable. This method is fully + supported by :ref:`flash-debug-host-tools`. + You can read more about how to enable and use the ROM bootloader by checking + the application note `AN2606`_ (STM32U585xx section). + +2. Using SWD hardware tools + + The STEVAL-STWINBX1 does not include a on-board debug probe. + It requires to connect additional hardware, like a ST-LINK/V3 + embedded debug tool, to the board STDC14 connector (CN4) labeled ``MCU-/SWD``. + + +Install dfu-util +---------------- + +.. note:: + Required only to use dfu-util runner. + +It is recommended to use at least v0.9 of dfu-util. The package available in +Debian and Ubuntu can be quite old, so you might have to build dfu-util from source. +Information about how to get the source code and how to build it can be found +at the `DFU-UTIL website`_ + +Install STM32CubeProgrammer +--------------------------- + +.. note:: + Required to program over DFU (default) or SWD. + +It is recommended to use the latest version of `STM32CubeProgrammer`_ + + +Flash an Application to STEVAL-STWINBX1 +------------------------------------------ + +There are two ways to enter DFU mode: + +1. USB-C cable not connected + + While pressing the USER button, connect the USB-C cable to the USB OTG STEVAL-STWINBX1 + port and to your computer. + +2. USB-C cable connected + + While pressing the USER button, press the RESET button and release it. + +With both methods, the board should be forced to enter DFU mode. + +Check that the board is indeed in DFU mode: + +.. code-block:: console + + $ sudo dfu-util -l + dfu-util 0.9 + + Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. + Copyright 2010-2019 Tormod Volden and Stefan Schmidt + This program is Free Software and has ABSOLUTELY NO WARRANTY + Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ + + Found DFU: [0483:df11] ver=0200, devnum=58, cfg=1, intf=0, path="3-1", alt=2, name="@OTP Memory /0x0BFA0000/01*512 e", serial="207136863530" + Found DFU: [0483:df11] ver=0200, devnum=58, cfg=1, intf=0, path="3-1", alt=1, name="@Option Bytes /0x40022040/01*64 e", serial="207136863530" + Found DFU: [0483:df11] ver=0200, devnum=58, cfg=1, intf=0, path="3-1", alt=0, name="@Internal Flash /0x08000000/256*08Kg", serial="207136863530" + +You should see the following confirmation on your Linux host: + +.. code-block:: console + + $ dmesg + usb 3-1: new full-speed USB device number 16 using xhci_hcd + usb 3-1: New USB device found, idVendor=0483, idProduct=df11, bcdDevice= 2.00 + usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + usb 3-1: Product: DFU in FS Mode + usb 3-1: Manufacturer: STMicroelectronics + usb 3-1: SerialNumber: 207136863530 + +.. You can build and flash the provided sample application +.. (:ref:`sensortile_box_pro_sample_sensors`) that reads sensors data and outputs +.. values on the console. + + +.. _STEVAL-STWINBX1 Development kit website: + https://www.st.com/en/evaluation-tools/steval-stwinbx1.html + +.. _STEVAL-STWINBX1 board User Manual: + https://www.st.com/resource/en/user_manual/um2965-getting-started-with-the-stevalstwinbx1-sensortile-wireless-industrial-node-development-kit-stmicroelectronics.pdf + +.. _STM32U585 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32u575-585.html + +.. _STM32U585 reference manual: + https://www.st.com/resource/en/reference_manual/rm0456-stm32u575585-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _DFU-UTIL website: + http://dfu-util.sourceforge.net/ + +.. _AN2606: + http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf + +.. _BlueNRG-M2 datasheet: + https://www.st.com/en/product/BlueNRG-M2 + +.. _st25dv64k datasheet: + https://www.st.com/en/nfc/st25dv64k.html + +.. _stlink-v3mini: + https://www.st.com/en/development-tools/stlink-v3mini.html + +.. _ilps22qs datasheet: + https://www.st.com/en/mems-and-sensors/ilps22qs.html + +.. _stts22hh datasheet: + https://www.st.com/en/mems-and-sensors/stts22h.html + +.. _tsv912 datasheet: + https://www.st.com/en/automotive-analog-and-power/tsv912.html + +.. _ism330dhcx datasheet: + https://www.st.com/en/mems-and-sensors/ism330dhcx.html + +.. _iis3dwb datasheet: + https://www.st.com/en/mems-and-sensors/iis3dwb.html + +.. _iis2dlpc datasheet: + https://www.st.com/en/mems-and-sensors/iis2dlpc.html + +.. _iis2mdc datasheet: + https://www.st.com/en/mems-and-sensors/iis2mdc.html + +.. _iis2iclx datasheet: + https://www.st.com/en/mems-and-sensors/iis2iclx.html + +.. _imp23absu datasheet: + https://www.st.com/en/mems-and-sensors/imp23absu.html + +.. _imp34dt05 datasheet: + https://www.st.com/en/mems-and-sensors/imp34dt05.html diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.dts b/boards/st/steval_stwinbx1/steval_stwinbx1.dts new file mode 100644 index 00000000000000..d84b9fae9cda42 --- /dev/null +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.dts @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + #include + #include + #include + +/ { + model = "STMicroelectronics STEVAL-STWINBX1 Development kit"; + compatible = "st,steval_stwinbx1"; + + chosen { + /* + * By default, Zephyr console and shell are assigned to + * USB CDC/ACM. To enable console and shell over UART, + * uncomment the 2 following lines and set the correct + * config in steval_stwinbx1_defconfig. + */ + /* zephyr,console = &usart2; */ + /* zephyr,shell-uart = &usart2; */ + /* + * To enable console and shell over UART, + * comment the 2 following lines + */ + zephyr,console = &cdc_acm_uart0; + zephyr,shell-uart = &cdc_acm_uart0; + + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&gpioh 12 GPIO_ACTIVE_HIGH>; + label = "LED_1"; + }; + orange_led: led_2 { + gpios = <&gpioh 10 GPIO_ACTIVE_HIGH>; + label = "LED_2"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm5 3 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "LED_1 - PWM5"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioe 0 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led; + led1 = &orange_led; + pwm-led0 = &green_pwm_led; + sw0 = &user_button; + mcuboot-led0 = &green_led; + mcuboot-button0 = &user_button; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref1; + volt-sensor1 = &vbat4; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_msis { + status = "okay"; + msi-range = <4>; + msi-pll-mode; +}; + +&pll1 { + div-m = <1>; + mul-n = <10>; + div-q = <2>; + div-r = <1>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&pll2 { + div-m = <2>; + mul-n = <48>; + div-p = <2>; + div-q = <7>; + div-r = <25>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&pll3 { + div-m = <2>; + mul-n = <48>; + div-p = <2>; + div-q = <25>; + div-r = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll1>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&gpioe { + status = "okay"; + + /* Enable 2.7V Analog LDO */ + ldo-enable-gpios { + gpio-hog; + gpios = <15 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +stm32_lp_tick_source: &lptim1 { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00000800>, + <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; + status = "okay"; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_ph4 &i2c2_sda_pf0>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; + + stts22h@3f { + compatible = "st,stts22h"; + reg = <0x3f>; + int-gpios = <&gpiof 5 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&timers5 { + st,prescaler = <10000>; + status = "okay"; + + pwm5: pwm { + status = "okay"; + pinctrl-0 = <&tim5_ch3_ph12>; + pinctrl-names = "default"; + }; +}; + + +&aes { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +zephyr_udc0: &usbotg_fs { + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; + + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +&adc1 { + pinctrl-0 = <&adc1_in1_pc0>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + vref-mv = <2750>; + status = "okay"; +}; + +&adc4 { + pinctrl-0 = <&adc4_in3_pc2>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + vref-mv = <2750>; + status = "okay"; +}; + +&die_temp { + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&vref1 { + status = "okay"; +}; + +&vbat4 { + status = "okay"; +}; + +&sdmmc1 { + status = "okay"; + pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 + &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 + &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2>; + pinctrl-names = "default"; + cd-gpios = <&gpiog 1 GPIO_ACTIVE_LOW>; + bus-width = <4>; + clk-div = <4>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * Following flash partition is dedicated to the use of steval_stwinbx1 + * with TZEN=0 (so w/o TFM). + * Set the partitions with first MB to make use of the whole Bank1 + */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(416)>; + }; + slot1_partition: partition@78000 { + label = "image-1"; + reg = <0x00078000 DT_SIZE_K(416)>; + }; + scratch_partition: partition@e0000 { + label = "image-scratch"; + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 DT_SIZE_K(64)>; + }; + + }; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.yaml b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml new file mode 100644 index 00000000000000..12715712a0bb84 --- /dev/null +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml @@ -0,0 +1,16 @@ +identifier: steval_stwinbx1 +name: STEVAL STWINBX1 Development kit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 786 +flash: 2048 +supported: + - adc + - counter + - gpio + - pwm + - watchdog +vendor: st diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig b/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig new file mode 100644 index 00000000000000..c432b5184df153 --- /dev/null +++ b/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y +CONFIG_GPIO_HOGS=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# config USB and USB console +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_UART_LINE_CTRL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Comment out following USB config lines when +# switching console to UART +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_VID=0x0483 +CONFIG_USB_DEVICE_PID=0x5740 +CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC STEval-STWinbx1" +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/steval_stwinbx1/support/openocd.cfg b/boards/st/steval_stwinbx1/support/openocd.cfg new file mode 100644 index 00000000000000..31f15356db7158 --- /dev/null +++ b/boards/st/steval_stwinbx1/support/openocd.cfg @@ -0,0 +1,44 @@ +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +set CHIPNAME STM32U585AIIxQ +set BOARDNAME STEVAL-STWINBX1 + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate connect_assert_srst +set CONNECT_UNDER_RESET 1 +set CORE_RESET 0 + +# ACCESS PORT NUMBER +set AP_NUM 0 +# GDB PORT +set GDB_PORT 3333 + +# BCTM CPU variables + +source [find target/stm32u5x.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} From d9c1226a4753482acae99b709e4143a61d38087e Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0799/1389] sensor: convert ADC `depends on` to `select` When a sensor that depends on an ADC is enabled in devicetree, enable the ADC subsystem. ADC is roughly equivalent to a bus for these sensors (the mechanism through which data is transferred), which had the same conversion applied in #48707. The same benefits apply here, namely removing the need for the following pattern in board `.kconfig` files: ``` configdefault ADC default y if SENSOR ``` Signed-off-by: Jordan Yates --- drivers/input/Kconfig.analog_axis | 2 +- drivers/sensor/current_amp/Kconfig | 2 +- drivers/sensor/rpi_pico_temp/Kconfig | 2 +- drivers/sensor/seeed/grove/Kconfig | 6 ++++-- drivers/sensor/st/stm32_vbat/Kconfig | 3 ++- drivers/sensor/st/stm32_vref/Kconfig | 3 ++- drivers/sensor/voltage_divider/Kconfig | 2 +- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/input/Kconfig.analog_axis b/drivers/input/Kconfig.analog_axis index 472b611acea8e2..47f90e9fcb4c51 100644 --- a/drivers/input/Kconfig.analog_axis +++ b/drivers/input/Kconfig.analog_axis @@ -5,8 +5,8 @@ config INPUT_ANALOG_AXIS bool "ADC based analog axis input driver" default y depends on DT_HAS_ANALOG_AXIS_ENABLED - depends on ADC depends on MULTITHREADING + select ADC help ADC based analog axis input driver diff --git a/drivers/sensor/current_amp/Kconfig b/drivers/sensor/current_amp/Kconfig index 62ea9bc0d12807..b167221256da55 100644 --- a/drivers/sensor/current_amp/Kconfig +++ b/drivers/sensor/current_amp/Kconfig @@ -8,6 +8,6 @@ config CURRENT_AMP bool "Current sense amplifier driver" default y depends on DT_HAS_CURRENT_SENSE_AMPLIFIER_ENABLED - depends on ADC + select ADC help Enable current sense amplifier driver. diff --git a/drivers/sensor/rpi_pico_temp/Kconfig b/drivers/sensor/rpi_pico_temp/Kconfig index 9b618984d88b48..33a9b7f9b27293 100644 --- a/drivers/sensor/rpi_pico_temp/Kconfig +++ b/drivers/sensor/rpi_pico_temp/Kconfig @@ -7,7 +7,7 @@ config RPI_PICO_TEMP bool "Raspberry Pi Pico CPU Temperature Sensor" default y depends on DT_HAS_RASPBERRYPI_PICO_TEMP_ENABLED - depends on ADC + select ADC help Enable driver for Raspberry Pi Pico CPU temperature sensor. diff --git a/drivers/sensor/seeed/grove/Kconfig b/drivers/sensor/seeed/grove/Kconfig index f3804f3323fbd0..9563bdd7b3aa63 100644 --- a/drivers/sensor/seeed/grove/Kconfig +++ b/drivers/sensor/seeed/grove/Kconfig @@ -16,7 +16,8 @@ config GROVE_LIGHT_SENSOR bool "The Seeed Grove Light Sensor" default y depends on DT_HAS_SEEED_GROVE_LIGHT_ENABLED - depends on ADC && !MINIMAL_LIBC + depends on !MINIMAL_LIBC + select ADC help Setting this value will enable driver support for the Grove Light Sensor. @@ -25,7 +26,8 @@ config GROVE_TEMPERATURE_SENSOR bool "The Seeed Grove Temperature Sensor" default y depends on DT_HAS_SEEED_GROVE_TEMPERATURE_ENABLED - depends on ADC && !MINIMAL_LIBC + depends on !MINIMAL_LIBC + select ADC help Setting this value will enable driver support for the Grove Temperature Sensor. diff --git a/drivers/sensor/st/stm32_vbat/Kconfig b/drivers/sensor/st/stm32_vbat/Kconfig index 8f1c7e03875ace..2638269224dcca 100644 --- a/drivers/sensor/st/stm32_vbat/Kconfig +++ b/drivers/sensor/st/stm32_vbat/Kconfig @@ -7,6 +7,7 @@ config STM32_VBAT bool "STM32 Vbat Sensor" default y depends on DT_HAS_ST_STM32_VBAT_ENABLED - depends on ADC && (SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X) + depends on SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X + select ADC help Enable driver for STM32 Vbat sensor and then also ADC diff --git a/drivers/sensor/st/stm32_vref/Kconfig b/drivers/sensor/st/stm32_vref/Kconfig index 192cd3fd922e60..3e76dcd4f79d59 100644 --- a/drivers/sensor/st/stm32_vref/Kconfig +++ b/drivers/sensor/st/stm32_vref/Kconfig @@ -7,6 +7,7 @@ config STM32_VREF bool "STM32 VREF Sensor" default y depends on DT_HAS_ST_STM32_VREF_ENABLED - depends on ADC && (SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X) + depends on SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X + select ADC help Enable driver for STM32 Vref sensor. diff --git a/drivers/sensor/voltage_divider/Kconfig b/drivers/sensor/voltage_divider/Kconfig index 19027aa93615e9..b89510c2b72b1a 100644 --- a/drivers/sensor/voltage_divider/Kconfig +++ b/drivers/sensor/voltage_divider/Kconfig @@ -8,6 +8,6 @@ config VOLTAGE_DIVIDER bool "Voltage sensor driver" default y depends on DT_HAS_VOLTAGE_DIVIDER_ENABLED - depends on ADC + select ADC help Enable voltage sensor driver. From 0fe2b6979e6d9c6704913185a95de14df3e0bfd7 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0800/1389] dts: bindings: gpio: remove unused reg property from emul driver The gpio-emul driver does not actually require any reg property, since it is not in the physical memory map of any device. So let's remove that property from the bindings. Signed-off-by: Chris Friedt --- boards/native/native_sim/native_sim.dts | 3 +-- dts/bindings/gpio/zephyr,gpio-emul.yaml | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/boards/native/native_sim/native_sim.dts b/boards/native/native_sim/native_sim.dts index 5ed512dd05e48c..87d6297f7491d3 100644 --- a/boards/native/native_sim/native_sim.dts +++ b/boards/native/native_sim/native_sim.dts @@ -161,10 +161,9 @@ compatible = "zephyr,native-posix-counter"; }; - gpio0: gpio@800 { + gpio0: gpio_emul { status = "okay"; compatible = "zephyr,gpio-emul"; - reg = <0x800 0x4>; rising-edge; falling-edge; high-level; diff --git a/dts/bindings/gpio/zephyr,gpio-emul.yaml b/dts/bindings/gpio/zephyr,gpio-emul.yaml index b1810ef26991cc..fc2b09cd8390e8 100644 --- a/dts/bindings/gpio/zephyr,gpio-emul.yaml +++ b/dts/bindings/gpio/zephyr,gpio-emul.yaml @@ -8,9 +8,6 @@ compatible: "zephyr,gpio-emul" include: [gpio-controller.yaml, base.yaml] properties: - reg: - required: true - rising-edge: description: Enables support for rising edge interrupt detection type: boolean From 7b1bc2fae15f546c10e406705b52b67850a800b0 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0801/1389] kernel: structs: define priq bitmap size via bits per long Since a long is 64-bits on 64-bit architectures, and 32-bits on 32-bit architectures, we can simplify the definition of PRIQ_BITMAP_SIZE by defining it in terms of BITS_PER_LONG. Signed-off-by: Chris Friedt --- include/zephyr/kernel_structs.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/include/zephyr/kernel_structs.h b/include/zephyr/kernel_structs.h index ff8bde4e57162a..baa2046f07c8e0 100644 --- a/include/zephyr/kernel_structs.h +++ b/include/zephyr/kernel_structs.h @@ -33,13 +33,7 @@ #endif #define K_NUM_THREAD_PRIO (CONFIG_NUM_PREEMPT_PRIORITIES + CONFIG_NUM_COOP_PRIORITIES + 1) - -#if defined(CONFIG_64BIT) -#define PRIQ_BITMAP_SIZE (DIV_ROUND_UP(K_NUM_THREAD_PRIO, 8 * sizeof(uint64_t))) -#else -#define PRIQ_BITMAP_SIZE (DIV_ROUND_UP(K_NUM_THREAD_PRIO, 8 * sizeof(uint32_t))) -#endif - +#define PRIQ_BITMAP_SIZE (DIV_ROUND_UP(K_NUM_THREAD_PRIO, BITS_PER_LONG)) #ifdef __cplusplus extern "C" { @@ -127,11 +121,7 @@ struct _priq_rb { */ struct _priq_mq { sys_dlist_t queues[K_NUM_THREAD_PRIO]; -#ifdef CONFIG_64BIT - uint64_t bitmask[PRIQ_BITMAP_SIZE]; -#else - uint32_t bitmask[PRIQ_BITMAP_SIZE]; -#endif + unsigned long bitmask[PRIQ_BITMAP_SIZE]; }; struct _ready_q { From 92bb20ab412d5c90aa7ddd6d7b540c1228601980 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0802/1389] input: gpio_keys: skip change checking when suspended Check if the driver is suspended in gpio_keys_change_deferred(), this avoids a potential situation where a race condition could try and read from a pin that has just been disconnected. Signed-off-by: Fabio Baltieri --- drivers/input/input_gpio_keys.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/input/input_gpio_keys.c b/drivers/input/input_gpio_keys.c index 7fca24a55ed427..fa27ca5bd64407 100644 --- a/drivers/input/input_gpio_keys.c +++ b/drivers/input/input_gpio_keys.c @@ -106,6 +106,14 @@ static __maybe_unused void gpio_keys_change_deferred(struct k_work *work) const struct gpio_keys_config *cfg = dev->config; int key_index = pin_data - (struct gpio_keys_pin_data *)cfg->pin_data; +#ifdef CONFIG_PM_DEVICE + struct gpio_keys_data *data = dev->data; + + if (atomic_get(&data->suspended) == 1) { + return; + } +#endif + gpio_keys_poll_pin(dev, key_index); } From cbd5a64aa782de3d27dd3cfffd0eacc565c66d02 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0803/1389] twister: Fix path to binary location for unit_testing board PR #72100 broke execution of unit type tests. This commit fixes it by bringing back the "old" logic for selecting a binary path for unit type tests. Signed-off-by: Maciej Perkowski --- scripts/pylib/twister/twisterlib/handlers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index b8007849eb55b6..16cec58be2f8f9 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -235,6 +235,8 @@ def _create_command(self, robot_test): command = [self.generator_cmd, "run_renode_test"] elif self.call_make_run: command = [self.generator_cmd, "run"] + elif self.instance.testsuite.type == "unit": + command = [self.binary] else: binary = os.path.join(self.get_default_domain_build_dir(), "zephyr", "zephyr.exe") command = [binary] From 4dc309e3b8c9a74ebfcae154d6f23c92b095de5c Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0804/1389] broadcom/bcm2712: Fix UART DT Its UART driver needs the interrupt-names property, let's add it. Signed-off-by: Alberto Escolar Piedras --- dts/arm64/broadcom/bcm2712.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/arm64/broadcom/bcm2712.dtsi b/dts/arm64/broadcom/bcm2712.dtsi index a31e8b21d14bd0..9249cb3622c0b5 100644 --- a/dts/arm64/broadcom/bcm2712.dtsi +++ b/dts/arm64/broadcom/bcm2712.dtsi @@ -73,6 +73,7 @@ reg = <0x10 0x7d001000 0x200>; interrupts = ; + interrupt-names = "irq_121"; clocks = <&clk_uart>; status = "disabled"; }; From bfd4027224d07018d111a2eb9234d218c5443c81 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0805/1389] boards: nrf54h20dk: Drop shared_ram20_region's compatible Access to this region should no longer be requested via UICR, because it will be statically reserved by secure domain firmware. Signed-off-by: Grzegorz Swiderski --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 5ea59e94697135..f67ddfb80bf48e 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -70,11 +70,7 @@ }; shared_ram20_region: memory@2f88f000 { - compatible = "nordic,owned-memory"; reg = <0x2f88f000 DT_SIZE_K(4)>; - status = "okay"; - perm-read; - perm-write; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x2f88f000 0x1000>; From 1e8ab3429a2212e62f64ce33a199232f80052512 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0806/1389] ARC: nSIM: hs5x: align sys clock with other SMP nSIM configs Align SYS_CLOCK_HW_CYCLES_PER_SEC with other SMP nSIM configurations and set it to 1000000. This significantly reduce verification time on HS5x platforms. Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- soc/snps/nsim/Kconfig.defconfig.hs5x_smp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/snps/nsim/Kconfig.defconfig.hs5x_smp b/soc/snps/nsim/Kconfig.defconfig.hs5x_smp index 9d7ac1d7f4cfd3..69b0b578afa08d 100644 --- a/soc/snps/nsim/Kconfig.defconfig.hs5x_smp +++ b/soc/snps/nsim/Kconfig.defconfig.hs5x_smp @@ -15,7 +15,7 @@ config NUM_IRQS default 30 config SYS_CLOCK_HW_CYCLES_PER_SEC - default 5000000 + default 1000000 config CACHE_MANAGEMENT default y From 1b306863c7cca254e6a98fbf7222b63fc2d57ee4 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0807/1389] Bluetooth: Audio: Shell: Fix build errors for USB=n When CONFIG_USB_DEVICE_STACK=n then the sine wave generator was enabled, which caused build errors. This commit fixes those errors and also adds the nRF5340 as a build target for the USB tests. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/shell/bap.c | 14 ++++++-------- .../boards/nrf5340_audio_dk_nrf5340_cpuapp.conf | 3 +++ .../shell/boards/nrf5340dk_nrf5340_cpuapp.conf | 10 +++++++++- tests/bluetooth/shell/testcase.yaml | 14 ++++++++++++-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index 0cc7d9b3d79acc..4ffa9539940323 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -3778,7 +3778,7 @@ static void start_sine_stream_cb(struct shell_stream *sh_stream, void *user_data if (err != 0) { shell_error(sh, "Failed to init LC3 %d for stream %p", err, bap_stream); - return -ENOEXEC; + return; } sh_stream->tx.active = true; @@ -3791,7 +3791,6 @@ static void start_sine_stream_cb(struct shell_stream *sh_stream, void *user_data static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) { bool start_all = false; - int err; if (argc > 1) { if (strcmp(argv[1], "all") == 0) { @@ -3804,11 +3803,11 @@ static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) } if (start_all) { - bap_foreach_stream(start_sine_stream_cb, sh); + bap_foreach_stream(start_sine_stream_cb, (void *)sh); } else { struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream); - start_sine_stream_cb(sh_stream, sh); + start_sine_stream_cb(sh_stream, (void *)sh); } return 0; @@ -3817,8 +3816,7 @@ static int cmd_start_sine(const struct shell *sh, size_t argc, char *argv[]) static void stop_sine_stream_cb(struct shell_stream *sh_stream, void *user_data) { if (sh_stream->is_tx) { - struct bt_bap_stream *bap_stream = - bap_stream_from_shell_stream(&unicast_streams[i]); + struct bt_bap_stream *bap_stream = bap_stream_from_shell_stream(sh_stream); const struct shell *sh = user_data; shell_print(sh, "Stopped transmitting on stream %p", bap_stream); @@ -3842,11 +3840,11 @@ static int cmd_stop_sine(const struct shell *sh, size_t argc, char *argv[]) } if (stop_all) { - bap_foreach_stream(stop_sine_stream_cb, sh); + bap_foreach_stream(stop_sine_stream_cb, (void *)sh); } else { struct shell_stream *sh_stream = shell_stream_from_bap_stream(default_stream); - stop_sine_stream_cb(sh_stream, sh) + stop_sine_stream_cb(sh_stream, (void *)sh); } return 0; diff --git a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index 849817b36acb27..607737479e2e5b 100644 --- a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -1,10 +1,13 @@ # For LC3 the following configs are needed CONFIG_FPU=y CONFIG_LIBLC3=y + +# For USB audio the following configs are needed CONFIG_RING_BUFFER=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_AUDIO=y CONFIG_USB_DEVICE_PRODUCT="Zephyr Shell USB" + # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=5120 diff --git a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf index 8d48d5e1c20721..607737479e2e5b 100644 --- a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -1,6 +1,14 @@ # For LC3 the following configs are needed CONFIG_FPU=y CONFIG_LIBLC3=y + +# For USB audio the following configs are needed +CONFIG_RING_BUFFER=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_AUDIO=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr Shell USB" + # The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence # inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=5120 +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/tests/bluetooth/shell/testcase.yaml b/tests/bluetooth/shell/testcase.yaml index ef1a0b39b22484..3ddde520a861fe 100644 --- a/tests/bluetooth/shell/testcase.yaml +++ b/tests/bluetooth/shell/testcase.yaml @@ -353,14 +353,24 @@ tests: bluetooth.audio_shell.no_lc3: extra_args: CONF_FILE="audio.conf" build_only: true - platform_allow: native_posix + platform_allow: + - nrf5340dk/nrf5340/cpuapp + - nrf5340_audio_dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + - nrf5340_audio_dk/nrf5340/cpuapp extra_configs: - CONFIG_FPU=n - CONFIG_LIBLC3=n bluetooth.audio_shell.no_usb: extra_args: CONF_FILE="audio.conf" build_only: true - platform_allow: native_posix + platform_allow: + - nrf5340dk/nrf5340/cpuapp + - nrf5340_audio_dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + - nrf5340_audio_dk/nrf5340/cpuapp extra_configs: - CONFIG_RING_BUFFER=n - CONFIG_USB_DEVICE_STACK=n From 7d5c4eb6b75c4eef03cfa8dd952b2951591fe06a Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0808/1389] Bluetooth: Audio: Shell: Remove increased workqueue stack size The LC3 in the shell is now done in separate threads with their own stacks. Signed-off-by: Emil Gydesen --- tests/bluetooth/shell/boards/native_posix.conf | 3 --- tests/bluetooth/shell/boards/native_sim.conf | 3 --- .../shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf | 4 +--- tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf | 4 +--- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/tests/bluetooth/shell/boards/native_posix.conf b/tests/bluetooth/shell/boards/native_posix.conf index a2ab2f4e87a5ff..80cbf6267972df 100644 --- a/tests/bluetooth/shell/boards/native_posix.conf +++ b/tests/bluetooth/shell/boards/native_posix.conf @@ -11,6 +11,3 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=500 # For LC3 the following configs are needed CONFIG_FPU=y CONFIG_LIBLC3=y -# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence -# inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/bluetooth/shell/boards/native_sim.conf b/tests/bluetooth/shell/boards/native_sim.conf index a2ab2f4e87a5ff..80cbf6267972df 100644 --- a/tests/bluetooth/shell/boards/native_sim.conf +++ b/tests/bluetooth/shell/boards/native_sim.conf @@ -11,6 +11,3 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=500 # For LC3 the following configs are needed CONFIG_FPU=y CONFIG_LIBLC3=y -# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence -# inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index 607737479e2e5b..68e0a8a7e50f8e 100644 --- a/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -8,7 +8,5 @@ CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_AUDIO=y CONFIG_USB_DEVICE_PRODUCT="Zephyr Shell USB" -# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence -# inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=5120 +# Enable encryption in the host CONFIG_BT_TINYCRYPT_ECC=y diff --git a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf index 607737479e2e5b..68e0a8a7e50f8e 100644 --- a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -8,7 +8,5 @@ CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_AUDIO=y CONFIG_USB_DEVICE_PRODUCT="Zephyr Shell USB" -# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence -# inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=5120 +# Enable encryption in the host CONFIG_BT_TINYCRYPT_ECC=y From 4bebd38b49de6bccbcb0e2232cb29a2a63f98265 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0809/1389] drivers: flash: stm32 flash driver has a Kconfig STM32_MEMMAP This CONFIG_STM32_MEMMAP is for enabling the MemoryMapped mode on external octo or quad spi memory. In this case, the flash_stm32_read is done in mem map mode the flash_stm32_erase is not available. Signed-off-by: Francois Ramu --- drivers/flash/Kconfig.stm32 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 4fd5bd4a3e2fe5..72481c5ae6ed9c 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -72,4 +72,11 @@ config FLASH_STM32_BLOCK_REGISTERS registers improves system security, because flash content (or protection settings) can't be changed even when exploit was found. +config STM32_MEMMAP + bool "NOR Flash in MemoryMapped for XiP" + depends on XIP + help + This option enables the XIP mode for the external NOR flash + mounted on STM32 boards. + endif # SOC_FLASH_STM32 From 0cc828abf3d1ee567e9110d4f6a530fa8cac8918 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:39:09 +0200 Subject: [PATCH 0810/1389] drivers/flash: enable memory-mapped mode for STM32 QSPI This puts the QSPI peripheral into memory-mapped mode when CONFIG_STM32_MEMMAP is set. Writes and erase put it back into indirect write mode. Signed-off-by: Armin Brauns --- drivers/flash/flash_stm32_qspi.c | 123 +++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index 8421d71f16ee73..adec32e8e4e6fe 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -385,6 +387,66 @@ static bool qspi_address_is_valid(const struct device *dev, off_t addr, return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size); } +#ifdef CONFIG_STM32_MEMMAP +/* Must be called inside qspi_lock_thread(). */ +static int stm32_qspi_set_memory_mapped(const struct device *dev) +{ + int ret; + HAL_StatusTypeDef hal_ret; + struct flash_stm32_qspi_data *dev_data = dev->data; + + QSPI_CommandTypeDef cmd = { + .Instruction = SPI_NOR_CMD_READ, + .Address = 0, + .InstructionMode = QSPI_INSTRUCTION_1_LINE, + .AddressMode = QSPI_ADDRESS_1_LINE, + .DataMode = QSPI_DATA_1_LINE, + }; + + qspi_set_address_size(dev, &cmd); + if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO)) { + ret = qspi_prepare_quad_read(dev, &cmd); + if (ret < 0) { + return ret; + } + } + + QSPI_MemoryMappedTypeDef mem_mapped = { + .TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE, + }; + + hal_ret = HAL_QSPI_MemoryMapped(&dev_data->hqspi, &cmd, &mem_mapped); + if (hal_ret != 0) { + LOG_ERR("%d: Failed to enable memory mapped", hal_ret); + return -EIO; + } + + LOG_DBG("MemoryMap mode enabled"); + return 0; +} + +static bool stm32_qspi_is_memory_mapped(const struct device *dev) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + + return READ_BIT(dev_data->hqspi.Instance->CCR, QUADSPI_CCR_FMODE) == QUADSPI_CCR_FMODE; +} + +static int stm32_qspi_abort(const struct device *dev) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_QSPI_Abort(&dev_data->hqspi); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: QSPI abort failed", hal_ret); + return -EIO; + } + + return 0; +} +#endif + static int flash_stm32_qspi_read(const struct device *dev, off_t addr, void *data, size_t size) { @@ -401,6 +463,27 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + qspi_lock_thread(dev); + + /* Do reads through memory-mapping instead of indirect */ + if (!stm32_qspi_is_memory_mapped(dev)) { + ret = stm32_qspi_set_memory_mapped(dev); + if (ret != 0) { + LOG_ERR("READ: failed to set memory mapped"); + goto end; + } + } + + __ASSERT_NO_MSG(stm32_qspi_is_memory_mapped(dev)); + + uintptr_t mmap_addr = STM32_QSPI_BASE_ADDRESS + addr; + + LOG_DBG("Memory-mapped read from 0x%08lx, len %zu", mmap_addr, size); + memcpy(data, (void *)mmap_addr, size); + ret = 0; + goto end; +#else QSPI_CommandTypeDef cmd = { .Instruction = SPI_NOR_CMD_READ, .Address = addr, @@ -420,7 +503,10 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr, qspi_lock_thread(dev); ret = qspi_read_access(dev, &cmd, data, size); + goto end; +#endif +end: qspi_unlock_thread(dev); return ret; @@ -482,6 +568,17 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr, qspi_lock_thread(dev); +#ifdef CONFIG_STM32_MEMMAP + if (stm32_qspi_is_memory_mapped(dev)) { + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_qspi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before write"); + goto end; + } + } +#endif + while (size > 0) { size_t to_write = size; @@ -517,7 +614,9 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr, break; } } + goto end; +end: qspi_unlock_thread(dev); return ret; @@ -555,6 +654,17 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr, qspi_set_address_size(dev, &cmd_erase); qspi_lock_thread(dev); +#ifdef CONFIG_STM32_MEMMAP + if (stm32_qspi_is_memory_mapped(dev)) { + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_qspi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before erase"); + goto end; + } + } +#endif + while ((size > 0) && (ret == 0)) { cmd_erase.Address = addr; qspi_send_cmd(dev, &cmd_write_en); @@ -596,7 +706,9 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr, } qspi_wait_until_ready(dev); } + goto end; +end: qspi_unlock_thread(dev); return ret; @@ -1372,9 +1484,20 @@ static int flash_stm32_qspi_init(const struct device *dev) } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ +#ifdef CONFIG_STM32_MEMMAP + ret = stm32_qspi_set_memory_mapped(dev); + if (ret != 0) { + LOG_ERR("Failed to enable memory-mapped mode: %d", ret); + return ret; + } + LOG_INF("Memory-mapped NOR quad-flash at 0x%lx (0x%x bytes)", + (long)(STM32_QSPI_BASE_ADDRESS), + dev_cfg->flash_size); +#else LOG_INF("NOR quad-flash at 0x%lx (0x%x bytes)", (long)(STM32_QSPI_BASE_ADDRESS), dev_cfg->flash_size); +#endif return 0; } From e5e272821eec3163c6e7f6343b29085501d5cc5e Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0811/1389] boards/stm32f769i_disco: fix NOR flash max frequency According to the datasheet, fRSCLK (Clock Frequency for READ instructions) is 66MHz; it doesn't mention 72MHz anywhere. Signed-off-by: Armin Brauns --- boards/st/stm32f769i_disco/stm32f769i_disco.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/st/stm32f769i_disco/stm32f769i_disco.dts b/boards/st/stm32f769i_disco/stm32f769i_disco.dts index 22b981b50225a1..1d81dbf805a7e0 100644 --- a/boards/st/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/st/stm32f769i_disco/stm32f769i_disco.dts @@ -180,7 +180,7 @@ arduino_serial: &usart6 {}; mx25l51245g: qspi-nor-flash@90000000 { compatible = "st,stm32-qspi-nor"; reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ - qspi-max-frequency = <72000000>; + qspi-max-frequency = ; status = "okay"; partitions { From d1784c66492af050cbd97306664d29186d7b08d5 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0812/1389] boards/stm32f769i_disco: use openocd "reset init" instead of "reset halt" The init script is required for QSPI flash setup. Signed-off-by: Armin Brauns --- boards/st/stm32f769i_disco/support/openocd.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/st/stm32f769i_disco/support/openocd.cfg b/boards/st/stm32f769i_disco/support/openocd.cfg index 1c964a0e643845..8896666bc6d22a 100644 --- a/boards/st/stm32f769i_disco/support/openocd.cfg +++ b/boards/st/stm32f769i_disco/support/openocd.cfg @@ -2,7 +2,7 @@ source [find board/stm32f769i-disco.cfg] $_TARGETNAME configure -event gdb-attach { echo "Debugger attaching: halting execution" - reset halt + reset init gdb_breakpoint_override hard } From 8e49568426ee0042f70f6578997e9d6055b94185 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0813/1389] boards/stm32f769i_disco: add accessible memory region for QSPI flash By default, the QSPI region is marked as EXTMEM and inaccessible (see #57467), mark the first 64MB as IO on stm32f769i_disco. Signed-off-by: Armin Brauns --- boards/st/stm32f769i_disco/stm32f769i_disco.dts | 7 +++++++ dts/arm/st/f7/stm32f7.dtsi | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/boards/st/stm32f769i_disco/stm32f769i_disco.dts b/boards/st/stm32f769i_disco/stm32f769i_disco.dts index 1d81dbf805a7e0..03ff90c729baaf 100644 --- a/boards/st/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/st/stm32f769i_disco/stm32f769i_disco.dts @@ -79,6 +79,13 @@ sw0 = &user_button; spi-flash0 = &mx25l51245g; }; + + quadspi_memory_avail: memory-avail@90000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x90000000 DT_SIZE_M(64)>; + zephyr,memory-region = "QSPI_AVAIL"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; }; &clk_hse { diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index ea80dbe86afc5d..439bc560a7d5eb 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -45,10 +45,10 @@ }; }; - quadspi_memory: memory@90000000 { + quadspi_memory: memory-placeholder@90000000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x90000000 DT_SIZE_M(256)>; - zephyr,memory-region = "QSPI"; + zephyr,memory-region = "QSPI_PLACEHOLDER"; zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; }; From 6c57afcdcf762bcaf0d2194a88f983bfad336736 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0814/1389] samples: code_relocation_nocopy: add stm32f769i_disco board This board has memory-mapped QSPI flash. Signed-off-by: Armin Brauns --- .../code_relocation_nocopy/README.rst | 25 +++++++++++++------ .../boards/stm32f769i_disco.conf | 2 ++ .../linker_arm_nocopy.ld | 7 ++++++ .../code_relocation_nocopy/sample.yaml | 1 + 4 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf diff --git a/samples/application_development/code_relocation_nocopy/README.rst b/samples/application_development/code_relocation_nocopy/README.rst index f8ac178a7e94df..2e0f49f520f838 100644 --- a/samples/application_development/code_relocation_nocopy/README.rst +++ b/samples/application_development/code_relocation_nocopy/README.rst @@ -10,18 +10,14 @@ using a custom linker script. Differently from the code relocation sample, this sample is relocating the content of the ext_code.c file to a different FLASH section and the code is XIP -directly from there without the need to copy / relocate the code. +directly from there without the need to copy / relocate the code. All other code +(e.g. main(), Zephyr kernel) stays in the internal flash. nRF5340 DK platform instructions ******************************** The nRF5340 DK has a 64 Mb external flash memory supporting Quad SPI. It is -possible to do XIP from the external flash memory. - -The external flash memory is mapped to 0x10000000. - -In this sample we relocate some of the code to the external flash memory with -the remaining Zephyr kernel in the internal flash. +mapped to 0x10000000. To build and flash the application (including the external memory part): @@ -31,7 +27,20 @@ To build and flash the application (including the external memory part): :goals: build flash :compact: -Execution output: +STM32F769I-Discovery platform instructions +****************************************** + +The stm32f769i_disco has 64MB of external flash attached via QSPI. It is mapped +to 0x90000000. + +.. zephyr-app-commands:: + :zephyr-app: samples/application_development/code_relocation_nocopy + :board: stm32f769i_disco + :goals: build flash + :compact: + +Execution output +**************** .. code-block:: console diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf b/samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf new file mode 100644 index 00000000000000..eac2504a7850e5 --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld b/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld index 7ead7f6bae4831..4bf540a7211002 100644 --- a/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld +++ b/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld @@ -26,6 +26,13 @@ #define EXTFLASH_SIZE DT_PROP_OR(EXTFLASH_NODE, size_in_bytes, \ DT_PROP(EXTFLASH_NODE, size) / 8) +#elif defined(CONFIG_STM32_MEMMAP) && DT_NODE_EXISTS(DT_INST(0, st_stm32_qspi_nor)) +/* On stm32 QSPI, external flash is mapped in XIP region at address given by the reg property. */ + +#define EXTFLASH_NODE DT_INST(0, st_stm32_qspi_nor) +#define EXTFLASH_ADDR DT_REG_ADDR(DT_INST(0, st_stm32_qspi_nor)) +#define EXTFLASH_SIZE DT_REG_ADDR_BY_IDX(DT_INST(0, st_stm32_qspi_nor), 1) + #else /* diff --git a/samples/application_development/code_relocation_nocopy/sample.yaml b/samples/application_development/code_relocation_nocopy/sample.yaml index b9415221e24680..a583ea3b44f0fa 100644 --- a/samples/application_development/code_relocation_nocopy/sample.yaml +++ b/samples/application_development/code_relocation_nocopy/sample.yaml @@ -6,6 +6,7 @@ tests: platform_allow: - qemu_cortex_m3 - nrf5340dk/nrf5340/cpuapp + - stm32f769i_disco integration_platforms: - qemu_cortex_m3 tags: linker From c628e2fdaa01ddb28f0217a572a99934de3193b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20LOCHE=20-=20MAKEEN=20Energy?= Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0815/1389] arch: arm: rom_start relocation configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to support Linux rproc loading, some SOCs require the boot-vector and irq-vectors to be placed into a defined memory area for the mcu to boot. This is necessary for NXP's IMX SOCs for instance but can be leveraged by other SOCs that have multiple zephyr,flash choices. Signed-off-by: Jérémy LOCHE - MAKEEN Energy --- arch/arm/Kconfig | 65 +++++++++++++++++++ .../arch/arm/cortex_m/scripts/linker.ld | 13 +++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3f5f3075777fc8..bf68ec6faae69b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -34,6 +34,71 @@ config ARM_CUSTOM_INTERRUPT_CONTROLLER is assumed that the custom interrupt control interface implementation assumes responsibility for handling the NVIC. +config ROMSTART_RELOCATION_ROM + bool + default n + help + Relocates the rom_start region containing the boot-vector data and + irq vectors to the region specified by configurations: + ROMSTART_REGION_ADDRESS and ROMSTART_REGION_SIZE + + This is useful for the Linux Remoteproc framework that uses the elf-loader + such that it is able to load the correct boot-vector (contained in rom_start) + into the correct memory location independent of the chosen zephyr,flash + ROM region. + + Most SOCs include an alias for the boot-vector at address 0x00000000 + so a default which might be supported by the corresponding Linux rproc driver. + If it is not, additionnal options allows to specify the addresses. + + In general this option should be chosen if the zephyr,flash chosen node + is not placed into the boot-vector memory area. + + While this aims at generating a correct zephyr.elf file, it has the side + effect of enlarging the bin file. If the zephyr.bin file is used to boot the + secondary core, this option should be disabled. + + Example: + on IMX7D, the chosen zephyr,flash can be OCRAM/OCRAM_S/TCM/DDR memories + for code location. But the boot-vector must be placed into OCRAM_S for the + CORTEX-M to boot (alias 0, real 0x00180000/32K available). + +if ROMSTART_RELOCATION_ROM + + config ROMSTART_REGION_ADDRESS + hex + default 0x00000000 + help + Start address of the rom_start region. + This setting can be derived from a DT node reg property or specified directly. + + A default value of 0x00000000 might work in most cases as SOCs have an alias + to the right memory region of the boot-vector. + + Examples: + -IMX7D the boot-vector is OCRAM_S (0x00180000, aliased at 0x0). + -IMX6SX the boot-vector is TCML (0x007F8000, aliased at 0x0). + -IMX8MQ the boot-vector is TCML (0x007E0000, aliased at 0x0). + -IMX8MN the boot-vector is ITCM (0x007E0000, aliased at 0x0). + + Example of DT definition: + $(dt_nodelabel_reg_addr_hex,ocram_s_sys) + + config ROMSTART_REGION_SIZE + hex + default 1 + help + Size of the rom_start region in KB. + + Default is 1KB which is enough to store the boot and irq vectors. + + This setting can be derived from a DT node reg property or specified directly. + + Example for IMX7D that needs the boot-vector into OCRAM_S (0x00180000): + $(dt_nodelabel_reg_size_hex,ocram_s_sys,0,K) + +endif + config CODE_DATA_RELOCATION_SRAM bool "Relocate code/data sections to SRAM" depends on CPU_CORTEX_M diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 6d5ba15ee6e825..88598cf5790ebd 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -26,6 +26,14 @@ #endif #define RAMABLE_REGION RAM +/* Region of the irq vectors and boot-vector SP/PC */ +#if defined(CONFIG_ROMSTART_RELOCATION_ROM) +#define ROMSTART_ADDR CONFIG_ROMSTART_REGION_ADDRESS +#define ROMSTART_SIZE (CONFIG_ROMSTART_REGION_SIZE * 1K) +#else +#define ROMSTART_REGION ROMABLE_REGION +#endif + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else @@ -85,6 +93,9 @@ _region_min_align = 4; MEMORY { +#if defined(CONFIG_ROMSTART_RELOCATION_ROM) + ROMSTART_REGION (rx) : ORIGIN = ROMSTART_ADDR, LENGTH = ROMSTART_SIZE +#endif FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE RAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE #if defined(CONFIG_LINKER_DEVNULL_MEMORY) @@ -129,7 +140,7 @@ SECTIONS */ #include - } GROUP_LINK_IN(ROMABLE_REGION) + } GROUP_LINK_IN(ROMSTART_REGION) #ifdef CONFIG_CODE_DATA_RELOCATION From ea5f2b455ea4e373e0ea61732713722f538db12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20LOCHE=20-=20MAKEEN=20Energy?= Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0816/1389] nxp: imx7d-6sx: add rom_start relocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the Kconfig options and use the aliased addresses for the bootcode regions of the IMX7D and IMX6SX SOCs to allow the Linux rproc framework to load the irq-vectors into the correct memory areas. Activating this option might enlarge the bin file if the zephyr,flash and rom_start chosen region addresses are not matching. It is up to the user to enable this feature based on code location choices (OCRAM, DDR, TCM...). Signed-off-by: Jérémy LOCHE - MAKEEN Energy --- dts/arm/nxp/nxp_imx6sx_m4.dtsi | 5 +++-- dts/arm/nxp/nxp_imx7d_m4.dtsi | 5 +++-- soc/nxp/imx/imx6sx/Kconfig.defconfig.mcimx6x_m4 | 14 ++++++++++++++ soc/nxp/imx/imx7d/Kconfig.defconfig.mcimx7d_m4 | 13 +++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/dts/arm/nxp/nxp_imx6sx_m4.dtsi b/dts/arm/nxp/nxp_imx6sx_m4.dtsi index 4a6d606c25374d..ce34a247b80e08 100644 --- a/dts/arm/nxp/nxp_imx6sx_m4.dtsi +++ b/dts/arm/nxp/nxp_imx6sx_m4.dtsi @@ -29,9 +29,10 @@ }; }; - tcml:memory@1fff8000 { + /* TCML 0x1fff8000 is aliased at 0 */ + tcml:memory@0 { compatible = "nxp,imx-itcm"; - reg = <0x1fff8000 DT_SIZE_K(32)>; + reg = <0x00000000 DT_SIZE_K(32)>; }; tcmu:memory@20000000 { diff --git a/dts/arm/nxp/nxp_imx7d_m4.dtsi b/dts/arm/nxp/nxp_imx7d_m4.dtsi index 9b7ed2aed5acc7..b127c8eda4f5b4 100644 --- a/dts/arm/nxp/nxp_imx7d_m4.dtsi +++ b/dts/arm/nxp/nxp_imx7d_m4.dtsi @@ -56,9 +56,10 @@ reg = <0x20200000 DT_SIZE_K(128)>; }; - ocram_s_code: code@20180000 { + /* OCRAM_S 0x20180000 is aliased at 0 */ + ocram_s_code: code@0 { compatible = "nxp,imx-code-bus"; - reg = <0x20180000 DT_SIZE_K(32)>; + reg = <0x00000000 DT_SIZE_K(32)>; }; ocram_s_sys: memory@180000 { diff --git a/soc/nxp/imx/imx6sx/Kconfig.defconfig.mcimx6x_m4 b/soc/nxp/imx/imx6sx/Kconfig.defconfig.mcimx6x_m4 index 9a925ade2f6a62..73f11971d6c8fe 100644 --- a/soc/nxp/imx/imx6sx/Kconfig.defconfig.mcimx6x_m4 +++ b/soc/nxp/imx/imx6sx/Kconfig.defconfig.mcimx6x_m4 @@ -8,4 +8,18 @@ if SOC_MCIMX6X_M4 config FPU default y + +#-By default ROM_START is relocated to address 0 in a 1K region, allowing imx_rproc +# to translate it to TCM_L address +#-Select the relocation if the chosen flash is not the TCML +#-Disable this option if you use the bin format as this choice will enlarge it. +# This is due to relocation of the irq-vectors in a different memory region than +# the chosen zephyr,flash and all the address span in between +# will be filled in the bin file. +config ROMSTART_RELOCATION_ROM + default n + +config ROMSTART_REGION_ADDRESS + default $(dt_nodelabel_reg_addr_hex,tcml) + endif # SOC_MCIMX6X_M4 diff --git a/soc/nxp/imx/imx7d/Kconfig.defconfig.mcimx7d_m4 b/soc/nxp/imx/imx7d/Kconfig.defconfig.mcimx7d_m4 index 2e9d5e71d9d9be..041da088770cc2 100644 --- a/soc/nxp/imx/imx7d/Kconfig.defconfig.mcimx7d_m4 +++ b/soc/nxp/imx/imx7d/Kconfig.defconfig.mcimx7d_m4 @@ -11,4 +11,17 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC config GPIO default y +#-By default ROM_START is relocated to address 0 in a 1K region, allowing imx_rproc +# to translate it to OCRAM_S address +#-Select the relocation if the chosen flash is not the OCRAM_S +#-Disable this option if you use the bin format as this choice will enlarge it. +# This is due to relocation of the irq-vectors in a different memory region than +# the chosen zephyr,flash and all the address span in between +# will be filled in the bin file. +config ROMSTART_RELOCATION_ROM + default n + +config ROMSTART_REGION_ADDRESS + default $(dt_nodelabel_reg_addr_hex,ocram_s_code) + endif # SOC_MCIMX7D_M4 From e93ff8e141eb036c5a3f22985ed45a7ff6b46f1d Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0817/1389] dts: bindings: Move zephyr,memory-region property definition Move it to a common file named `zephyr,memory-common.yaml`, which replaces `zephyr,memory-attr.yaml` and takes its contents as well. This is so that another binding, e.g., `vnd,memory-region`, can support being combined with the `zephyr,memory-region` binding like so: node@deadbeef { compatible = "vnd,memory-region", "zephyr,memory-region"; zephyr,memory-region = "NAME"; ... }; To allow this, edtlib would require `vnd,memory-region` to include the property definitions from this new common file. The same can't be done by including `zephyr,memory-region.yaml` directly because that file marks the property in question as always required, and it shouldn't be required whenever the `vnd,memory-region` compatible is used on its own. Signed-off-by: Grzegorz Swiderski --- ...{zephyr,memory-attr.yaml => zephyr,memory-common.yaml} | 8 ++++++++ dts/bindings/base/zephyr,memory-region.yaml | 8 +------- dts/bindings/test/vnd,memory-attr.yaml | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) rename dts/bindings/base/{zephyr,memory-attr.yaml => zephyr,memory-common.yaml} (67%) diff --git a/dts/bindings/base/zephyr,memory-attr.yaml b/dts/bindings/base/zephyr,memory-common.yaml similarity index 67% rename from dts/bindings/base/zephyr,memory-attr.yaml rename to dts/bindings/base/zephyr,memory-common.yaml index 1a5611b5258e48..f2ccbdb3c412ce 100644 --- a/dts/bindings/base/zephyr,memory-attr.yaml +++ b/dts/bindings/base/zephyr,memory-common.yaml @@ -4,6 +4,14 @@ include: [base.yaml] properties: + zephyr,memory-region: + type: string + description: | + Signify that this node should result in a dedicated linker script + memory region in the final executable. The region address and size + is taken from the property, while the name is the value of + this property. + zephyr,memory-region-mpu: type: string deprecated: true diff --git a/dts/bindings/base/zephyr,memory-region.yaml b/dts/bindings/base/zephyr,memory-region.yaml index 60308af7173a4e..1d9486de8b3eef 100644 --- a/dts/bindings/base/zephyr,memory-region.yaml +++ b/dts/bindings/base/zephyr,memory-region.yaml @@ -5,14 +5,8 @@ description: Compatible for devices resulting in linker memory regions compatible: "zephyr,memory-region" -include: [base.yaml, "zephyr,memory-attr.yaml"] +include: [base.yaml, "zephyr,memory-common.yaml"] properties: zephyr,memory-region: - type: string required: true - description: | - Signify that this node should result in a dedicated linker script - memory region in the final executable. The region address and size - is taken from the property, while the name is the value of - this property. diff --git a/dts/bindings/test/vnd,memory-attr.yaml b/dts/bindings/test/vnd,memory-attr.yaml index 0303d255c54724..8696279859db1d 100644 --- a/dts/bindings/test/vnd,memory-attr.yaml +++ b/dts/bindings/test/vnd,memory-attr.yaml @@ -5,4 +5,4 @@ description: Test memory and memory attributes compatible: "vnd,memory-attr" -include: [base.yaml, "zephyr,memory-attr.yaml"] +include: [base.yaml, "zephyr,memory-common.yaml"] From f0645c0591bb3f91e071cb25729fb94aaf0a460b Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0818/1389] soc: Add SOC_COMPATIBLE_NRF54L* options In preparation for simulated nRF54L targets, let's add kconfig options aking to the ones we have for the nRF52 and 53 devices. Signed-off-by: Alberto Escolar Piedras --- soc/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/soc/Kconfig b/soc/Kconfig index 0063021c3e3c80..cd3b17f28affe2 100644 --- a/soc/Kconfig +++ b/soc/Kconfig @@ -36,6 +36,9 @@ config SOC_COMPATIBLE_NRF52X config SOC_COMPATIBLE_NRF53X bool +config SOC_COMPATIBLE_NRF54LX + bool + config SOC_COMPATIBLE_NRF52833 bool @@ -45,6 +48,12 @@ config SOC_COMPATIBLE_NRF5340_CPUNET config SOC_COMPATIBLE_NRF5340_CPUAPP bool +config SOC_COMPATIBLE_NRF54L15 + bool + +config SOC_COMPATIBLE_NRF54L15_CPUAPP + bool + config SOC_DEPRECATED_RELEASE string help From 74c0a59af265ead8017c76d2cee77e52b9165ca3 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0819/1389] modules hal_nordic: Handle appropiately new kconfig options The new kconfig options intend to represent a final nRF54L product, let's handle them appropriately. Signed-off-by: Alberto Escolar Piedras --- modules/hal_nordic/nrfx/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index 7463cceefa3c4f..e46e458ccab847 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -45,6 +45,8 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54H20_CPUPPR NRF54H20_XXAA zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L15_ENGA NRF54L15_ENGA_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L15_ENGA_CPUAPP NRF_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L15_ENGA_CPUFLPR NRF_FLPR) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54L15 NRF54L15_XXAA) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54L15_CPUAPP NRF_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9120 NRF9120_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9160 NRF9160_XXAA) From 617cc5441de2a6b3e0a3d368eb37a441383c09e5 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0820/1389] manifest: Update nRF hw models to latest * Update the HW models module to 5d638052c9fe1ef3bd7638067354eba4d3f2fa78 Including the following: * 5d63805 Makefile: Also build NRF54L15 models by default * 0154337 GRTC: Add model * ecd2a01 PPIB: Add model * 086fe1e hal: hack: Add initial nRF54L15 support * 384f29d zephyr integration: Add support for nRF54L15 * b17fffc hal: Include new peripherals hals in static hal version * 67fc961 TEMP: Add nrf54L15 reset values * 4fd6b6f docs: HW impl. status: Add nrf54L15 * 30f7a7b nrf54L15: Initial HW models with reused peripherals * 6150de0 TIMER: Add support for CLK freqs != 16MHz * 4b245cd IRQ controller: Fix typo * 0b0ab3a irq_ctrl: Support more than 64 interrupts * 86800c9 Override HAL type qualifiers to remove const * d2433a1 Make: Add basic infra for NRF54L15 * 3ec8f66 nrf_hack: Reorganize header in preparation for the nrf54 plat * 9f1f473 DPPI types: Use 54 like NRF_DPPI names * ed8f9b7 Make: Provide a reasonable default for BSIM_COMPONENTS_PATH * e55aaff RADIO: Add an explicit check to silence a build warning * 7630b69 RADIO: Make function declaration prototype Signed-off-by: Alberto Escolar Piedras --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 4fd16a2f7d6f0c..05d9717db8355f 100644 --- a/west.yml +++ b/west.yml @@ -295,7 +295,7 @@ manifest: groups: - tools - name: nrf_hw_models - revision: 123d37db9cae528d51530c61ba0422192bc03bda + revision: 5d638052c9fe1ef3bd7638067354eba4d3f2fa78 path: modules/bsim_hw_models/nrf_hw_models - name: open-amp revision: da78aea63159771956fe0c9263f2e6985b66e9d5 From 312c52f83806de2d0b52a729e76fd65062b74781 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0821/1389] boards nrf_bsim: Add a new nrf54l15bsim target Add a new simulated nrf54l15 cpuapp target Signed-off-by: Alberto Escolar Piedras --- boards/native/doc/bsim_boards_design.rst | 5 +- boards/native/nrf_bsim/Kconfig | 18 ++++ boards/native/nrf_bsim/Kconfig.defconfig | 2 + boards/native/nrf_bsim/Kconfig.nrf54l15bsim | 5 ++ boards/native/nrf_bsim/board.yml | 8 +- boards/native/nrf_bsim/board_soc.h | 3 + boards/native/nrf_bsim/doc/nrf54l15bsim.rst | 86 +++++++++++++++++++ .../nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts | 80 +++++++++++++++++ .../nrf54l15bsim_nrf54l15_cpuapp.yaml | 15 ++++ .../nrf54l15bsim_nrf54l15_cpuapp_defconfig | 8 ++ 10 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 boards/native/nrf_bsim/Kconfig.nrf54l15bsim create mode 100644 boards/native/nrf_bsim/doc/nrf54l15bsim.rst create mode 100644 boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts create mode 100644 boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml create mode 100644 boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig diff --git a/boards/native/doc/bsim_boards_design.rst b/boards/native/doc/bsim_boards_design.rst index 6165f76a438dcb..7fef9d1b5228bd 100644 --- a/boards/native/doc/bsim_boards_design.rst +++ b/boards/native/doc/bsim_boards_design.rst @@ -7,6 +7,7 @@ Bsim boards * :ref:`Simulated nRF52833 (nrf52_bsim)` * :ref:`Simulated nRF5340 (nrf5340bsim)` +* :ref:`Simulated nRF54L15 (nrf54l15bsim)` .. contents:: Table of contents :depth: 2 @@ -20,8 +21,8 @@ These boards are postfixed with `_bsim` as they use BabbleSim_ These boards use the `native simulator`_ and the :ref:`POSIX architecture` to build and execute the embedded code natively on Linux. -Particular details on the :ref:`nRF52` and :ref:`nRF5340` -simulation boards, including how to use them, +Particular details on the :ref:`nRF52`, :ref:`nRF5340` and +:ref:`nRF54l15` simulation boards, including how to use them, can be found in their respective documentation. .. _BabbleSim: diff --git a/boards/native/nrf_bsim/Kconfig b/boards/native/nrf_bsim/Kconfig index caed5baf8b6a9b..0273667c4152a9 100644 --- a/boards/native/nrf_bsim/Kconfig +++ b/boards/native/nrf_bsim/Kconfig @@ -34,6 +34,17 @@ config BOARD_NRF5340BSIM_NRF5340_CPUAPP Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute +config BOARD_NRF54L15BSIM_NRF54L15_CPUAPP + bool + select SOC_SERIES_BSIM_NRF54LX + select SOC_COMPATIBLE_NRF54L15 + select SOC_COMPATIBLE_NRF54L15_CPUAPP + select CLOCK_CONTROL + help + Simulated NRF54L15 Application core + Will produce a console Linux process which can be executed natively. + It needs the BabbleSim simulator both in compile time and to execute + if SOC_SERIES_BSIM_NRFXX @@ -76,6 +87,13 @@ config SOC_SERIES_BSIM_NRF53X help Any NRF53 simulated SOC with BabbleSim, based on the POSIX arch +config SOC_SERIES_BSIM_NRF54LX + bool + select SOC_SERIES_BSIM_NRFXX + select SOC_COMPATIBLE_NRF54LX + help + Any NRF54L simulated SOC with BabbleSim, based on the POSIX arch + if BOARD_NRF5340BSIM_NRF5340_CPUAPP # Replica of the option provided by the BOARD_NRF5340DK_NRF5340_CPUAPP board so samples can be diff --git a/boards/native/nrf_bsim/Kconfig.defconfig b/boards/native/nrf_bsim/Kconfig.defconfig index f0d1dde660b9ae..81f90836b543b6 100644 --- a/boards/native/nrf_bsim/Kconfig.defconfig +++ b/boards/native/nrf_bsim/Kconfig.defconfig @@ -30,10 +30,12 @@ config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX default 0 config SYS_CLOCK_HW_CYCLES_PER_SEC + default 1000000 if NRF_GRTC_TIMER default 32768 config SYS_CLOCK_TICKS_PER_SEC default 128 if !TICKLESS_KERNEL + default 10000 if NRF_GRTC_TIMER default 32768 config BT_CTLR diff --git a/boards/native/nrf_bsim/Kconfig.nrf54l15bsim b/boards/native/nrf_bsim/Kconfig.nrf54l15bsim new file mode 100644 index 00000000000000..d3ef1f5ffa2bf9 --- /dev/null +++ b/boards/native/nrf_bsim/Kconfig.nrf54l15bsim @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NRF54L15BSIM + select SOC_POSIX diff --git a/boards/native/nrf_bsim/board.yml b/boards/native/nrf_bsim/board.yml index 874c661c380a1a..ba14ed8aef6f6b 100644 --- a/boards/native/nrf_bsim/board.yml +++ b/boards/native/nrf_bsim/board.yml @@ -6,6 +6,10 @@ boards: - name: nrf5340bsim vendor: zephyr socs: - # Note this is referring to the real SOC yaml, but we only use its name and cpu-cluster definition - # In practice this board uses the same native SOC (SOC_POSIX) as the nrf52_bsim - name: nrf5340 +- name: nrf54l15bsim + vendor: zephyr + socs: + - name: nrf54l15 +# Note the 53 and 54 are referring to the real SOC yamls, but we only use their name and cpu-cluster +# definitions. In practice these board uses the same native SOC (SOC_POSIX) as the nrf52_bsim diff --git a/boards/native/nrf_bsim/board_soc.h b/boards/native/nrf_bsim/board_soc.h index d75a187aa61099..e0b1cb60a594af 100644 --- a/boards/native/nrf_bsim/board_soc.h +++ b/boards/native/nrf_bsim/board_soc.h @@ -31,12 +31,15 @@ #include "cmsis.h" #include "soc_nrf_common.h" +/* For offloading interrupts we can use any free interrupt */ #if defined(CONFIG_BOARD_NRF52_BSIM) #define OFFLOAD_SW_IRQ SWI0_EGU0_IRQn #elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUAPP) #define OFFLOAD_SW_IRQ EGU0_IRQn #elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUNET) #define OFFLOAD_SW_IRQ SWI0_IRQn +#elif defined(CONFIG_BOARD_NRF54L15BSIM) +#define OFFLOAD_SW_IRQ SWI00_IRQn #endif #define FLASH_PAGE_ERASE_MAX_TIME_US 89700UL diff --git a/boards/native/nrf_bsim/doc/nrf54l15bsim.rst b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst new file mode 100644 index 00000000000000..8440d76384d0bd --- /dev/null +++ b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst @@ -0,0 +1,86 @@ +.. _nrf54l15bsim: + +NRF54L15 simulated boards (BabbleSim) +##################################### + +.. contents:: + :depth: 1 + :backlinks: entry + :local: + + +Overview +******** + +To allow simulating nRF54L15 SOCs a Zephyr target boards is provided: the +``nrf54l15bsim/nrf54l15/cpuapp``. + +This uses `BabbleSim`_ to simulate the radio activity, and the +:ref:`POSIX architecture` and the `native simulator`_ to +run applications natively on the development system. This has the benefit of +providing native code execution performance and easy debugging using +native tools, but inherits :ref:`its limitations `. + +Just like for the nrf54l15pdk target, +the nrf54l15bsim/nrf54l15/cpuapp build target provides support for the application core, +on the simulated nRF54L15 SOC. + +.. note:: + + This simulated target does **not** yet support targeting the cpuflpr core. + +.. warning:: + + This target is experimental, and does not yet include models of the RADIO peripheral, + so the BLE and 802.15.4 stacks cannot be run on it yet. + +This boards include models of some of the nRF54L15 SOC peripherals: + +* DPPI (Distributed Programmable Peripheral Interconnect) +* EGU (Event Generator Unit) +* GRTC (Global Real-time Counter) +* PPIB (PPI Bridge) +* RTC (Real Time Counter) +* TEMP (Temperature sensor) +* TIMER + +and will use the same drivers as the nrf54l15pdk targets for these. +For more information on what is modeled to which level of detail, +check the `HW models implementation status`_. + +Note that unlike a real nrf54l15 device, the nrf54l15bsim boards have unlimited RAM and flash for +code. + +.. _BabbleSim: + https://BabbleSim.github.io + +.. _native simulator: + https://github.com/BabbleSim/native_simulator/blob/main/docs/README.md + +.. _HW models implementation status: + https://github.com/BabbleSim/ext_nRF_hw_models/blob/main/docs/README_impl_status.md + + +Building for, and using this board +********************************** + +You can follow the instructions from the :ref:`nrf52_bsim board `. +Simply change the board/target appropriately when building. + + +TrustZone, TF-M and other security considerations +************************************************* + +ARM's TrustZone is not modeled in this board. This means that: + +* There is no differentiation between secure and non secure execution states or bus accesses. +* All RAM, flash and peripherals are in principle accessible from all SW. Peripherals with their + own interconnect master ports can, in principle, access any other peripheral or RAM area. +* There is no nrf54l15bsim/nrf54l15/cpuapp/ns board/build target, or possibility of mixing secure + and non-secure images. +* Currently there is no model of the SPU, and therefore neither RRAM, RAM areas or peripherals + can be labeled as restricted for secure or non secure access. +* TF-M cannot be used. + +Note that the CRACEN peripheral is not modeled. The mbedTLS library can still be used +but with a SW crypto backend. diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts new file mode 100644 index 00000000000000..4a80be6b7ca80c --- /dev/null +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include + +/ { + model = "Nordic NRF54L15 BSIM NRF54L15 Application"; + compatible = "bsim,nrf54l15-bsim-nrf54l15-cpuapp", "bsim,nrf54"; + + chosen { + }; + + /delete-node/ cpus; + /delete-node/ clocks; + /delete-node/ sw-pwm; + + soc { + /delete-node/ uicr@ffd000; + /delete-node/ ficr@ffc000; + /delete-node/ memory@20000000; + /delete-node/ memory@2002f000; + peripheral@50000000 { + /delete-node/ spi@4a000; + /delete-node/ uart@4a000; + /delete-node/ vpr@4c000; + /delete-node/ mailbox@0; + /delete-node/ interrupt-controller@f0000000; + /delete-node/ gpio@50400; + /delete-node/ radio@8a000; + /delete-node/ i2c@c6000; + /delete-node/ spi@c6000; + /delete-node/ uart@c6000; + /delete-node/ i2c@c7000; + /delete-node/ spi@c7000; + /delete-node/ uart@c7000; + /delete-node/ i2c@c8000; + /delete-node/ spi@c8000; + /delete-node/ uart@c8000; + /delete-node/ pwm@d2000; + /delete-node/ pwm@d3000; + /delete-node/ pwm@d4000; + /delete-node/ adc@d5000; + /delete-node/ nfct@d6000; + /delete-node/ gpio@d8200; + /delete-node/ gpiote@da000; + /delete-node/ i2s@dd000; + /delete-node/ qdec@e0000; + /delete-node/ qdec@e1000; + /delete-node/ i2c@104000; + /delete-node/ spi@104000; + /delete-node/ uart@104000; + /delete-node/ watchdog@108000; + /delete-node/ watchdog@109000; + /delete-node/ gpio@10a000; + /delete-node/ gpiote@10c000; + /delete-node/ clock@10e000; + }; + /delete-node/ rram-controller@5004b000; + /delete-node/ spu@50003000; + /delete-node/ gpiote@5000d000; + /delete-node/ crypto@50844000; + }; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&temp { + status = "okay"; +}; diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml new file mode 100644 index 00000000000000..acdf8e2a467e83 --- /dev/null +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml @@ -0,0 +1,15 @@ +identifier: nrf54l15bsim/nrf54l15/cpuapp +name: NRF54L15 BabbleSim - Application Core target +type: native +arch: posix +simulation: native +env: + - BSIM_OUT_PATH +toolchain: + - zephyr +testing: + ignore_tags: + - gpio + - modem + - uart + - bsim_skip_CI diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig new file mode 100644 index 00000000000000..0fde4e01b5838b --- /dev/null +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Nordic Semiconductor ASA + +CONFIG_CONSOLE=y +CONFIG_NO_OPTIMIZATIONS=y + +# Start SYSCOUNTER on driver init +CONFIG_NRF_GRTC_START_SYSCOUNTER=y From 3e13653bfc84ba8c719ad6b21eeb6bc447ab1913 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0822/1389] drivers/timer/nrf_grtc_timer: Misc fixes Misc fixes for the grtc timer driver: * In non tickless mode: * The tick time would drift a bit with each interrupt * If something would cause a very significant delay in handling the tick interrupt the number of announcements would be incorrect * Fortickless mode: The calculation of the next tick time in sys_clock_set_timeout() was incorrectly done, resulting in two spurious, too early, wakes of the kernel before each correct wake. This caused tests/kernel/context/ to fail. Signed-off-by: Alberto Escolar Piedras --- drivers/timer/nrf_grtc_timer.c | 58 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 98faa4e231cc1e..a5c41a63ab97c7 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -65,7 +65,7 @@ const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context); static struct k_spinlock lock; -static uint64_t last_count; +static uint64_t last_count; /* Time (SYSCOUNTER value) @last sys_clock_announce() */ static atomic_t int_mask; static uint8_t ext_channels_allocated; static nrfx_grtc_channel_t system_clock_channel_data = { @@ -137,7 +137,10 @@ static inline int get_comparator(uint32_t chan, uint64_t *cc) return 0; } -static void system_timeout_set(uint64_t value) +/* + * Program a new callback microseconds in the future + */ +static void system_timeout_set_relative(uint64_t value) { if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) { grtc_wakeup(); @@ -150,6 +153,15 @@ static void system_timeout_set(uint64_t value) } } +/* + * Program a new callback in the absolute time given by + */ +static void system_timeout_set_abs(uint64_t value) +{ + nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value, + true); +} + static bool compare_int_lock(int32_t chan) { atomic_val_t prev = atomic_and(&int_mask, ~BIT(chan)); @@ -172,22 +184,19 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte ARG_UNUSED(id); ARG_UNUSED(p_context); uint64_t dticks; - uint64_t now = counter(); - if (unlikely(now < cc_val)) { - return; - } + dticks = counter_sub(cc_val, last_count) / CYC_PER_TICK; + + last_count += dticks * CYC_PER_TICK; + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { /* protection is not needed because we are in the GRTC interrupt * so it won't get preempted by the interrupt. */ - system_timeout_set(CYC_PER_TICK); + system_timeout_set_abs(last_count + CYC_PER_TICK); } - dticks = counter_sub(now, last_count) / CYC_PER_TICK; - - last_count += dticks * CYC_PER_TICK; - sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? (int32_t)dticks : (dticks > 0)); + sys_clock_announce((int32_t)dticks); } int32_t z_nrf_grtc_timer_chan_alloc(void) @@ -520,7 +529,7 @@ static int sys_clock_driver_init(void) int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - system_timeout_set(CYC_PER_TICK); + system_timeout_set_relative(CYC_PER_TICK); } #if defined(CONFIG_CLOCK_CONTROL_NRF) @@ -540,34 +549,23 @@ static int sys_clock_driver_init(void) void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); - uint64_t cyc, off, now; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { return; } - ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks - 1, 0)); - - now = counter(); + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks, 0)); - /* Round up to the next tick boundary */ - off = (now - last_count) + (CYC_PER_TICK - 1); - off = (off / CYC_PER_TICK) * CYC_PER_TICK; + uint64_t delta_time = ticks * CYC_PER_TICK; - /* Get the offset with respect to now */ - off -= (now - last_count); + uint64_t target_time = counter() + delta_time; - /* Add the offset to get to the next tick boundary */ - cyc = (uint64_t)ticks * CYC_PER_TICK + off; - - /* Due to elapsed time the calculation above might produce a - * duration that laps the counter. Don't let it. + /* Rounded down target_time to the tick boundary + * (but not less than one tick after the last) */ - if (cyc > MAX_CYCLES) { - cyc = MAX_CYCLES; - } + target_time = MAX((target_time - last_count)/CYC_PER_TICK, 1)*CYC_PER_TICK + last_count; - system_timeout_set(cyc == 0 ? 1 : cyc); + system_timeout_set_abs(target_time); } #if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT) From b00dbb30e9e12103d9dd2174b06175b94b8b1efc Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0823/1389] boards nrf54l15bsim_nrf54l15_cpuapp: Enable counter tests These tests run fine in this board, let's provide an overlay and enable them. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml | 2 ++ .../boards/nrf54l15bsim_nrf54l15_cpuapp.overlay | 1 + 2 files changed, 3 insertions(+) create mode 100644 tests/drivers/counter/counter_basic_api/boards/nrf54l15bsim_nrf54l15_cpuapp.overlay diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml index acdf8e2a467e83..cbdd257334f44b 100644 --- a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml @@ -7,6 +7,8 @@ env: - BSIM_OUT_PATH toolchain: - zephyr +supported: + - counter testing: ignore_tags: - gpio diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54l15bsim_nrf54l15_cpuapp.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54l15bsim_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..b1942e1f84f8f9 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54l15bsim_nrf54l15_cpuapp.overlay @@ -0,0 +1 @@ +#include "nrf54l15pdk_nrf54l15_cpuapp.overlay" From dc4c93851d6dfe6b4cae84ea6d262ae8506fd6c1 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0824/1389] board: nrf54bsim: Add cmake check to prevent targetting the flipper core This is not yet possible. So let's add a check that provides an easy to understanding error message instead of a bunch of kconfig and build warnings. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boards/native/nrf_bsim/CMakeLists.txt b/boards/native/nrf_bsim/CMakeLists.txt index a4329cd888007d..d55a52e1a5311f 100644 --- a/boards/native/nrf_bsim/CMakeLists.txt +++ b/boards/native/nrf_bsim/CMakeLists.txt @@ -6,6 +6,10 @@ find_package(BabbleSim) zephyr_library() +if (CONFIG_BOARD_NRF54L15BSIM_NRF54L15_CPUFLPR) + message(FATAL_ERROR "Targeting the nrf54l15bsim/nrf54l15/cpuflpr core is not yet supported") +endif() + # Due to the BLE controller assumption about enum size zephyr_compile_options( -fshort-enums From 79cafb3f7b74cd195570b18e47bccc296b63a9c2 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0825/1389] board nrf54l15bsim: Let's use the native entropy driver Let's use the native_posix entropy driver by now, as the real target relies on the PSA one, and we currently do not have plans to include that. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts index 4a80be6b7ca80c..994af625bcbbaf 100644 --- a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -14,6 +14,7 @@ compatible = "bsim,nrf54l15-bsim-nrf54l15-cpuapp", "bsim,nrf54"; chosen { + zephyr,entropy = &rng; }; /delete-node/ cpus; @@ -66,6 +67,11 @@ /delete-node/ gpiote@5000d000; /delete-node/ crypto@50844000; }; + + rng: rng { + status = "okay"; + compatible = "zephyr,native-posix-rng"; + }; }; &grtc { From 99a7cb1b924c65e2abb633d1486828df2c7b768d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0826/1389] develop/test/bsim: Reference new nrf54l15bsim target Add links to the new nrf54l15 from this doc. Signed-off-by: Alberto Escolar Piedras --- doc/develop/test/bsim.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/develop/test/bsim.rst b/doc/develop/test/bsim.rst index d2f98295dc76a9..0bdc7d0fecc199 100644 --- a/doc/develop/test/bsim.rst +++ b/doc/develop/test/bsim.rst @@ -21,7 +21,8 @@ to simulate the radio channel. In the BabbleSim documentation you can find more information on how to `get `_ and `build `_ the simulator. -In the :ref:`nrf52_bsim` and :ref:`nrf5340bsim` boards documentation +In the :ref:`nrf52_bsim`, :ref:`nrf5340bsim`, +and :ref:`nrf54l15bsim` boards documentation you can find more information about how to build Zephyr targeting these particular boards, and a few examples. @@ -67,8 +68,9 @@ found in the :ref:`bsim boards tests section`. Test coverage and BabbleSim *************************** -As the :ref:`nrf52_bsim` and :ref:`nrf5340bsim` boards are based on the -POSIX architecture, you can easily collect test coverage information. +As the :ref:`nrf52_bsim` and :ref:`nrf5340bsim`, and +:ref:`nrf54l15bsim` boards are based on the POSIX architecture, you can easily collect +test coverage information. You can use the script :zephyr_file:`tests/bsim/generate_coverage_report.sh` to generate an html coverage report from tests. From abc57b53f0fe33916cb31f3c7c43f6c7dc4e955d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0827/1389] doc: release_notes: Mention new nrf54l15bsim target Add a mention of the new nrf54l15bsim in the release notes. Signed-off-by: Alberto Escolar Piedras --- doc/releases/release-notes-3.7.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 12c90c0298bb1d..47aee8764a590e 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -108,6 +108,8 @@ Boards & SoC Support * Made these changes for native/POSIX boards: + * Introduced the simulated :ref:`nrf54l15bsim` target. + * LLVM fuzzing support has been refactored while adding support for it in native_sim. * Added support for these following shields: From 0ac531f2eec145043666fb0b04bfe058406a90d7 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Sun, 26 May 2024 22:39:10 +0200 Subject: [PATCH 0828/1389] include: storage: flash_map: _NODE macros adds size, offset and divice access macros that are operating with nodes as an argumet. Signed-off-by: Mateusz Michalek --- include/zephyr/storage/flash_map.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index 37b7c7f3223315..b03628afc93ec3 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -301,6 +301,15 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); */ #define FIXED_PARTITION_OFFSET(label) DT_REG_ADDR(DT_NODELABEL(label)) +/** + * Get fixed-partition offset from DTS node + * + * @param node DTS node of a partition + * + * @return fixed-partition offset, as defined for the partition in DTS. + */ +#define FIXED_PARTITION_NODE_OFFSET(node) DT_REG_ADDR(node) + /** * Get fixed-partition size for DTS node label * @@ -310,6 +319,15 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); */ #define FIXED_PARTITION_SIZE(label) DT_REG_SIZE(DT_NODELABEL(label)) +/** + * Get fixed-partition size for DTS node + * + * @param node DTS node of a partition + * + * @return fixed-partition size, as defined for the partition in DTS. + */ +#define FIXED_PARTITION_NODE_SIZE(node) DT_REG_SIZE(node) + /** * Get device pointer for device the area/partition resides on * @@ -330,6 +348,16 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); #define FIXED_PARTITION_DEVICE(label) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))) +/** + * Get device pointer for device the area/partition resides on + * + * @param node DTS node of a partition + * + * @return Pointer to a device. + */ +#define FIXED_PARTITION_NODE_DEVICE(node) \ + DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(node)) + #ifdef __cplusplus } #endif From 0c0dfb2fff3f572db3cc4192e723e73d06979625 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0829/1389] tests: storage: flash_map: _NODE macros adds API checks for fixed partitions access macros that are called with nodes as an argumet. Signed-off-by: Mateusz Michalek --- tests/subsys/storage/flash_map/src/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/subsys/storage/flash_map/src/main.c b/tests/subsys/storage/flash_map/src/main.c index 07430fc766e584..e66f6ac7e0f133 100644 --- a/tests/subsys/storage/flash_map/src/main.c +++ b/tests/subsys/storage/flash_map/src/main.c @@ -13,6 +13,7 @@ #define SLOT1_PARTITION slot1_partition #define SLOT1_PARTITION_ID FIXED_PARTITION_ID(SLOT1_PARTITION) #define SLOT1_PARTITION_DEV FIXED_PARTITION_DEVICE(SLOT1_PARTITION) +#define SLOT1_PARTITION_NODE DT_NODELABEL(SLOT1_PARTITION) extern int flash_map_entries; struct flash_sector fs_sectors[256]; @@ -190,4 +191,15 @@ ZTEST(flash_map, test_flash_area_erased_val) flash_area_close(fa); } +ZTEST(flash_map, test_fixed_partition_node_macros) +{ + /* Test against changes in API */ + zassert_equal(FIXED_PARTITION_NODE_OFFSET(SLOT1_PARTITION_NODE), + DT_REG_ADDR(SLOT1_PARTITION_NODE)); + zassert_equal(FIXED_PARTITION_NODE_SIZE(SLOT1_PARTITION_NODE), + DT_REG_SIZE(SLOT1_PARTITION_NODE)); + zassert_equal(FIXED_PARTITION_NODE_DEVICE(SLOT1_PARTITION_NODE), + DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(SLOT1_PARTITION_NODE))); +} + ZTEST_SUITE(flash_map, NULL, NULL, NULL, NULL, NULL); From a55aceecd4feadfc4b55977d7ee68a8b385df8c9 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0830/1389] drivers: i3c: use byte ordering macros with ccc Use the sys_get_be* macros with ccc where it can be used. Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_ccc.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/i3c/i3c_ccc.c b/drivers/i3c/i3c_ccc.c index efe65e6756e149..748d25e4b9ebd3 100644 --- a/drivers/i3c/i3c_ccc.c +++ b/drivers/i3c/i3c_ccc.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -254,8 +255,7 @@ int i3c_ccc_do_setmwl_all(const struct device *controller, ccc_payload.ccc.data_len = sizeof(data); /* The actual data is MSB first. So order the data. */ - data[0] = (uint8_t)((mwl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mwl->len & 0xFFU); + sys_put_be16(mwl->len, data); return i3c_do_ccc(controller, &ccc_payload); } @@ -282,8 +282,7 @@ int i3c_ccc_do_setmwl(const struct i3c_device_desc *target, ccc_payload.targets.num_targets = 1; /* The actual length is MSB first. So order the data. */ - data[0] = (uint8_t)((mwl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mwl->len & 0xFFU); + sys_put_be16(mwl->len, data); return i3c_do_ccc(target->bus, &ccc_payload); } @@ -314,7 +313,7 @@ int i3c_ccc_do_getmwl(const struct i3c_device_desc *target, if (ret == 0) { /* The actual length is MSB first. So order the data. */ - mwl->len = (data[0] << 8) | data[1]; + mwl->len = sys_get_be16(data); } return ret; @@ -337,8 +336,7 @@ int i3c_ccc_do_setmrl_all(const struct device *controller, ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2; /* The actual length is MSB first. So order the data. */ - data[0] = (uint8_t)((mrl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mrl->len & 0xFFU); + sys_put_be16(mrl->len, data); if (has_ibi_size) { data[2] = mrl->ibi_len; @@ -368,8 +366,7 @@ int i3c_ccc_do_setmrl(const struct i3c_device_desc *target, ccc_payload.targets.num_targets = 1; /* The actual length is MSB first. So order the data. */ - data[0] = (uint8_t)((mrl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mrl->len & 0xFFU); + sys_put_be16(mrl->len, data); if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) { @@ -413,7 +410,7 @@ int i3c_ccc_do_getmrl(const struct i3c_device_desc *target, if (ret == 0) { /* The actual length is MSB first. So order the data. */ - mrl->len = (data[0] << 8) | data[1]; + mrl->len = sys_get_be16(data); if (has_ibi_sz) { mrl->ibi_len = data[2]; @@ -477,13 +474,13 @@ int i3c_ccc_do_getstatus(const struct i3c_device_desc *target, if (ret == 0) { /* Received data is MSB first. So order the data. */ if (fmt == GETSTATUS_FORMAT_1) { - status->fmt1.status = (data[0] << 8) | data[1]; + status->fmt1.status = sys_get_be16(data); } else if (fmt == GETSTATUS_FORMAT_2) { switch (defbyte) { case GETSTATUS_FORMAT_2_TGTSTAT: __fallthrough; case GETSTATUS_FORMAT_2_PRECR: - status->fmt2.raw_u16 = (data[0] << 8) | data[1]; + status->fmt2.raw_u16 = sys_get_be16(data); break; default: break; From 31b8a4f6330f6b51173e73c1dc0aaddde8ec4845 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0831/1389] drivers: i3c: fix ccc getmxds macros GETMXDS macros had typos in them. This fixes them. Signed-off-by: Ryan McClelland --- include/zephyr/drivers/i3c/ccc.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/zephyr/drivers/i3c/ccc.h b/include/zephyr/drivers/i3c/ccc.h index 116750bcac59bc..9846efce0a1711 100644 --- a/include/zephyr/drivers/i3c/ccc.h +++ b/include/zephyr/drivers/i3c/ccc.h @@ -761,7 +761,7 @@ union i3c_ccc_getmxds { /** Get Max Data Speed (GETMXDS) - Max Sustained Data Rate bitmask. */ #define I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_MASK \ - (0x07U << I3C_CCC_GET_MXDS_MAXWR_MAX_SDR_FSCL_SHIFT) + (0x07U << I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_SHIFT) /** * @brief Get Max Data Speed (GETMXDS) - maxWr - Max Sustained Data Rate @@ -803,7 +803,7 @@ union i3c_ccc_getmxds { /** Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate bitmask. */ #define I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_MASK \ - (0x07U << I3C_CCC_GET_MXDS_MAXRD_MAX_SDR_FSCL_SHIFT) + (0x07U << I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_SHIFT) /** * @brief Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate @@ -826,7 +826,7 @@ union i3c_ccc_getmxds { /** Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State bitmask. */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_MASK \ - (0x03U << I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_SHIFT) + (0x03U << I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_SHIFT) /** * @brief Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State @@ -838,8 +838,8 @@ union i3c_ccc_getmxds { */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE(crhdly1) \ (((crhdly1) & \ - I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_MASK) \ - >> I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_SHIFT) + I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_MASK) \ + >> I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_SHIFT) /** * @brief Payload for GETCAPS CCC (Get Optional Feature Capabilities). From 4e50a6497973ae5a8c13b22a6e7c44d1b9f5db85 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0832/1389] drivers: i3c: add ccc getcaps helper This adds the defines for getcaps format 1 and format 2. Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_ccc.c | 99 ++++++++ include/zephyr/drivers/i3c.h | 52 ++++ include/zephyr/drivers/i3c/ccc.h | 395 ++++++++++++++++++++++++++++--- 3 files changed, 512 insertions(+), 34 deletions(-) diff --git a/drivers/i3c/i3c_ccc.c b/drivers/i3c/i3c_ccc.c index 748d25e4b9ebd3..7b03b5b9f429f5 100644 --- a/drivers/i3c/i3c_ccc.c +++ b/drivers/i3c/i3c_ccc.c @@ -491,3 +491,102 @@ int i3c_ccc_do_getstatus(const struct i3c_device_desc *target, out: return ret; } + +int i3c_ccc_do_getcaps(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps, + enum i3c_ccc_getcaps_fmt fmt, + enum i3c_ccc_getcaps_defbyte defbyte) +{ + struct i3c_ccc_payload ccc_payload; + struct i3c_ccc_target_payload ccc_tgt_payload; + uint8_t defining_byte; + uint8_t data[4]; + uint8_t len; + int ret; + + __ASSERT_NO_MSG(target != NULL); + __ASSERT_NO_MSG(target->bus != NULL); + __ASSERT_NO_MSG(caps != NULL); + + ccc_tgt_payload.addr = target->dynamic_addr; + ccc_tgt_payload.rnw = 1; + ccc_tgt_payload.data = &data[0]; + + if (fmt == GETCAPS_FORMAT_1) { + /* Could be 1-4 Data Bytes Returned */ + ccc_tgt_payload.data_len = 4; + } else if (fmt == GETCAPS_FORMAT_2) { + switch (defbyte) { + case GETCAPS_FORMAT_2_CRCAPS: + __fallthrough; + case GETCAPS_FORMAT_2_VTCAPS: + /* Could be 1-2 Data Bytes Returned*/ + ccc_tgt_payload.data_len = 2; + break; + case GETCAPS_FORMAT_2_TGTCAPS: + __fallthrough; + case GETCAPS_FORMAT_2_TESTPAT: + /* Could be 1-4 Data Bytes Returned */ + ccc_tgt_payload.data_len = 4; + break; + default: + ret = -EINVAL; + goto out; + } + } else { + ret = -EINVAL; + goto out; + } + + memset(&ccc_payload, 0, sizeof(ccc_payload)); + ccc_payload.ccc.id = I3C_CCC_GETCAPS; + ccc_payload.targets.payloads = &ccc_tgt_payload; + ccc_payload.targets.num_targets = 1; + + if (fmt == GETCAPS_FORMAT_2) { + defining_byte = (uint8_t)defbyte; + + ccc_payload.ccc.data = &defining_byte; + ccc_payload.ccc.data_len = 1; + } + + ret = i3c_do_ccc(target->bus, &ccc_payload); + + if (ret == 0) { + /* GETCAPS will return a variable length */ + len = ccc_tgt_payload.num_xfer; + + if (fmt == GETCAPS_FORMAT_1) { + memcpy(caps->fmt1.getcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len); + } else if (fmt == GETCAPS_FORMAT_2) { + switch (defbyte) { + case GETCAPS_FORMAT_2_CRCAPS: + memcpy(caps->fmt2.crcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len); + case GETCAPS_FORMAT_2_VTCAPS: + memcpy(caps->fmt2.vtcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len); + break; + case GETCAPS_FORMAT_2_TGTCAPS: + memcpy(caps->fmt2.tgtcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt2.tgtcaps[len], 0, + sizeof(caps->fmt2.tgtcaps) - len); + break; + case GETCAPS_FORMAT_2_TESTPAT: + /* should always be 4 data bytes */ + caps->fmt2.testpat = sys_get_be32(data); + break; + default: + break; + } + } + } + +out: + return ret; +} diff --git a/include/zephyr/drivers/i3c.h b/include/zephyr/drivers/i3c.h index b5411dcd9a309b..7233143fc705dd 100644 --- a/include/zephyr/drivers/i3c.h +++ b/include/zephyr/drivers/i3c.h @@ -1040,6 +1040,58 @@ struct i3c_device_desc { uint8_t max_ibi; } data_length; + /** Describes advanced (Target) capabilities and features */ + struct { + union { + /** + * I3C v1.0 HDR Capabilities (@c I3C_CCC_GETCAPS1_*) + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[7:3]: Reserved + */ + uint8_t gethdrcap; + + /** + * I3C v1.1+ GETCAPS1 (@c I3C_CCC_GETCAPS1_*) + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[3]: HDR-BT + * - Bit[7:4]: Reserved + */ + uint8_t getcap1; + }; + + /** + * GETCAPS2 (@c I3C_CCC_GETCAPS2_*) + * - Bit[3:0]: I3C 1.x Specification Version + * - Bit[5:4]: Group Address Capabilities + * - Bit[6]: HDR-DDR Write Abort + * - Bit[7]: HDR-DDR Abort CRC + */ + uint8_t getcap2; + + /** + * GETCAPS3 (@c I3C_CCC_GETCAPS3_*) + * - Bit[0]: Multi-Lane (ML) Data Transfer Support + * - Bit[1]: Device to Device Transfer (D2DXFER) Support + * - Bit[2]: Device to Device Transfer (D2DXFER) IBI Capable + * - Bit[3]: Defining Byte Support in GETCAPS + * - Bit[4]: Defining Byte Support in GETSTATUS + * - Bit[5]: HDR-BT CRC-32 Support + * - Bit[6]: IBI MDB Support for Pending Read Notification + * - Bit[7]: Reserved + */ + uint8_t getcap3; + + /** + * GETCAPS4 + * - Bit[7:0]: Reserved + */ + uint8_t getcap4; + } getcaps; + /** * Private data by the controller to aid in transactions. Do not modify. * diff --git a/include/zephyr/drivers/i3c/ccc.h b/include/zephyr/drivers/i3c/ccc.h index 9846efce0a1711..767d922086c2db 100644 --- a/include/zephyr/drivers/i3c/ccc.h +++ b/include/zephyr/drivers/i3c/ccc.h @@ -841,26 +841,144 @@ union i3c_ccc_getmxds { I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_MASK) \ >> I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_SHIFT) +/** + * @brief Indicate which format of GETCAPS to use. + */ +enum i3c_ccc_getcaps_fmt { + /** GETCAPS Format 1 */ + GETCAPS_FORMAT_1, + + /** GETCAPS Format 2 */ + GETCAPS_FORMAT_2, +}; + +/** + * @brief Enum for I3C Get Capabilities (GETCAPS) Format 2 Defining Byte Values. + */ +enum i3c_ccc_getcaps_defbyte { + /** Standard Target capabilities and features. */ + GETCAPS_FORMAT_2_TGTCAPS = 0x00U, + + /** Fixed 32b test pattern. */ + GETCAPS_FORMAT_2_TESTPAT = 0x5AU, + + /** Controller handoff capabilities and features. */ + GETCAPS_FORMAT_2_CRCAPS = 0x91U, + + /** Virtual Target capabilities and features. */ + GETCAPS_FORMAT_2_VTCAPS = 0x93U, + + /** Debug-capable Device capabilities and features. */ + GETCAPS_FORMAT_2_DBGCAPS = 0xD7U, + + /** Invalid defining byte. */ + GETCAPS_FORMAT_2_INVALID = 0x100, +}; + /** * @brief Payload for GETCAPS CCC (Get Optional Feature Capabilities). * - * @note Only support GETCAPS Format 1. + * @note Only supports GETCAPS Format 1 and Format 2. In I3C v1.0 this was + * GETHDRCAP which only returned a single byte which is the same as the + * GETCAPS1 byte. */ -struct i3c_ccc_getcaps { - /** - * GETCAP[1-4] bytes. - */ - uint8_t getcaps[4]; +union i3c_ccc_getcaps { + union { + /** + * I3C v1.0 HDR Capabilities + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[7:3]: Reserved + */ + uint8_t gethdrcap; + + /** + * I3C v1.1+ Device Capabilities + * Byte 1 GETCAPS1 + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[3]: HDR-BT + * - Bit[7:4]: Reserved + * Byte 2 GETCAPS2 + * - Bit[3:0]: I3C 1.x Specification Version + * - Bit[5:4]: Group Address Capabilities + * - Bit[6]: HDR-DDR Write Abort + * - Bit[7]: HDR-DDR Abort CRC + * Byte 3 GETCAPS3 + * - Bit[0]: Multi-Lane (ML) Data Transfer Support + * - Bit[1]: Device to Device Transfer (D2DXFER) Support + * - Bit[2]: Device to Device Transfer (D2DXFER) IBI Capable + * - Bit[3]: Defining Byte Support in GETCAPS + * - Bit[4]: Defining Byte Support in GETSTATUS + * - Bit[5]: HDR-BT CRC-32 Support + * - Bit[6]: IBI MDB Support for Pending Read Notification + * - Bit[7]: Reserved + * Byte 4 GETCAPS4 + * - Bit[7:0]: Reserved + */ + uint8_t getcaps[4]; + } fmt1; + + union { + /** + * Defining Byte 0x00: TGTCAPS + * + * @see i3c_ccc_getcaps::fmt1::getcaps + */ + uint8_t tgtcaps[4]; + + /** + * Defining Byte 0x5A: TESTPAT + * + * @note should always be 0xA55AA55A in big endian + */ + uint32_t testpat; + + /** + * Defining Byte 0x91: CRCAPS + * Byte 1 CRCAPS1 + * - Bit[0]: Hot-Join Support + * - Bit[1]: Group Management Support + * - Bit[2]: Multi-Lane Support + * Byte 2 CRCAPS2 + * - Bit[0]: In-Band Interrupt Support + * - Bit[1]: Controller Pass-Back + * - Bit[2]: Deep Sleep Capable + * - Bit[3]: Delayed Controller Handoff + */ + uint8_t crcaps[2]; + + /** + * Defining Byte 0x93: VTCAPS + * Byte 1 VTCAPS1 + * - Bit[2:0]: Virtual Target Type + * - Bit[4]: Side Effects + * - Bit[5]: Shared Peripheral Detect + * Byte 2 VTCAPS2 + * - Bit[1:0]: Interrupt Requests + * - Bit[2]: Address Remapping + * - Bit[4:3]: Bus Context and Conditions + */ + uint8_t vtcaps[2]; + } fmt2; } __packed; -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR-DDR mode bit. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-DDR mode bit. */ #define I3C_CCC_GETCAPS1_HDR_DDR BIT(0) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR-BT mode bit. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-TSP mode bit. */ +#define I3C_CCC_GETCAPS1_HDR_TSP BIT(1) + +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-TSL mode bit. */ +#define I3C_CCC_GETCAPS1_HDR_TSL BIT(2) + +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-BT mode bit. */ #define I3C_CCC_GETCAPS1_HDR_BT BIT(3) /** - * @brief Get Optional Feature Capabilities (GETCAPS) - HDR Mode + * @brief Get Optional Feature Capabilities Byte 1 (GETCAPS) - HDR Mode * * Get the bit corresponding to HDR mode. * @@ -868,53 +986,53 @@ struct i3c_ccc_getcaps { */ #define I3C_CCC_GETCAPS1_HDR_MODE(x) BIT(x) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 0. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 0. */ #define I3C_CCC_GETCAPS1_HDR_MODE0 BIT(0) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 1. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 1. */ #define I3C_CCC_GETCAPS1_HDR_MODE1 BIT(1) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 2. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 2. */ #define I3C_CCC_GETCAPS1_HDR_MODE2 BIT(2) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 3. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 3. */ #define I3C_CCC_GETCAPS1_HDR_MODE3 BIT(3) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 4. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 4. */ #define I3C_CCC_GETCAPS1_HDR_MODE4 BIT(4) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 5. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 5. */ #define I3C_CCC_GETCAPS1_HDR_MODE5 BIT(5) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 6. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 6. */ #define I3C_CCC_GETCAPS1_HDR_MODE6 BIT(6) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 7. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 7. */ #define I3C_CCC_GETCAPS1_HDR_MODE7 BIT(7) -/** Get Optional Feature Capabilities (GETCAPS) Format 2 - HDR-DDR Write Abort bit. */ +/** Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - HDR-DDR Write Abort bit. */ #define I3C_CCC_GETCAPS2_HDRDDR_WRITE_ABORT BIT(6) -/** Get Optional Feature Capabilities (GETCAPS) Format 2 - HDR-DDR Abort CRC bit. */ +/** Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - HDR-DDR Abort CRC bit. */ #define I3C_CCC_GETCAPS2_HDRDDR_ABORT_CRC BIT(7) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * Group Address Capabilities bit shift value. */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP_SHIFT 4 /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * Group Address Capabilities bitmask. */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP_MASK \ (0x03U << I3C_CCC_GETCAPS2_GRPADDR_CAP_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - Group Address Capabilities. + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - Group Address Capabilities. * - * Obtain Group Address Capabilities value from GETCAPS Format 2 value + * Obtain Group Address Capabilities value from GETCAPS Format 1 value * obtained via GETCAPS. * * @param getcaps2 GETCAPS2 value. @@ -925,23 +1043,23 @@ struct i3c_ccc_getcaps { >> I3C_CCC_GETCAPS_GRPADDR_CAP_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * I3C 1.x Specification Version bit shift value. */ #define I3C_CCC_GETCAPS2_SPEC_VER_SHIFT 0 /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * I3C 1.x Specification Version bitmask. */ #define I3C_CCC_GETCAPS2_SPEC_VER_MASK \ (0x0FU << I3C_CCC_GETCAPS2_SPEC_VER_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * I3C 1.x Specification Version. * - * Obtain I3C 1.x Specification Version value from GETCAPS Format 2 value + * Obtain I3C 1.x Specification Version value from GETCAPS Format 1 value * obtained via GETCAPS. * * @param getcaps2 GETCAPS2 value. @@ -952,47 +1070,197 @@ struct i3c_ccc_getcaps { >> I3C_CCC_GETCAPS_SPEC_VER_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Multi-Lane Data Transfer Support bit. */ #define I3C_CCC_GETCAPS3_MLANE_SUPPORT BIT(0) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Device to Device Transfer (D2DXFER) Support bit. */ #define I3C_CCC_GETCAPS3_D2DXFER_SUPPORT BIT(1) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Device to Device Transfer (D2DXFER) IBI Capable bit. */ #define I3C_CCC_GETCAPS3_D2DXFER_IBI_CAPABLE BIT(2) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Defining Byte Support in GETCAPS bit. */ #define I3C_CCC_GETCAPS3_GETCAPS_DEFINING_BYTE_SUPPORT BIT(3) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Defining Byte Support in GETSTATUS bit. */ #define I3C_CCC_GETCAPS3_GETSTATUS_DEFINING_BYTE_SUPPORT BIT(4) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * HDR-BT CRC-32 Support bit. */ #define I3C_CCC_GETCAPS3_HDRBT_CRC32_SUPPORT BIT(5) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * IBI MDB Support for Pending Read Notification bit. */ #define I3C_CCC_GETCAPS3_IBI_MDR_PENDING_READ_NOTIFICATION BIT(6) +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 1. + */ +#define I3C_CCC_GETCAPS_TESTPAT1 0xA5 + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 2. + */ +#define I3C_CCC_GETCAPS_TESTPAT2 0x5A + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 3. + */ +#define I3C_CCC_GETCAPS_TESTPAT3 0xA5 + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 4. + */ +#define I3C_CCC_GETCAPS_TESTPAT4 0x5A + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Word in Big Endian. + */ +#define I3C_CCC_GETCAPS_TESTPAT 0xA55AA55A + +/** + * @brief Get Controller Handoff Capabilities Byte 1 (GETCAPS) Format 2 - + * Hot-Join Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS1_HJ_SUPPORT BIT(0) + +/** + * @brief Get Controller Handoff Capabilities Byte 1 (GETCAPS) Format 2 - + * Group Management Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS1_GRP_MANAGEMENT_SUPPORT BIT(1) + +/** + * @brief Get Controller Handoff Capabilities Byte 1 (GETCAPS) Format 2 - + * Multi-Lane Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS1_ML_SUPPORT BIT(2) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * In-Band Interrupt Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_IBI_TIR_SUPPORT BIT(0) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * Controller Pass-Back. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_CONTROLLER_PASSBACK BIT(1) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * Deep Sleep Capable. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_DEEP_SLEEP_CAPABLE BIT(2) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * Deep Sleep Capable. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_DELAYED_CONTROLLER_HANDOFF BIT(3) + +/** Get Capabilities (GETCAPS) - VTCAP1 - Virtual Target Type bit shift value. */ +#define I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_SHIFT 0 + +/** Get Capabilities (GETCAPS) - VTCAP1 - Virtual Target Type bitmask. */ +#define I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_MASK \ + (0x07U << I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_SHIFT) + +/** + * @brief Get Capabilities (GETCAPS) - VTCAP1 - Virtual Target Type + * + * Obtain Virtual Target Type value from VTCAP1 value + * obtained via GETCAPS format 2 VTCAP def byte. + * + * @param vtcap1 VTCAP1 value. + */ +#define I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE(vtcap1) \ + (((vtcap1) & \ + I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_MASK) \ + >> I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_SHIFT) + +/** + * @brief Get Virtual Target Capabilities Byte 1 (GETCAPS) Format 2 - + * Side Effects. + */ +#define I3C_CCC_GETCAPS_VTCAP1_SIDE_EFFECTS BIT(4) + +/** + * @brief Get Virtual Target Capabilities Byte 1 (GETCAPS) Format 2 - + * Shared Peripheral Detect. + */ +#define I3C_CCC_GETCAPS_VTCAP1_SHARED_PERIPH_DETECT BIT(5) + +/** Get Capabilities (GETCAPS) - VTCAP2 - Interrupt Requests bit shift value. */ +#define I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_SHIFT 0 + +/** Get Capabilities (GETCAPS) - VTCAP2 - Interrupt Requests bitmask. */ +#define I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_MASK \ + (0x03U << I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_SHIFT) + +/** + * @brief Get Capabilities (GETCAPS) - VTCAP2 - Interrupt Requests + * + * Obtain Interrupt Requests value from VTCAP2 value + * obtained via GETCAPS format 2 VTCAP def byte. + * + * @param vtcap2 VTCAP2 value. + */ +#define I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS(vtcap2) \ + (((vtcap2) & \ + I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_MASK) \ + >> I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_SHIFT) + +/** + * @brief Get Virtual Target Capabilities Byte 2 (GETCAPS) Format 2 - + * Address Remapping. + */ +#define I3C_CCC_GETCAPS_VTCAP2_ADDRESS_REMAPPING BIT(2) + +/** Get Capabilities (GETCAPS) - VTCAP2 - Bus Context and Condition bit shift value. */ +#define I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_SHIFT 3 + +/** Get Capabilities (GETCAPS) - VTCAP2 - Bus Context and Condition bitmask. */ +#define I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_MASK \ + (0x03U << I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_SHIFT) + +/** + * @brief Get Capabilities (GETCAPS) - VTCAP2 - Bus Context and Condition + * + * Obtain Bus Context and Condition value from VTCAP2 value + * obtained via GETCAPS format 2 VTCAP def byte. + * + * @param vtcap2 VTCAP2 value. + */ +#define I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND(vtcap2) \ + (((vtcap2) & \ + I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_MASK) \ + >> I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_SHIFT) + /** * @brief Enum for I3C Reset Action (RSTACT) Defining Byte Values. */ @@ -1309,6 +1577,65 @@ static inline int i3c_ccc_do_getstatus_fmt2(const struct i3c_device_desc *target GETSTATUS_FORMAT_2, defbyte); } +/** + * @brief Single target GETCAPS to Get Target Status. + * + * Helper function to do GETCAPS (Get Capabilities) of + * one target. + * + * This should only be supported if Advanced Capabilities Bit of + * the BCR is set + * + * @param[in] target Pointer to the target device descriptor. + * @param[out] caps Pointer to GETCAPS payload. + * @param[in] fmt Which GETCAPS to use. + * @param[in] defbyte Defining Byte if using format 2. + * + * @return @see i3c_do_ccc + */ +int i3c_ccc_do_getcaps(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps, + enum i3c_ccc_getcaps_fmt fmt, + enum i3c_ccc_getcaps_defbyte defbyte); + +/** + * @brief Single target GETCAPS to Get Capabilities (Format 1). + * + * Helper function to do GETCAPS (Get Capabilities, format 1) of + * one target. + * + * @param[in] target Pointer to the target device descriptor. + * @param[out] caps Pointer to GETCAPS payload. + * + * @return @see i3c_do_ccc + */ +static inline int i3c_ccc_do_getcaps_fmt1(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps) +{ + return i3c_ccc_do_getcaps(target, caps, + GETCAPS_FORMAT_1, + GETCAPS_FORMAT_2_INVALID); +} + +/** + * @brief Single target GETCAPS to Get Capabilities (Format 2). + * + * Helper function to do GETCAPS (Get Capabilities, format 2) of + * one target. + * + * @param[in] target Pointer to the target device descriptor. + * @param[out] caps Pointer to GETCAPS payload. + * @param[in] defbyte Defining Byte for GETCAPS format 2. + * + * @return @see i3c_do_ccc + */ +static inline int i3c_ccc_do_getcaps_fmt2(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps, + enum i3c_ccc_getcaps_defbyte defbyte) +{ + return i3c_ccc_do_getcaps(target, caps, + GETCAPS_FORMAT_2, defbyte); +} #ifdef __cplusplus } From d11a48bb0c72f74cb62a816e7c70fb490900dc3c Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0833/1389] drivers: i3c: add reading GETCAPS in basic_info_get Add reading of GETCAPS CCC in `i3c_device_basic_info_get`. Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_common.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/i3c/i3c_common.c b/drivers/i3c/i3c_common.c index 93b30388da1a52..f58521bd483d92 100644 --- a/drivers/i3c/i3c_common.c +++ b/drivers/i3c/i3c_common.c @@ -512,6 +512,7 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target) struct i3c_ccc_getdcr dcr = {0}; struct i3c_ccc_mrl mrl = {0}; struct i3c_ccc_mwl mwl = {0}; + union i3c_ccc_getcaps caps = {0}; /* * Since some CCC functions requires BCR to function @@ -547,6 +548,21 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target) LOG_DBG("No settable limit for GETMWL"); } + /* GETCAPS */ + ret = i3c_ccc_do_getcaps_fmt1(target, &caps); + /* + * GETCAPS (GETHDRCAP) is required to be supported for I3C v1.0 targets that support HDR + * modes and required if the Target's I3C version is v1.1 or later, but which the version it + * supports it can't be known ahead of time. So if the BCR bit for Advanced capabilities is + * set, then it is expected for GETCAPS to always be supported. Otherwise, then it's a I3C + * v1.0 device without any HDR modes so do not treat as an error if no valid response. + */ + if (ret == 0) { + memcpy(&target->getcaps, &caps, sizeof(target->getcaps)); + } else if ((ret != 0) && (target->bcr & I3C_BCR_ADV_CAPABILITIES)) { + goto out; + } + target->dcr = dcr.dcr; target->data_length.mrl = mrl.len; target->data_length.mwl = mwl.len; From 1cdf9593ab310d71ea918e60a5db2e8d1b2b785e Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0834/1389] drivers: i3c: shell: add ccc getcaps command Add a shell command for the CCC GETCAPS Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_shell.c | 93 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/drivers/i3c/i3c_shell.c b/drivers/i3c/i3c_shell.c index d4f3269dff0951..9bfc72f954803e 100644 --- a/drivers/i3c/i3c_shell.c +++ b/drivers/i3c/i3c_shell.c @@ -217,7 +217,8 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) "\tmax_read_turnaround: 0x%08x\n" "\tmrl: 0x%04x\n" "\tmwl: 0x%04x\n" - "\tmax_ibi: 0x%02x", + "\tmax_ibi: 0x%02x\n" + "\tgetcaps: 0x%02x; 0x%02x; 0x%02x; 0x%02x", desc->dev->name, (uint64_t)desc->pid, desc->static_addr, desc->dynamic_addr, #if defined(CONFIG_I3C_USE_GROUP_ADDR) @@ -227,7 +228,9 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) desc->data_speed.maxwr, desc->data_speed.max_read_turnaround, desc->data_length.mrl, desc->data_length.mwl, - desc->data_length.max_ibi); + desc->data_length.max_ibi, + desc->getcaps.getcap1, desc->getcaps.getcap2, + desc->getcaps.getcap3, desc->getcaps.getcap4); found = true; break; } @@ -262,7 +265,8 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) "\tmax_read_turnaround: 0x%08x\n" "\tmrl: 0x%04x\n" "\tmwl: 0x%04x\n" - "\tmax_ibi: 0x%02x", + "\tmax_ibi: 0x%02x\n" + "\tgetcaps: 0x%02x; 0x%02x; 0x%02x; 0x%02x", desc->dev->name, (uint64_t)desc->pid, desc->static_addr, desc->dynamic_addr, #if defined(CONFIG_I3C_USE_GROUP_ADDR) @@ -272,7 +276,9 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) desc->data_speed.maxwr, desc->data_speed.max_read_turnaround, desc->data_length.mrl, desc->data_length.mwl, - desc->data_length.max_ibi); + desc->data_length.max_ibi, desc->getcaps.getcap1, + desc->getcaps.getcap2, desc->getcaps.getcap3, + desc->getcaps.getcap4); } } else { shell_print(shell_ctx, "I3C: No devices found."); @@ -1113,6 +1119,81 @@ static int cmd_i3c_ccc_getstatus(const struct shell *shell_ctx, size_t argc, cha return ret; } +/* i3c ccc getcaps [] */ +static int cmd_i3c_ccc_getcaps(const struct shell *shell_ctx, size_t argc, char **argv) +{ + const struct device *dev, *tdev; + struct i3c_device_desc *desc; + union i3c_ccc_getcaps caps; + enum i3c_ccc_getcaps_fmt fmt; + enum i3c_ccc_getcaps_defbyte defbyte = GETCAPS_FORMAT_2_INVALID; + int ret; + + dev = device_get_binding(argv[ARGV_DEV]); + if (!dev) { + shell_error(shell_ctx, "I3C: Device driver %s not found.", argv[ARGV_DEV]); + return -ENODEV; + } + tdev = device_get_binding(argv[ARGV_TDEV]); + if (!tdev) { + shell_error(shell_ctx, "I3C: Device driver %s not found.", argv[ARGV_TDEV]); + return -ENODEV; + } + desc = get_i3c_attached_desc_from_dev_name(dev, tdev->name); + if (!desc) { + shell_error(shell_ctx, "I3C: Device %s not attached to bus.", tdev->name); + return -ENODEV; + } + + if (!(desc->bcr & I3C_BCR_ADV_CAPABILITIES)) { + shell_error(shell_ctx, "I3C: Device %s does not support advanced capabilities", + desc->dev->name); + return -ENOTSUP; + } + + /* If there is a defining byte, then it is assumed to be Format 2 */ + if (argc > 3) { + fmt = GETCAPS_FORMAT_2; + defbyte = strtol(argv[3], NULL, 16); + if (defbyte != GETCAPS_FORMAT_2_TGTCAPS || defbyte != GETCAPS_FORMAT_2_TESTPAT || + defbyte != GETCAPS_FORMAT_2_CRCAPS || defbyte != GETCAPS_FORMAT_2_VTCAPS || + defbyte != GETCAPS_FORMAT_2_DBGCAPS) { + shell_error(shell_ctx, "Invalid defining byte."); + return -EINVAL; + } + } else { + fmt = GETCAPS_FORMAT_1; + } + + ret = i3c_ccc_do_getcaps(desc, &caps, fmt, defbyte); + if (ret < 0) { + shell_error(shell_ctx, "I3C: unable to send CCC GETCAPS."); + return ret; + } + + if (fmt == GETCAPS_FORMAT_2) { + if (defbyte == GETCAPS_FORMAT_2_TGTCAPS) { + shell_print(shell_ctx, "TGTCAPS: 0x%02x; 0x%02x; 0x%02x; 0x%02x", + caps.fmt2.tgtcaps[0], caps.fmt2.tgtcaps[1], + caps.fmt2.tgtcaps[2], caps.fmt2.tgtcaps[3]); + } else if (defbyte == GETCAPS_FORMAT_2_TESTPAT) { + shell_print(shell_ctx, "TESTPAT: 0x%08x", caps.fmt2.testpat); + } else if (defbyte == GETCAPS_FORMAT_2_CRCAPS) { + shell_print(shell_ctx, "CRCAPS: 0x%02x; 0x%02x", caps.fmt2.crcaps[0], + caps.fmt2.crcaps[1]); + } else if (defbyte == GETCAPS_FORMAT_2_VTCAPS) { + shell_print(shell_ctx, "VTCAPS: 0x%02x; 0x%02x", caps.fmt2.vtcaps[0], + caps.fmt2.vtcaps[1]); + } + } else { + shell_print(shell_ctx, "GETCAPS: 0x%02x; 0x%02x; 0x%02x; 0x%02x", + caps.fmt1.getcaps[0], caps.fmt1.getcaps[1], caps.fmt1.getcaps[2], + caps.fmt1.getcaps[3]); + } + + return ret; +} + static int cmd_i3c_attach(const struct shell *shell_ctx, size_t argc, char **argv) { const struct device *dev, *tdev; @@ -1383,6 +1464,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Send CCC GETSTATUS\n" "Usage: ccc getstatus []", cmd_i3c_ccc_getstatus, 3, 1), + SHELL_CMD_ARG(getcaps, &dsub_i3c_device_attached_name, + "Send CCC GETCAPS\n" + "Usage: ccc getcaps []", + cmd_i3c_ccc_getcaps, 3, 1), SHELL_SUBCMD_SET_END /* Array terminated. */ ); From c48fe608a2eb1223283f020fb97240a91e4fe553 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0835/1389] drivers: i3c: shell: fix argc length check for optional param GETSTATUS and GETMRL where not checking the right argc length. This corrects it to check for the right count. Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_shell.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i3c/i3c_shell.c b/drivers/i3c/i3c_shell.c index 9bfc72f954803e..8cd2c2b57e58bb 100644 --- a/drivers/i3c/i3c_shell.c +++ b/drivers/i3c/i3c_shell.c @@ -883,11 +883,11 @@ static int cmd_i3c_ccc_setmrl_bc(const struct shell *shell_ctx, size_t argc, cha } mrl.len = strtol(argv[2], NULL, 16); - if (argc > 2) { + if (argc > 3) { mrl.ibi_len = strtol(argv[3], NULL, 16); } - ret = i3c_ccc_do_setmrl_all(dev, &mrl, argc > 2); + ret = i3c_ccc_do_setmrl_all(dev, &mrl, argc > 3); if (ret < 0) { shell_error(shell_ctx, "I3C: unable to send CCC SETMRL BC."); return ret; @@ -1089,7 +1089,7 @@ static int cmd_i3c_ccc_getstatus(const struct shell *shell_ctx, size_t argc, cha } /* If there is a defining byte, then it is assumed to be Format 2*/ - if (argc > 2) { + if (argc > 3) { fmt = GETSTATUS_FORMAT_2; defbyte = strtol(argv[3], NULL, 16); if (defbyte != GETSTATUS_FORMAT_2_TGTSTAT || defbyte != GETSTATUS_FORMAT_2_PRECR) { From 9f636eeb74dfb7870c59a2a9b49e1dbdf4c9afb1 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0836/1389] drivers: i3c: cdns: handle variable length ccc with m0 err The CDNS will report a M0 error if the data length is not what it expects, but certain CCCs can have a variable length such as GETMXDS and GETCAPS. This sets it up to ignore the M0 error if it sees that ccc was GETMXDS or GETCAPS. Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_cdns.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/i3c/i3c_cdns.c b/drivers/i3c/i3c_cdns.c index ef361523e4e225..fab1df7f4abe4c 100644 --- a/drivers/i3c/i3c_cdns.c +++ b/drivers/i3c/i3c_cdns.c @@ -1350,9 +1350,42 @@ static void cdns_i3c_complete_transfer(const struct device *dev) } break; + case CMDR_M0_ERROR: { + uint8_t ccc = data->xfer.cmds[i].cmd1 & 0xFF; + /* + * The M0 is an illegally formatted CCC. i.e. the Controller + * receives 1 byte instead of 2 with the GETMWL CCC. This can + * be problematic for CCCs that can have variable length such + * as GETMXDS and GETCAPS. Verify the number of bytes received matches + * what's expected from the specification and ignore the error. The IP will + * still retramsit the same CCC and theres nothing that can be done to + * prevent this. It it still up to the application to read `num_xfer` to + * determine the number of bytes returned. + */ + if (ccc == I3C_CCC_GETMXDS) { + /* + * Whether GETMXDS format 1 and format 2 can't be known ahead of + * time which will be returned. + */ + if ((*data->xfer.cmds[i].num_xfer != + sizeof(((union i3c_ccc_getmxds *)0)->fmt1)) && + (*data->xfer.cmds[i].num_xfer != + sizeof(((union i3c_ccc_getmxds *)0)->fmt2))) { + ret = -EIO; + } + } else if (ccc == I3C_CCC_GETCAPS) { + /* GETCAPS can only return 1-4 bytes */ + if (*data->xfer.cmds[i].num_xfer > sizeof(union i3c_ccc_getcaps)) { + ret = -EIO; + } + } else { + ret = -EIO; + } + break; + } + case CMDR_DDR_PREAMBLE_ERROR: case CMDR_DDR_PARITY_ERROR: - case CMDR_M0_ERROR: case CMDR_M1_ERROR: case CMDR_M2_ERROR: case CMDR_NACK_RESP: From c962328bcd9dcf8fced69d84109fea1cfaca5116 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0837/1389] usb: device_next: prevent recursive logging loop Apply the commit 21975231e267 ("usb: device: cdc_acm: Prevent recursive logging loop") to the new CDC ACM implementation. Signed-off-by: Johann Fischer --- subsys/usb/device_next/class/usbd_cdc_acm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index b0be2cc6636d22..838550f18dd71a 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -21,6 +21,14 @@ #include "usbd_msg.h" #include +#if DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart) \ + && defined(CONFIG_USBD_CDC_ACM_LOG_LEVEL) \ + && CONFIG_USBD_CDC_ACM_LOG_LEVEL != LOG_LEVEL_NONE +/* Prevent endless recursive logging loop and warn user about it */ +#warning "USB_CDC_ACM_LOG_LEVEL forced to LOG_LEVEL_NONE" +#undef CONFIG_USBD_CDC_ACM_LOG_LEVEL +#define CONFIG_USBD_CDC_ACM_LOG_LEVEL LOG_LEVEL_NONE +#endif LOG_MODULE_REGISTER(usbd_cdc_acm, CONFIG_USBD_CDC_ACM_LOG_LEVEL); NET_BUF_POOL_FIXED_DEFINE(cdc_acm_ep_pool, From 009d233be4cd9d1fb975a066977b5bdae8b9f183 Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0838/1389] dts: mcxn947: Fix input key error Fix the compile error when input driver is enabled. Error message: In file included from zephyr/zephyr/include/zephyr/sys/util_macro.h:34, from zephyr/zephyr/include/zephyr/irq_multilevel.h:15, from zephyr/zephyr/include/zephyr/devicetree.h:20, from zephyr/zephyr/include/zephyr/device.h:12, from zephyr/zephyr/drivers/input/input_gpio_keys.c:9: zephyr/zephyr/include/zephyr/toolchain/gcc.h:87:36: error: static assertion failed: "zephyr-code must be specified to use the input-gpio-keys driver" Signed-off-by: Jason Yu --- boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi index e928f64ab33bc3..37e15451bc9f4a 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi @@ -6,6 +6,7 @@ #include "frdm_mcxn947-pinctrl.dtsi" #include +#include / { aliases{ @@ -41,11 +42,13 @@ user_button_2: button_0 { label = "User SW2"; gpios = <&gpio0 23 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; status = "disabled"; }; user_button_3: button_1 { label = "User SW3"; gpios = <&gpio0 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; status = "disabled"; }; }; From a5414de3be95ed1d027505d809e41510c0fce7e0 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0839/1389] MAINTAINERS: add arc qemu to Synopsys platform entry The ARC QEMU boards are maintained by Synopsys, so let's add boards/qemu/arc to Synopsys platform entry Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 2d464460eb59c3..821497ff6c0d66 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3153,6 +3153,7 @@ Synopsys Platforms: files: - soc/snps/ - boards/snps/ + - boards/qemu/arc/ - samples/boards/arc_secure_services/ - scripts/west_commands/runners/mdb.py - scripts/west_commands/tests/test_mdb.py From ad561846b14d1eb1298a03b788d72325105645f6 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0840/1389] doc: release-notes-3.7: Add CVE-2024-4785 Add CVE under embargo. Signed-off-by: Flavio Ceolin --- doc/releases/release-notes-3.7.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 47aee8764a590e..d4c2352b0755b2 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -29,6 +29,8 @@ https://docs.zephyrproject.org/latest/security/vulnerabilities.html * CVE-2024-3077 `Zephyr project bug tracker GHSA-gmfv-4vfh-2mh8 `_ +* CVE-2024-4785: Under embargo until 2024-08-07 + API Changes *********** From 1e224698435a3c31217443b75c27130674d42df1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0841/1389] doc: vuln: Add CVE under embargo Add an entry to CVE-2024-4785 Signed-off-by: Flavio Ceolin --- doc/security/vulnerabilities.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/security/vulnerabilities.rst b/doc/security/vulnerabilities.rst index 468098fa0cc06c..33ebd3f3d9b79b 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1713,3 +1713,8 @@ This has been fixed in main for v3.7.0 - `PR 69396 fix for main `_ + +CVE-2024-4785 +------------- + +Under embargo until 2024-08-07 From f0a8432ce0d1688feb3590a7e4bbf4be0d10d1d1 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0842/1389] dts: arm: nxp_rw610: Add OS_Timer Add OS Timer to device tree Signed-off-by: Declan Snyder --- dts/arm/nxp/nxp_rw6xx_common.dtsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index 22e34b4777ac12..b846950bc7b88c 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -362,7 +362,6 @@ }; }; - gau { ranges = <>; #address-cells = <1>; @@ -392,6 +391,13 @@ #io-channel-cells = <0>; }; }; + + os_timer: timers@13b000 { + compatible = "nxp,os-timer"; + reg = <0x13b000 0x1000>; + interrupts = <41 0>; + status = "disabled"; + }; }; &flexspi { From 53bc1094b2a0cccf2e56997543f8d1eb8a99c211 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0843/1389] soc: nxp: Enable support for OS Timer on RW platform The OS Timer will be used as the System Timer. Signed-off-by: Mahesh Mahadevan --- soc/nxp/rw/Kconfig.defconfig | 7 +++++++ soc/nxp/rw/soc.c | 4 ++++ soc/nxp/rw/soc.h | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/soc/nxp/rw/Kconfig.defconfig b/soc/nxp/rw/Kconfig.defconfig index 38bb0df74b7bca..aa62fea1460a90 100644 --- a/soc/nxp/rw/Kconfig.defconfig +++ b/soc/nxp/rw/Kconfig.defconfig @@ -9,6 +9,13 @@ config ROM_START_OFFSET config NUM_IRQS default 129 +if MCUX_OS_TIMER + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 1000000 + +endif # MCUX_OS_TIMER + if CORTEX_M_SYSTICK config SYS_CLOCK_HW_CYCLES_PER_SEC diff --git a/soc/nxp/rw/soc.c b/soc/nxp/rw/soc.c index dcf52c84377859..536d79b67ec6ae 100644 --- a/soc/nxp/rw/soc.c +++ b/soc/nxp/rw/soc.c @@ -138,6 +138,10 @@ __ramfunc void clock_init(void) /* Call function set_flexspi_clock() to set flexspi clock source to aux0_pll_clk in XIP. */ set_flexspi_clock(FLEXSPI, 2U, 2U); +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(os_timer), nxp_os_timer, okay) + CLOCK_AttachClk(kLPOSC_to_OSTIMER_CLK); +#endif + #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt), nxp_lpc_wwdt, okay)) CLOCK_AttachClk(kLPOSC_to_WDT0_CLK); #else diff --git a/soc/nxp/rw/soc.h b/soc/nxp/rw/soc.h index a9a28b3ab6e8e1..780bd9b66aad81 100644 --- a/soc/nxp/rw/soc.h +++ b/soc/nxp/rw/soc.h @@ -9,12 +9,18 @@ #ifndef _ASMLANGUAGE #include #include +#include "fsl_power.h" /* Add include for DTS generated information */ #include #endif /* !_ASMLANGUAGE */ +/* Wrapper Function to deal with SDK differences in power API */ +static inline void EnableDeepSleepIRQ(IRQn_Type irq) +{ + POWER_EnableWakeup(irq); +} #ifdef CONFIG_MEMC int flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate); From 5d07b471138e300b98259a876522780d166fd28f Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0844/1389] boards: rd_rw61x: Switch to OS Timer for System clock This clock is better suited for Power Management support than Systick. Signed-off-by: Mahesh Mahadevan --- boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi index 6216d381d037a9..3310e806608926 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi @@ -254,3 +254,13 @@ zephyr_udc0: &usb_otg { &dac0 { status = "okay"; }; + +/* OS Timer is the wakeup source for PM mode 2 */ +&os_timer { + status = "okay"; + wakeup-source; +}; + +&systick { + status = "disabled"; +}; From a1fd9d5a5736d154efc043bc121b93b1bddb0bdf Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0845/1389] dts: rw61x: Add Idle and Suspend power modes The Power states map to Power Mode 1 and 2. Signed-off-by: Mahesh Mahadevan --- dts/arm/nxp/nxp_rw6xx_common.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index b846950bc7b88c..ae4361e0d0dd47 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -19,6 +19,7 @@ cpus { #address-cells = <1>; #size-cells = <0>; + cpu-power-states = <&idle &suspend>; cpu0: cpu@0 { compatible = "arm,cortex-m33f"; @@ -31,6 +32,28 @@ reg = <0xe000ed90 0x40>; }; }; + + power-states { + /* Idle mode maps to Power Mode 1 */ + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <0>; + exit-latency-us = <0>; + }; + /* Suspend mode maps to Power Mode 2 */ + suspend: suspend { + compatible = "nxp,pdcfg-power", "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <500>; + exit-latency-us = <120>; + deep-sleep-config = <0x180000>, + <0x0>, + <0x4>, + <0x100>, + <0x0>; + }; + }; }; }; From a245ef6a8a09783f4092627710ca3cc715c1ad36 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0846/1389] soc: rw6xx: Add power management support Add support for Power modes 1 and 2. The wakeup from power mode 2 is from the os timer. Signed-off-by: Mahesh Mahadevan --- soc/nxp/rw/CMakeLists.txt | 4 ++ soc/nxp/rw/Kconfig | 1 + soc/nxp/rw/power.c | 77 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 soc/nxp/rw/power.c diff --git a/soc/nxp/rw/CMakeLists.txt b/soc/nxp/rw/CMakeLists.txt index d4c7cd7af4d33c..ace3c53eda847a 100644 --- a/soc/nxp/rw/CMakeLists.txt +++ b/soc/nxp/rw/CMakeLists.txt @@ -7,6 +7,10 @@ zephyr_sources( flexspi_clock_setup.c ) +zephyr_sources_ifdef(CONFIG_PM + power.c + ) + zephyr_linker_sources_ifdef(CONFIG_NXP_RW6XX_BOOT_HEADER ROM_START SORT_KEY 0 boot_header.ld) diff --git a/soc/nxp/rw/Kconfig b/soc/nxp/rw/Kconfig index 5951cf59ab2570..a072151a05c60d 100644 --- a/soc/nxp/rw/Kconfig +++ b/soc/nxp/rw/Kconfig @@ -17,6 +17,7 @@ config SOC_SERIES_RW6XX select HAS_MCUX_FLEXCOMM select INIT_SYS_PLL select HAS_MCUX_CACHE + select HAS_PM if SOC_SERIES_RW6XX diff --git a/soc/nxp/rw/power.c b/soc/nxp/rw/power.c new file mode 100644 index 00000000000000..69e9901f0d20b8 --- /dev/null +++ b/soc/nxp/rw/power.c @@ -0,0 +1,77 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#include "fsl_power.h" + +#include +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +/* Active mode */ +#define POWER_MODE0 0 +/* Idle mode */ +#define POWER_MODE1 1 +/* Standby mode */ +#define POWER_MODE2 2 +/* Sleep mode */ +#define POWER_MODE3 3 +/* Deep Sleep mode */ +#define POWER_MODE4 4 + +#define NODE_ID DT_INST(0, nxp_pdcfg_power) + +power_sleep_config_t slp_cfg; + +/* Invoke Low Power/System Off specific Tasks */ +__weak void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + + /* Set PRIMASK */ + __disable_irq(); + /* Set BASEPRI to 0 */ + irq_unlock(0); + + switch (state) { + case PM_STATE_RUNTIME_IDLE: + POWER_SetSleepMode(POWER_MODE1); + __WFI(); + break; + case PM_STATE_SUSPEND_TO_IDLE: + POWER_EnterPowerMode(POWER_MODE2, &slp_cfg); + break; + default: + LOG_DBG("Unsupported power state %u", state); + break; + } +} + +/* Handle SOC specific activity after Low Power Mode Exit */ +__weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(state); + ARG_UNUSED(substate_id); + + /* Clear PRIMASK */ + __enable_irq(); +} + +static int nxp_rw6xx_power_init(void) +{ + uint32_t suspend_sleepconfig[5] = DT_PROP_OR(NODE_ID, deep_sleep_config, {}); + + slp_cfg.pm2MemPuCfg = suspend_sleepconfig[0]; + slp_cfg.pm2AnaPuCfg = suspend_sleepconfig[1]; + slp_cfg.clkGate = suspend_sleepconfig[2]; + slp_cfg.memPdCfg = suspend_sleepconfig[3]; + slp_cfg.pm3BuckCfg = suspend_sleepconfig[4]; + + return 0; +} + +SYS_INIT(nxp_rw6xx_power_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From 659588eb55902558be2ba0cf65649c79bb9286d7 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:11 +0200 Subject: [PATCH 0847/1389] boards: rd_rw612: Update board documentation Add information about OS Timer and Power Management support. Signed-off-by: Mahesh Mahadevan --- boards/nxp/rd_rw612_bga/doc/index.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boards/nxp/rd_rw612_bga/doc/index.rst b/boards/nxp/rd_rw612_bga/doc/index.rst index dae43dd8aea778..42783abb9bbd8c 100644 --- a/boards/nxp/rd_rw612_bga/doc/index.rst +++ b/boards/nxp/rd_rw612_bga/doc/index.rst @@ -61,7 +61,11 @@ Supported Features +-----------+------------+-----------------------------------+ | MRT | on-chip | counter | +-----------+------------+-----------------------------------+ - +| OS_TIMER | on-chip | os timer | ++-----------+------------+-----------------------------------+ +| PM | on-chip | power management; uses SoC Power | +| | | Modes 1 and 2 | ++-----------+------------+-----------------------------------+ The default configuration can be found in the defconfig file: From 03840e1e8a5aa74b208a36d938ee2635b11be3e9 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0848/1389] tests: pm: power_mgmt_soc: enable testing on rd_rw612_bga Enable the SoC power management test suite on the NXP RW612 EVK development board. Signed-off-by: Mahesh Mahadevan --- tests/subsys/pm/power_mgmt_soc/testcase.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/subsys/pm/power_mgmt_soc/testcase.yaml b/tests/subsys/pm/power_mgmt_soc/testcase.yaml index 021a3416b9b5ea..203e44fbef1171 100644 --- a/tests/subsys/pm/power_mgmt_soc/testcase.yaml +++ b/tests/subsys/pm/power_mgmt_soc/testcase.yaml @@ -10,6 +10,7 @@ tests: - nucleo_l476rg - twr_ke18f - mimxrt595_evk/mimxrt595s/cm33 + - rd_rw612_bga tags: pm integration_platforms: - mec15xxevb_assy6853 From 5abd102b2d59bf516f462421101bb48f3813e756 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0849/1389] sd: sd_ops: take card lock when issuing IOCTL command Take card lock when running IOCTL command, to avoid race conditions that could occur within the lower SDHC transfer implementations (as these will be called by sdmmc_wait_ready) Fixes #72368 Signed-off-by: Daniel DeGrasse --- subsys/sd/sd_ops.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/subsys/sd/sd_ops.c b/subsys/sd/sd_ops.c index debf80f46551b4..54f5b1a360f145 100644 --- a/subsys/sd/sd_ops.c +++ b/subsys/sd/sd_ops.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -773,6 +773,13 @@ int card_write_blocks(struct sd_card *card, const uint8_t *wbuf, uint32_t start_ /* IO Control handler for SD MMC */ int card_ioctl(struct sd_card *card, uint8_t cmd, void *buf) { + int ret; + + ret = k_mutex_lock(&card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); + if (ret) { + LOG_WRN("Could not get SD card mutex"); + return ret; + } switch (cmd) { case DISK_IOCTL_GET_SECTOR_COUNT: (*(uint32_t *)buf) = card->block_count; @@ -786,9 +793,10 @@ int card_ioctl(struct sd_card *card, uint8_t cmd, void *buf) * Note that SD stack does not support enabling caching, so * cache flush is not required here */ - return sdmmc_wait_ready(card); + ret = sdmmc_wait_ready(card); default: - return -ENOTSUP; + ret = -ENOTSUP; } - return 0; + k_mutex_unlock(&card->lock); + return ret; } From bad01c817802eb05c4a4a452350cb0b2a729e209 Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0850/1389] drivers: wifi: esp32: remove pre-defined mbedTLS requirements In #72651, build fails due to conflict when enabling mbedTLS components. Current Wi-Fi implementation for ESP32 can discard those selected cryptos. Signed-off-by: Sylvio Alves --- drivers/wifi/esp32/Kconfig.esp32 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/wifi/esp32/Kconfig.esp32 b/drivers/wifi/esp32/Kconfig.esp32 index 2efbbba1ce5514..7760668b0bd216 100644 --- a/drivers/wifi/esp32/Kconfig.esp32 +++ b/drivers/wifi/esp32/Kconfig.esp32 @@ -9,12 +9,6 @@ menuconfig WIFI_ESP32 select NET_L2_WIFI_MGMT select WIFI_USE_NATIVE_NETWORKING select MBEDTLS - select MBEDTLS_ENTROPY_ENABLED - select MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - select MBEDTLS_ECP_ALL_ENABLED - select MBEDTLS_ECDH_C - select MBEDTLS_ECDSA_C - select MBEDTLS_ECP_C select THREAD_STACK_INFO select DYNAMIC_THREAD select DYNAMIC_THREAD_ALLOC From 312003edfab06aaf345b5a296dbb8347bdb639eb Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0851/1389] boards: st: sensortile_box_pro: fix usb console init Init should return errno value. Signed-off-by: Frederic Pillon --- boards/st/sensortile_box_pro/board.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/boards/st/sensortile_box_pro/board.c b/boards/st/sensortile_box_pro/board.c index b66edf23be48d5..c19d0abe3da6e3 100644 --- a/boards/st/sensortile_box_pro/board.c +++ b/boards/st/sensortile_box_pro/board.c @@ -20,11 +20,10 @@ static int sensortile_box_pro_usb_console_init(void) { const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); - if (!device_is_ready(dev) || usb_enable(NULL)) { - return -1; + if (!device_is_ready(dev)) { + return -ENODEV; } - - return 0; + return usb_enable(NULL); } /* needs to be done at Application */ From 1de49c06970352179fbb2cde68eff3df79ec3d6d Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0852/1389] drivers: entropy: smartbond: Bug fix This commit should fix few wrong expressions Signed-off-by: Ioannis Karachalios --- drivers/entropy/entropy_smartbond.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/entropy/entropy_smartbond.c b/drivers/entropy/entropy_smartbond.c index 0b42f77f4f8fc8..80f9ef1510c5d3 100644 --- a/drivers/entropy/entropy_smartbond.c +++ b/drivers/entropy/entropy_smartbond.c @@ -317,11 +317,11 @@ static int entropy_smartbond_get_entropy_isr(const struct device *dev, uint8_t * } NVIC_ClearPendingIRQ(IRQN); - if (random_word_get(buf) != 0) { + if (random_word_get(bytes) != 0) { continue; } - while (ptr < limit) { + while (ptr < limit && len) { buf[--len] = *ptr++; } /* Store remaining data for later use */ From 5c1b44f1c6b17d43a95bb5576a93b8670170586f Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0853/1389] sensor: voltage_divider: fix `power-gpio` `CONFIG_PM_DEVICE` being disabled does not mean that the `power-gpio` does not need to be controlled. Additionally, not having a `power-gpio` property does not mean that power management is not supported, just that is has no work to do. Signed-off-by: Jordan Yates --- drivers/sensor/voltage_divider/voltage.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/sensor/voltage_divider/voltage.c b/drivers/sensor/voltage_divider/voltage.c index ef2b34c74b3163..47569b005d58db 100644 --- a/drivers/sensor/voltage_divider/voltage.c +++ b/drivers/sensor/voltage_divider/voltage.c @@ -17,9 +17,7 @@ LOG_MODULE_REGISTER(voltage, CONFIG_SENSOR_LOG_LEVEL); struct voltage_config { struct voltage_divider_dt_spec voltage; -#ifdef CONFIG_PM_DEVICE struct gpio_dt_spec gpio_power; -#endif }; struct voltage_data { @@ -90,8 +88,8 @@ static int pm_action(const struct device *dev, enum pm_device_action action) int ret; if (config->gpio_power.port == NULL) { - LOG_ERR("PM not supported"); - return -ENOTSUP; + /* No work to do */ + return 0; } switch (action) { @@ -126,7 +124,6 @@ static int voltage_init(const struct device *dev) return -ENODEV; } -#ifdef CONFIG_PM_DEVICE if (config->gpio_power.port != NULL) { if (!gpio_is_ready_dt(&config->gpio_power)) { LOG_ERR("Power GPIO is not ready"); @@ -138,7 +135,6 @@ static int voltage_init(const struct device *dev) LOG_ERR("failed to initialize GPIO for reset"); } } -#endif ret = adc_channel_setup_dt(&config->voltage.port); if (ret != 0) { @@ -158,18 +154,12 @@ static int voltage_init(const struct device *dev) return 0; } -#ifdef CONFIG_PM_DEVICE -#define POWER_GPIOS(inst) .gpio_power = GPIO_DT_SPEC_INST_GET_OR(inst, power_gpios, {0}), -#else -#define POWER_GPIOS(inst) -#endif - #define VOLTAGE_INIT(inst) \ static struct voltage_data voltage_##inst##_data; \ \ static const struct voltage_config voltage_##inst##_config = { \ .voltage = VOLTAGE_DIVIDER_DT_SPEC_GET(DT_DRV_INST(inst)), \ - POWER_GPIOS(inst) \ + .gpio_power = GPIO_DT_SPEC_INST_GET_OR(inst, power_gpios, {0}), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ From 8a9d4bdf8aad99f84f09f7a06726d3d2b32e23c6 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0854/1389] tests/kernel timer_api: Test absolute timers with loosing ticks Let's also explicitly test that absolute timeouts trigger at the correct time, even if the kernel has not seen system clock timer announcements for a while. Signed-off-by: Alberto Escolar Piedras --- tests/kernel/timer/timer_api/src/main.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/kernel/timer/timer_api/src/main.c b/tests/kernel/timer/timer_api/src/main.c index 58836c2ba9b980..ba9a76d4085a10 100644 --- a/tests/kernel/timer/timer_api/src/main.c +++ b/tests/kernel/timer/timer_api/src/main.c @@ -803,10 +803,30 @@ ZTEST_USER(timer_api, test_sleep_abs) * time slop or more depending on the time to resume */ k_ticks_t late = end - (start + sleep_ticks); + int slop = MAX(2, k_us_to_ticks_ceil32(250)); - zassert_true(late >= 0 && late <= MAX(2, k_us_to_ticks_ceil32(250)), + zassert_true(late >= 0 && late <= slop, "expected wakeup at %lld, got %lld (late %lld)", start + sleep_ticks, end, late); + + /* Let's test that an absolute delay awakes at the correct time + * even if the system did not get some ticks announcements + */ + int tickless_wait = 5; + + start = end; + k_busy_wait(k_ticks_to_us_ceil32(tickless_wait)); + /* We expect to not have got tick announcements, + * as there is currently nothing scheduled + */ + k_sleep(K_TIMEOUT_ABS_TICKS(start + sleep_ticks)); + end = k_uptime_ticks(); + late = end - (start + sleep_ticks); + + zassert_true(late >= 0 && late <= slop, + "expected wakeup at %lld, got %lld (late %lld)", + start + sleep_ticks, end, late); + } static void timer_init(struct k_timer *timer, k_timer_expiry_t expiry_fn, From bcced412a72658566b5905596ea1b55e2ce50bd5 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0855/1389] drivers: flash: flash_mcux_flexspi_nor: better handle legacy SFDP tables Implement more robust handling for legacy SFDP tables, which may not implement some of the JEDEC defined DWORDS for SFDP data. Instead of failing to probe/initialize the flash when these DWORDS are not defined in the basic flash parameter table, revert to sane defaults for SPI flash. Fixes #72051 Signed-off-by: Daniel DeGrasse --- drivers/flash/flash_mcux_flexspi_nor.c | 61 ++++++++++++++------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/flash/flash_mcux_flexspi_nor.c b/drivers/flash/flash_mcux_flexspi_nor.c index d072f25f9246c4..175e75554f24a4 100644 --- a/drivers/flash/flash_mcux_flexspi_nor.c +++ b/drivers/flash/flash_mcux_flexspi_nor.c @@ -720,22 +720,23 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data, /* Check to see if we can enable 4 byte addressing */ ret = jesd216_bfp_decode_dw16(&header->phdr[0], bfp, &dw16); - if (ret < 0) { - return ret; - } - - /* Attempt to enable 4 byte addressing */ - ret = flash_flexspi_nor_4byte_enable(data, flexspi_lut, dw16.enter_4ba); if (ret == 0) { - /* Use 4 byte address width */ - addr_width = 32; - /* Update LUT for ERASE_SECTOR and ERASE_BLOCK to use 32 bit addr */ - flexspi_lut[ERASE_SECTOR][0] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_SE, - kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, addr_width); - flexspi_lut[ERASE_BLOCK][0] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_BE, - kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, addr_width); + /* Attempt to enable 4 byte addressing */ + ret = flash_flexspi_nor_4byte_enable(data, flexspi_lut, + dw16.enter_4ba); + if (ret == 0) { + /* Use 4 byte address width */ + addr_width = 32; + /* Update LUT for ERASE_SECTOR and ERASE_BLOCK to use 32 bit addr */ + flexspi_lut[ERASE_SECTOR][0] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, + SPI_NOR_CMD_SE, kFLEXSPI_Command_RADDR_SDR, + kFLEXSPI_1PAD, addr_width); + flexspi_lut[ERASE_BLOCK][0] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, + SPI_NOR_CMD_BE, kFLEXSPI_Command_RADDR_SDR, + kFLEXSPI_1PAD, addr_width); + } } /* Extract the read command. * Note- enhanced XIP not currently supported, nor is 4-4-4 mode. @@ -766,20 +767,21 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0); /* Read 1S-4S-4S enable method */ ret = jesd216_bfp_decode_dw15(&header->phdr[0], bfp, &dw15); - if (ret < 0) { - return ret; - } - ret = flash_flexspi_nor_quad_enable(data, flexspi_lut, dw15.qer); - if (ret < 0) { - return ret; + if (ret == 0) { + ret = flash_flexspi_nor_quad_enable(data, flexspi_lut, + dw15.qer); + if (ret == 0) { + /* Now, install 1S-1S-4S page program command */ + flexspi_lut[PAGE_PROGRAM][0] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, + SPI_NOR_CMD_PP_1_1_4, kFLEXSPI_Command_RADDR_SDR, + kFLEXSPI_1PAD, addr_width); + flexspi_lut[PAGE_PROGRAM][1] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, + 0x4, kFLEXSPI_Command_STOP, + kFLEXSPI_1PAD, 0x0); + } } - /* Now, install 1S-1S-4S page program command */ - flexspi_lut[PAGE_PROGRAM][0] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_PP_1_1_4, - kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, addr_width); - flexspi_lut[PAGE_PROGRAM][1] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x4, - kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0); } else if (jesd216_bfp_read_support(&header->phdr[0], bfp, JESD216_MODE_122, &instr) > 0) { @@ -819,7 +821,8 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data, /* Now, read DW14 to determine the polling method we should use while programming */ ret = jesd216_bfp_decode_dw14(&header->phdr[0], bfp, &dw14); if (ret < 0) { - return ret; + /* Default to legacy polling mode */ + dw14.poll_options = 0x0; } if (dw14.poll_options & BIT(1)) { /* Read instruction used for polling is 0x70 */ From edb2aa6b433f653df20dda57cb8ac0d18bde6ce1 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0856/1389] west.yml: MCUboot synchronization from upstream Update Zephyr fork of MCUboot to revision: 018dc01d484358d81f889c36471d9ce5590965b6 Brings following Zephyr relevant fixes: - 018dc01d boot/zephyr: use socs conf - d4394c2f mbedtls config: fix too early check_config.h includes Signed-off-by: Jamie McCrae --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 05d9717db8355f..6673d1f65f72c1 100644 --- a/west.yml +++ b/west.yml @@ -282,7 +282,7 @@ manifest: groups: - crypto - name: mcuboot - revision: d4394c2f9b76e0a7b758441cea3a8ceb896f66c8 + revision: 018dc01d484358d81f889c36471d9ce5590965b6 path: bootloader/mcuboot - name: mipi-sys-t path: modules/debug/mipi-sys-t From a2dc5fd318e57064a75be17072fe2c91cb88c567 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0857/1389] drivers: sensor: add Innovative Sensor Technology TSic xx6 driver Add driver for TSic 206/306/316/506F/516/716 temperature sensor. The driver uses PWM capture driver to read a single wire with Manchester-like encoding. Signed-off-by: Jeppe Odgaard --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 1 + drivers/sensor/tsic_xx6/CMakeLists.txt | 5 + drivers/sensor/tsic_xx6/Kconfig | 11 + drivers/sensor/tsic_xx6/tsic_xx6.c | 284 +++++++++++++++++++++++++ dts/bindings/sensor/ist,tsic-xx6.yaml | 40 ++++ dts/bindings/vendor-prefixes.txt | 1 + 7 files changed, 343 insertions(+) create mode 100644 drivers/sensor/tsic_xx6/CMakeLists.txt create mode 100644 drivers/sensor/tsic_xx6/Kconfig create mode 100644 drivers/sensor/tsic_xx6/tsic_xx6.c create mode 100644 dts/bindings/sensor/ist,tsic-xx6.yaml diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 2a952bb2614ed3..0c1ec766321d41 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -61,6 +61,7 @@ add_subdirectory_ifdef(CONFIG_S11059 s11059) add_subdirectory_ifdef(CONFIG_SBS_GAUGE sbs_gauge) add_subdirectory_ifdef(CONFIG_SX9500 sx9500) add_subdirectory_ifdef(CONFIG_TH02 th02) +add_subdirectory_ifdef(CONFIG_TSIC_XX6 tsic_xx6) add_subdirectory_ifdef(CONFIG_VOLTAGE_DIVIDER voltage_divider) add_subdirectory_ifdef(CONFIG_TACH_ENE_KB1200 ene_tach_kb1200) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 3636641cb7a97e..5f264cc05c1292 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -142,6 +142,7 @@ source "drivers/sensor/s11059/Kconfig" source "drivers/sensor/sbs_gauge/Kconfig" source "drivers/sensor/sx9500/Kconfig" source "drivers/sensor/th02/Kconfig" +source "drivers/sensor/tsic_xx6/Kconfig" source "drivers/sensor/voltage_divider/Kconfig" source "drivers/sensor/ene_tach_kb1200/Kconfig" diff --git a/drivers/sensor/tsic_xx6/CMakeLists.txt b/drivers/sensor/tsic_xx6/CMakeLists.txt new file mode 100644 index 00000000000000..968d4cfe796bd6 --- /dev/null +++ b/drivers/sensor/tsic_xx6/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_TSIC_XX6 tsic_xx6.c) diff --git a/drivers/sensor/tsic_xx6/Kconfig b/drivers/sensor/tsic_xx6/Kconfig new file mode 100644 index 00000000000000..761eae1d963632 --- /dev/null +++ b/drivers/sensor/tsic_xx6/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +config TSIC_XX6 + bool "TSic xx6 driver" + default y + depends on DT_HAS_IST_TSIC_XX6_ENABLED + select PWM + select PWM_CAPTURE + help + Enable driver for TSic 206/306/316/506F/516/716. diff --git a/drivers/sensor/tsic_xx6/tsic_xx6.c b/drivers/sensor/tsic_xx6/tsic_xx6.c new file mode 100644 index 00000000000000..5470394a49ff9f --- /dev/null +++ b/drivers/sensor/tsic_xx6/tsic_xx6.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2024, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ist_tsic_xx6 + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(TSIC_XX6, CONFIG_SENSOR_LOG_LEVEL); + +#define FRAME_BIT_PERIOD_US 125 + +enum { + FRAME_PARITIY_BIT_LSB, + FRAME_DATA_BIT_0, + FRAME_DATA_BIT_1, + FRAME_DATA_BIT_2, + FRAME_DATA_BIT_3, + FRAME_DATA_BIT_4, + FRAME_DATA_BIT_5, + FRAME_DATA_BIT_6, + FRAME_DATA_BIT_7, + FRAME_START_BIT_LSB, + /* Theres a single bit period between the two packets that is constant high. This bit will + * be part of the 2nd packet's start bit thus frame length is not affected. + */ + FRAME_PARITIY_BIT_MSB, + FRAME_DATA_BIT_8, + FRAME_DATA_BIT_9, + FRAME_DATA_BIT_10, + FRAME_DATA_BIT_11, + FRAME_DATA_BIT_12, + FRAME_DATA_BIT_13, + FRAME_ZERO_BIT_0, + FRAME_ZERO_BIT_1, + FRAME_START_BIT_MSB, + FRAME_READY_BIT, + FRAME_FLAGS, +}; + +struct tsic_xx6_config { + const struct pwm_dt_spec pwm; + const int8_t lower_temperature_limit; + const uint8_t higher_temperature_limit; + const uint8_t data_bits; +}; + +struct tsic_xx6_data { + uint64_t frame_cycles; + struct sensor_value val; + + ATOMIC_DEFINE(frame, FRAME_FLAGS); + uint32_t buf; + uint8_t buf_index; +}; + +static inline void tsic_xx6_buf_reset(struct tsic_xx6_data *data) +{ + data->buf_index = FRAME_START_BIT_MSB; +} + +static inline bool tsic_xx6_is_buf_reset(struct tsic_xx6_data *data) +{ + return data->buf_index == FRAME_START_BIT_MSB; +} + +static inline bool tsic_xx6_is_data_line_idle(struct tsic_xx6_data *data, uint64_t period_cycles) +{ + /* If the period is larger than two frames assume the data line has been idle */ + return period_cycles > data->frame_cycles * 2; +} + +static void tsic_xx6_pwm_callback(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, int status, + void *user_data) +{ + const struct device *tsic_xx6_dev = user_data; + const struct tsic_xx6_config *config = tsic_xx6_dev->config; + struct tsic_xx6_data *data = tsic_xx6_dev->data; + uint32_t low_cycles; + bool val; + + if (dev != config->pwm.dev || channel != config->pwm.channel) { + return; + } + + if (status != 0) { + LOG_ERR("callback failed: %d", status); + return; + } + + if (!tsic_xx6_is_buf_reset(data) && tsic_xx6_is_data_line_idle(data, period_cycles)) { + LOG_ERR("unexpected data idle"); + tsic_xx6_buf_reset(data); + } + + /* + * Calculate low cycles: The sensor sends the pulse in the last part of the period. The PWM + * capture driver triggers on rising edge with normal polarity. Therefore only the low part + * of the frame bit is present. + */ + low_cycles = period_cycles - pulse_cycles; + + /* 25 % duty cycle is 0, 75 % duty cycle is 1 */ + val = low_cycles * 2 < data->frame_cycles; + WRITE_BIT(data->buf, data->buf_index, val); + + if (data->buf_index > 0) { + --data->buf_index; + } else { + WRITE_BIT(data->buf, FRAME_READY_BIT, 1); + (void)atomic_set(data->frame, data->buf); + tsic_xx6_buf_reset(data); + } +} + +static inline bool tsic_xx6_parity_check(uint8_t data, bool parity) +{ + bool data_parity = false; + size_t i; + + for (i = 0; i < 8; ++i) { + data_parity ^= FIELD_GET(BIT(i), data); + } + + return (parity ^ data_parity) == 0; +} + +static int tsic_xx6_get_data_bits(const struct tsic_xx6_config *config, uint16_t *data_bits, + uint32_t frame) +{ + uint8_t frame_data_bit_high = + config->data_bits == 14 ? FRAME_DATA_BIT_13 : FRAME_DATA_BIT_10; + uint8_t data_msb = FIELD_GET(GENMASK(frame_data_bit_high, FRAME_DATA_BIT_8), frame); + uint8_t data_lsb = FIELD_GET(GENMASK(FRAME_DATA_BIT_7, FRAME_DATA_BIT_0), frame); + bool parity_msb = FIELD_GET(BIT(FRAME_PARITIY_BIT_MSB), frame); + bool parity_lsb = BIT(FRAME_PARITIY_BIT_LSB) & frame; + + if (!tsic_xx6_parity_check(data_msb, parity_msb) || + !tsic_xx6_parity_check(data_lsb, parity_lsb)) { + return -EIO; + } + + *data_bits = data_msb << 8 | data_lsb; + + return 0; +} + +static void tsic_xx6_get_value(const struct tsic_xx6_config *config, struct tsic_xx6_data *data, + uint16_t data_bits) +{ + int64_t tmp; + + /* Apply the datasheet formula scaled to micro celcius */ + tmp = data_bits * (config->higher_temperature_limit - config->lower_temperature_limit); + tmp = tmp * 1000000 / (BIT(config->data_bits) - 1); + tmp += (int64_t)config->lower_temperature_limit * 1000000; + + data->val.val1 = tmp / 1000000; + data->val.val2 = tmp % 1000000; +} + +static int tsic_xx6_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct tsic_xx6_config *config = dev->config; + struct tsic_xx6_data *data = dev->data; + uint32_t frame; + uint16_t data_bits; + int rc; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + frame = atomic_and(data->frame, ~BIT(FRAME_READY_BIT)); + + if (FIELD_GET(BIT(FRAME_READY_BIT), frame) == 0) { + return -EBUSY; + } + + rc = tsic_xx6_get_data_bits(config, &data_bits, frame); + if (rc != 0) { + return rc; + } + + tsic_xx6_get_value(config, data, data_bits); + + return 0; +} + +static int tsic_xx6_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct tsic_xx6_data *data = dev->data; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + *val = data->val; + + return 0; +} + +static const struct sensor_driver_api tsic_xx6_driver_api = {.sample_fetch = tsic_xx6_sample_fetch, + .channel_get = tsic_xx6_channel_get}; + +static int tsic_xx6_get_frame_cycles(const struct tsic_xx6_config *config, uint64_t *frame_cycles) +{ + uint64_t tmp; + int rc; + + rc = pwm_get_cycles_per_sec(config->pwm.dev, config->pwm.channel, &tmp); + if (rc != 0) { + return rc; + } + + if (u64_mul_overflow(tmp, FRAME_BIT_PERIOD_US, &tmp)) { + return -ERANGE; + } + + *frame_cycles = tmp / USEC_PER_SEC; + + return 0; +} + +static int tsic_xx6_init(const struct device *dev) +{ + const struct tsic_xx6_config *config = dev->config; + struct tsic_xx6_data *data = dev->data; + int rc; + + if (!pwm_is_ready_dt(&config->pwm)) { + return -ENODEV; + } + + rc = tsic_xx6_get_frame_cycles(config, &data->frame_cycles); + if (rc != 0) { + return rc; + } + + rc = pwm_configure_capture(config->pwm.dev, config->pwm.channel, + config->pwm.flags | PWM_CAPTURE_TYPE_BOTH | + PWM_CAPTURE_MODE_CONTINUOUS, + tsic_xx6_pwm_callback, (void *)dev); + if (rc != 0) { + return rc; + } + + tsic_xx6_buf_reset(data); + + rc = pwm_enable_capture(config->pwm.dev, config->pwm.channel); + if (rc != 0) { + return rc; + } + + return 0; +} + +#define TSIC_XX6_DEVICE(n) \ + \ + static struct tsic_xx6_data tsic_xx6_data_##n; \ + \ + static const struct tsic_xx6_config tsic_xx6_config_##n = { \ + .pwm = PWM_DT_SPEC_INST_GET(n), \ + .lower_temperature_limit = (int8_t)DT_INST_PROP(n, lower_temperature_limit), \ + .higher_temperature_limit = DT_INST_PROP(n, higher_temperature_limit), \ + .data_bits = DT_INST_PROP(n, data_bits), \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, &tsic_xx6_init, NULL, &tsic_xx6_data_##n, \ + &tsic_xx6_config_##n, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &tsic_xx6_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TSIC_XX6_DEVICE) diff --git a/dts/bindings/sensor/ist,tsic-xx6.yaml b/dts/bindings/sensor/ist,tsic-xx6.yaml new file mode 100644 index 00000000000000..d6ee88b8079b7d --- /dev/null +++ b/dts/bindings/sensor/ist,tsic-xx6.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024, Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +description: | + TSic xx6 temperature sensor. + https://www.ist-ag.com/sites/default/files/downloads/ATTSic_E.pdf + + Example: + tsic_716: tsic_716 { + status = "okay"; + compatible = "ist,tsic-xx6"; + pwms = <&pwm2 1 PWM_USEC(5) PWM_POLARITY_NORMAL>; + data-bits = <14>; + lower-temperature-limit = <(-10)>; + higher-temperature-limit = <60>; + }; + +compatible: "ist,tsic-xx6" + +properties: + pwms: + required: true + type: phandle-array + description: Reference to a PWM instance with PWM capture support. + + lower-temperature-limit: + required: true + type: int + description: Lowest temperature supported by the device in celcius degrees. + + higher-temperature-limit: + required: true + type: int + description: Highest temperature supported by the device in celcius degrees. + + data-bits: + required: true + type: int + description: Data bits per reading. + enum: [11, 14] diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 93970fd70a79a4..a6121e34194f6e 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -321,6 +321,7 @@ isee ISEE 2007 S.L. isentek Isentek Inc. isil Intersil issi Integrated Silicon Solutions Inc. +ist Innovative Sensor Technology IST AG ite ITE Tech. Inc. itead ITEAD Intelligent Systems Co.Ltd ivo InfoVision Optoelectronics Kunshan Co. Ltd. From 680e9b29b7fd75cbe7dad411e7582a5fe43895fe Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0858/1389] tests: drivers: build_all: sensor: add tsic_xx6 Enable PWM and PWM_CAPTURE in conf and add pwm node to app.overlay. Add TSic xx6 node to pwm.dtsi. Signed-off-by: Jeppe Odgaard --- tests/drivers/build_all/sensor/app.overlay | 9 +++++++++ tests/drivers/build_all/sensor/prj.conf | 2 ++ tests/drivers/build_all/sensor/pwm.dtsi | 16 ++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 tests/drivers/build_all/sensor/pwm.dtsi diff --git a/tests/drivers/build_all/sensor/app.overlay b/tests/drivers/build_all/sensor/app.overlay index aec784c26888e1..ebfa224848a32f 100644 --- a/tests/drivers/build_all/sensor/app.overlay +++ b/tests/drivers/build_all/sensor/app.overlay @@ -74,6 +74,15 @@ #include "i2c.dtsi" }; + test_pwm: pwm@12341234 { + compatible = "vnd,pwm"; + reg = <0x12341234 0x1000>; + #pwm-cells = <3>; + status = "okay"; + + #include "pwm.dtsi" + }; + test_spi: spi@33334444 { #address-cells = <1>; #size-cells = <0>; diff --git a/tests/drivers/build_all/sensor/prj.conf b/tests/drivers/build_all/sensor/prj.conf index fe677345578bf1..2fb7bedcac8d6d 100644 --- a/tests/drivers/build_all/sensor/prj.conf +++ b/tests/drivers/build_all/sensor/prj.conf @@ -7,6 +7,8 @@ CONFIG_ADC=y CONFIG_GPIO=y CONFIG_I2C=y CONFIG_I3C=y +CONFIG_PWM=y +CONFIG_PWM_CAPTURE=y CONFIG_SERIAL=y CONFIG_SPI=y CONFIG_MFD=y diff --git a/tests/drivers/build_all/sensor/pwm.dtsi b/tests/drivers/build_all/sensor/pwm.dtsi new file mode 100644 index 00000000000000..e1b1ec978a9861 --- /dev/null +++ b/tests/drivers/build_all/sensor/pwm.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for pwm devices + */ + +test_pwm_tsic_xx6: tsic_xx6 { + status = "okay"; + compatible = "ist,tsic-xx6"; + pwms = <&test_pwm 0 0 0>; + data-bits = <14>; + lower-temperature-limit = <(-100)>; + higher-temperature-limit = <250>; +}; From a3a0ce0c4bac7403493c08dcffa31c8031684f3c Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0859/1389] west.yml: Update revision for hal_renesas Pull changes required for CMAC driver. Signed-off-by: Andrzej Kaczmarek --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 6673d1f65f72c1..091f6ac35a47b0 100644 --- a/west.yml +++ b/west.yml @@ -210,7 +210,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: e3560c79db1a002014f061c611cd84a99e4f33de + revision: 8390c9da4d76656934ea135c757ba946bccd736c groups: - hal - name: hal_rpi_pico From dcab890ad03ce1036d2764510929495a70a9d0d7 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0860/1389] drivers: hci: da1469x: Add driver for CMAC core on DA1469x This adds HCI driver which enables communication with CMAC core on Renesas SmartBond DA1469x series. The CMAC core is running an Apache NimBLE controller binary and uses shared memory for communcation via mailboxes. Signed-off-by: Andrzej Kaczmarek --- drivers/bluetooth/hci/CMakeLists.txt | 1 + drivers/bluetooth/hci/Kconfig | 6 + drivers/bluetooth/hci/hci_da1469x.c | 489 +++++++++++++++++++++++++++ 3 files changed, 496 insertions(+) create mode 100644 drivers/bluetooth/hci/hci_da1469x.c diff --git a/drivers/bluetooth/hci/CMakeLists.txt b/drivers/bluetooth/hci/CMakeLists.txt index adda6ea0e2ab05..ab1df047ce11dc 100644 --- a/drivers/bluetooth/hci/CMakeLists.txt +++ b/drivers/bluetooth/hci/CMakeLists.txt @@ -33,3 +33,4 @@ zephyr_library_sources_ifdef(CONFIG_BT_SILABS_HCI slz_hci.c) zephyr_library_sources_ifdef(CONFIG_BT_PSOC6_BLESS hci_psoc6_bless.c) zephyr_library_sources_ifdef(CONFIG_SOC_NRF5340_CPUAPP nrf53_support.c) zephyr_library_sources_ifdef(CONFIG_BT_AMBIQ_HCI hci_ambiq.c apollox_blue.c) +zephyr_library_sources_ifdef(CONFIG_BT_DA1469X hci_da1469x.c) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index ad1d9da2df2a64..1b4bc9fdb25d0c 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -109,6 +109,12 @@ config BT_PSOC6_BLESS PSOC6 BLESS driver with BLE Controller which operates in Single CPU mode. +config BT_DA1469X + bool "DA1469x HCI driver" + help + Bluetooth HCI driver for communication with CMAC core + on DA1469x MCU. + config BT_NO_DRIVER bool "No default HCI driver" select BT_HAS_HCI_VS diff --git a/drivers/bluetooth/hci/hci_da1469x.c b/drivers/bluetooth/hci/hci_da1469x.c new file mode 100644 index 00000000000000..8935244472a954 --- /dev/null +++ b/drivers/bluetooth/hci/hci_da1469x.c @@ -0,0 +1,489 @@ +/* hci_da1469x.c - DA1469x CMAC IPC Bluetooth driver */ + +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include + +LOG_MODULE_REGISTER(hci_da1469x); + +static K_KERNEL_STACK_DEFINE(rng_thread_stack, CONFIG_BT_RX_STACK_SIZE); +static struct k_thread rng_thread_data; +struct k_sem rng_sem; + +static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_RX_STACK_SIZE); +static struct k_thread rx_thread_data; + +static struct { + struct net_buf *buf; + struct k_fifo fifo; + + uint16_t remaining; + uint16_t discard; + + bool have_hdr; + bool discardable; + + uint8_t hdr_len; + + uint8_t type; + union { + struct bt_hci_evt_hdr evt; + struct bt_hci_acl_hdr acl; + struct bt_hci_iso_hdr iso; + uint8_t hdr[4]; + }; +} rx = { + .fifo = Z_FIFO_INITIALIZER(rx.fifo), +}; + +static void h4_get_type(void) +{ + /* Get packet type */ + if (cmac_mbox_read(&rx.type, 1) != 1) { + LOG_WRN("Unable to read H:4 packet type"); + rx.type = BT_HCI_H4_NONE; + return; + } + + switch (rx.type) { + case BT_HCI_H4_EVT: + rx.remaining = sizeof(rx.evt); + rx.hdr_len = rx.remaining; + break; + case BT_HCI_H4_ACL: + rx.remaining = sizeof(rx.acl); + rx.hdr_len = rx.remaining; + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + rx.remaining = sizeof(rx.iso); + rx.hdr_len = rx.remaining; + break; + } + __fallthrough; + default: + LOG_ERR("Unknown H:4 type 0x%02x", rx.type); + rx.type = BT_HCI_H4_NONE; + } +} + +static void h4_read_hdr(void) +{ + int bytes_read = rx.hdr_len - rx.remaining; + int ret; + + ret = cmac_mbox_read(rx.hdr + bytes_read, rx.remaining); + if (unlikely(ret < 0)) { + LOG_ERR("Unable to read from mailbox (ret %d)", ret); + } else { + rx.remaining -= ret; + } +} + +static inline void get_acl_hdr(void) +{ + h4_read_hdr(); + + if (!rx.remaining) { + struct bt_hci_acl_hdr *hdr = &rx.acl; + + rx.remaining = sys_le16_to_cpu(hdr->len); + LOG_DBG("Got ACL header. Payload %u bytes", rx.remaining); + rx.have_hdr = true; + } +} + +static inline void get_iso_hdr(void) +{ + h4_read_hdr(); + + if (!rx.remaining) { + struct bt_hci_iso_hdr *hdr = &rx.iso; + + rx.remaining = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); + LOG_DBG("Got ISO header. Payload %u bytes", rx.remaining); + rx.have_hdr = true; + } +} + +static inline void get_evt_hdr(void) +{ + struct bt_hci_evt_hdr *hdr = &rx.evt; + + h4_read_hdr(); + + if (rx.hdr_len == sizeof(*hdr) && rx.remaining < sizeof(*hdr)) { + switch (rx.evt.evt) { + case BT_HCI_EVT_LE_META_EVENT: + rx.remaining++; + rx.hdr_len++; + break; + } + } + + if (!rx.remaining) { + if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && + (rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { + LOG_DBG("Marking adv report as discardable"); + rx.discardable = true; + } + + rx.remaining = hdr->len - (rx.hdr_len - sizeof(*hdr)); + LOG_DBG("Got event header. Payload %u bytes", hdr->len); + rx.have_hdr = true; + } +} + + +static inline void copy_hdr(struct net_buf *buf) +{ + net_buf_add_mem(buf, rx.hdr, rx.hdr_len); +} + +static void reset_rx(void) +{ + rx.type = BT_HCI_H4_NONE; + rx.remaining = 0U; + rx.have_hdr = false; + rx.hdr_len = 0U; + rx.discardable = false; +} + +static struct net_buf *get_rx(k_timeout_t timeout) +{ + LOG_DBG("type 0x%02x, evt 0x%02x", rx.type, rx.evt.evt); + + switch (rx.type) { + case BT_HCI_H4_EVT: + return bt_buf_get_evt(rx.evt.evt, rx.discardable, timeout); + case BT_HCI_H4_ACL: + return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + return bt_buf_get_rx(BT_BUF_ISO_IN, timeout); + } + } + + return NULL; +} + +static void rx_thread(void *p1, void *p2, void *p3) +{ + struct net_buf *buf; + + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + LOG_DBG("started"); + + while (1) { + LOG_DBG("rx.buf %p", rx.buf); + + /* We can only do the allocation if we know the initial + * header, since Command Complete/Status events must use the + * original command buffer (if available). + */ + if (rx.have_hdr && !rx.buf) { + rx.buf = get_rx(K_FOREVER); + LOG_DBG("Got rx.buf %p", rx.buf); + if (rx.remaining > net_buf_tailroom(rx.buf)) { + LOG_ERR("Not enough space in buffer"); + rx.discard = rx.remaining; + reset_rx(); + } else { + copy_hdr(rx.buf); + } + } + + /* Let the ISR continue receiving new packets */ + irq_enable(CMAC2SYS_IRQn); + + buf = net_buf_get(&rx.fifo, K_FOREVER); + do { + irq_enable(CMAC2SYS_IRQn); + + LOG_DBG("Calling bt_recv(%p)", buf); + bt_recv(buf); + + /* Give other threads a chance to run if the ISR + * is receiving data so fast that rx.fifo never + * or very rarely goes empty. + */ + k_yield(); + + irq_disable(CMAC2SYS_IRQn); + buf = net_buf_get(&rx.fifo, K_NO_WAIT); + } while (buf); + } +} + +static size_t h4_discard(size_t len) +{ + uint8_t buf[33]; + int err; + + err = cmac_mbox_read(buf, MIN(len, sizeof(buf))); + if (unlikely(err < 0)) { + LOG_ERR("Unable to read from mailbox (err %d)", err); + return 0; + } + + return err; +} + +static inline void read_payload(void) +{ + struct net_buf *buf; + int read; + + if (!rx.buf) { + size_t buf_tailroom; + + rx.buf = get_rx(K_NO_WAIT); + if (!rx.buf) { + if (rx.discardable) { + LOG_WRN("Discarding event 0x%02x", rx.evt.evt); + rx.discard = rx.remaining; + reset_rx(); + return; + } + + LOG_WRN("Failed to allocate, deferring to rx_thread"); + irq_disable(CMAC2SYS_IRQn); + return; + } + + LOG_DBG("Allocated rx.buf %p", rx.buf); + + buf_tailroom = net_buf_tailroom(rx.buf); + if (buf_tailroom < rx.remaining) { + LOG_ERR("Not enough space in buffer %u/%zu", rx.remaining, buf_tailroom); + rx.discard = rx.remaining; + reset_rx(); + return; + } + + copy_hdr(rx.buf); + } + + read = cmac_mbox_read(net_buf_tail(rx.buf), rx.remaining); + if (unlikely(read < 0)) { + LOG_ERR("Failed to read mailbox (err %d)", read); + return; + } + + net_buf_add(rx.buf, read); + rx.remaining -= read; + + LOG_DBG("got %d bytes, remaining %u", read, rx.remaining); + LOG_DBG("Payload (len %u): %s", rx.buf->len, bt_hex(rx.buf->data, rx.buf->len)); + + if (rx.remaining) { + return; + } + + buf = rx.buf; + rx.buf = NULL; + + if (rx.type == BT_HCI_H4_EVT) { + bt_buf_set_type(buf, BT_BUF_EVT); + } else { + bt_buf_set_type(buf, BT_BUF_ACL_IN); + } + + reset_rx(); + + LOG_DBG("Putting buf %p to rx fifo", buf); + net_buf_put(&rx.fifo, buf); +} + +static inline void read_header(void) +{ + switch (rx.type) { + case BT_HCI_H4_NONE: + h4_get_type(); + return; + case BT_HCI_H4_EVT: + get_evt_hdr(); + break; + case BT_HCI_H4_ACL: + get_acl_hdr(); + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + get_iso_hdr(); + break; + } + __fallthrough; + default: + CODE_UNREACHABLE; + return; + } + + if (rx.have_hdr && rx.buf) { + if (rx.remaining > net_buf_tailroom(rx.buf)) { + LOG_ERR("Not enough space in buffer"); + rx.discard = rx.remaining; + reset_rx(); + } else { + copy_hdr(rx.buf); + } + } +} + +static inline void process_rx(void) +{ + LOG_DBG("remaining %u discard %u have_hdr %u rx.buf %p len %u", rx.remaining, rx.discard, + rx.have_hdr, rx.buf, rx.buf ? rx.buf->len : 0); + + if (rx.discard) { + rx.discard -= h4_discard(rx.discard); + return; + } + + if (rx.have_hdr) { + read_payload(); + } else { + read_header(); + } +} + +/* Called by HAL when data in CMAC mailbox is available to read */ +void cmac_read_req(void) +{ + while (cmac_mbox_has_data()) { + process_rx(); + } +} + +/* Called by HAL when CMAC requests host to put more data in rng buffer */ +void cmac_rng_req(void) +{ + k_sem_give(&rng_sem); +} + +static void rng_thread(void *p1, void *p2, void *p3) +{ + uint32_t word; + + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + while (1) { + k_sem_take(&rng_sem, K_FOREVER); + + while (cmac_rand_needs_data()) { + word = sys_rand32_get(); + cmac_rand_fill(&word, 1); + } + + cmac_signal(); + } +} + +static int bt_da1469x_open(void) +{ + k_tid_t tid; + + tid = k_thread_create(&rx_thread_data, rx_thread_stack, + K_KERNEL_STACK_SIZEOF(rx_thread_stack), + rx_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(tid, "bt_rx_thread"); + + k_sem_init(&rng_sem, 0, 1); + + tid = k_thread_create(&rng_thread_data, rng_thread_stack, + K_KERNEL_STACK_SIZEOF(rng_thread_stack), + rng_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(tid, "bt_rng_thread"); + + cmac_enable(); + irq_enable(CMAC2SYS_IRQn); + + return 0; +} + +#ifdef CONFIG_BT_HCI_HOST +static int bt_da1469x_close(void) +{ + irq_disable(CMAC2SYS_IRQn); + cmac_disable(); + + return 0; +} +#endif /* CONFIG_BT_HCI_HOST */ + +static int bt_da1469x_send(struct net_buf *buf) +{ + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_OUT: + LOG_DBG("ACL: buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + net_buf_push_u8(buf, BT_HCI_H4_ACL); + break; + case BT_BUF_CMD: + LOG_DBG("CMD: buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + net_buf_push_u8(buf, BT_HCI_H4_CMD); + break; + default: + LOG_ERR("Unsupported type"); + return -EINVAL; + } + + cmac_mbox_write(buf->data, buf->len); + + net_buf_unref(buf); + + return 0; +} + +static const struct bt_hci_driver drv = { + .name = "BT DA1469x", + .bus = BT_HCI_DRIVER_BUS_IPM, + .open = bt_da1469x_open, + .close = bt_da1469x_close, + .send = bt_da1469x_send, +}; + +static int bt_da1469x_init(void) +{ + irq_disable(CMAC2SYS_IRQn); + + bt_hci_driver_register(&drv); + + cmac_disable(); + cmac_load_image(); + cmac_configure_pdc(); + cmac_configure_shm(); + + IRQ_CONNECT(CMAC2SYS_IRQn, 0, cmac_cmac2sys_isr, NULL, 0); + + return 0; +} + +SYS_INIT(bt_da1469x_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); From f81c8ad20ca1661a8e42cdd626f2f7cf57d81b4f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0861/1389] boards: renesas: Add configuration for BT Adds required defconfigs for BT on DA1469x DK. Signed-off-by: Andrzej Kaczmarek --- boards/renesas/da1469x_dk_pro/Kconfig.defconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig index d487e093a080ff..c20c21658d06f4 100644 --- a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig +++ b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig @@ -48,4 +48,18 @@ config SERIAL_INIT_PRIORITY #endif # PM || PM_DEVICE +if BT + +choice BT_HCI_BUS_TYPE + default BT_DA1469X +endchoice + +config BT_WAIT_NOP + default y + +config TEST_RANDOM_GENERATOR + default y + +endif # BT + endif # BOARD_DA1469X_DK_PRO From 159ec48ae6bdea648992c9b36600ff3408cda992 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0862/1389] MAINTAINERS: Add ubieda to sensor drivers collaborator Add self as Sensor drivers collaborator. Signed-off-by: Luis Ubieda --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 821497ff6c0d66..ed368a990e9b2e 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1820,6 +1820,7 @@ Release Notes: - teburd - yperess - tristan-google + - ubieda files: - drivers/sensor/ - include/zephyr/drivers/sensor.h From a1781b2f4cba47ba6190a55f176224658257bcfb Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0863/1389] drivers: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- drivers/interrupt_controller/intc_system_apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/interrupt_controller/intc_system_apic.c b/drivers/interrupt_controller/intc_system_apic.c index b9ad0b70bbfa52..6089e453405d69 100644 --- a/drivers/interrupt_controller/intc_system_apic.c +++ b/drivers/interrupt_controller/intc_system_apic.c @@ -19,7 +19,7 @@ #include #include -#define IS_IOAPIC_IRQ(irq) (irq < z_loapic_irq_base()) +#define IS_IOAPIC_IRQ(irq) ((irq) < z_loapic_irq_base()) #define HARDWARE_IRQ_LIMIT ((z_loapic_irq_base() + LOAPIC_IRQ_COUNT) - 1) /** From 95472f1fd43fd61c0925408814e6f082686e24fc Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0864/1389] include: dt-bindings: gpio: fix flag value '1u' causes devicetree parsing error. Signed-off-by: Abderrahmane Jarmouni --- include/zephyr/dt-bindings/gpio/gpio.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/zephyr/dt-bindings/gpio/gpio.h b/include/zephyr/dt-bindings/gpio/gpio.h index 6e8631d7d6d3b1..b4110208b3fe97 100644 --- a/include/zephyr/dt-bindings/gpio/gpio.h +++ b/include/zephyr/dt-bindings/gpio/gpio.h @@ -81,9 +81,10 @@ /* Note: Bits 15 downto 8 are reserved for SoC specific flags. */ -/** Configures GPIO interrupt to wakeup the system from low power mode. +/** + * Configures GPIO interrupt to wakeup the system from low power mode. */ -#define GPIO_INT_WAKEUP (1u << 28) +#define GPIO_INT_WAKEUP (1 << 28) /** * @} From bf0935d3ebc40a61c58cf7533f3b79e8924800fe Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0865/1389] drivers: clock_control: Smartbond: Add runtime frequency support RC32K and RCX low power clocks require runtime calibration to work correctly. Frequency of those clock can differ from chip to chip, one constant value from Kconfig may not be best when low power clock (sourced from RCX or RC32K) is used for system tick. This code modifies global z_clock_hw_cycles_per_sec variable that is used when TIMER_READS_ITS_FREQUENCY_AT_RUNTIME is enabled in Kconfig. Signed-off-by: Jerzy Kasenberg --- .../clock_control/clock_control_smartbond.c | 30 +++++++++++++++++++ soc/renesas/smartbond/da1469x/Kconfig | 1 + 2 files changed, 31 insertions(+) diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index 60c98f8668a0fc..1ba24850f2d982 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -34,8 +34,13 @@ struct lpc_clock_state { DT_PROP(DT_NODELABEL(rcx), calibration_interval) : \ DT_PROP(DT_NODELABEL(rc32k), calibration_interval)) +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME +extern int z_clock_hw_cycles_per_sec; +#endif + static void calibration_work_cb(struct k_work *work); static void xtal32k_settle_work_cb(struct k_work *work); +static enum smartbond_clock smartbond_source_clock(enum smartbond_clock clk); static K_WORK_DELAYABLE_DEFINE(calibration_work, calibration_work_cb); static K_WORK_DELAYABLE_DEFINE(xtal32k_settle_work, xtal32k_settle_work_cb); @@ -59,6 +64,18 @@ static void calibration_work_cb(struct k_work *work) LOG_DBG("RC32K calibration done, RC32K freq: %d", (int)lpc_clock_state.rc32k_freq); } +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + switch (smartbond_source_clock(SMARTBOND_CLK_LP_CLK)) { + case SMARTBOND_CLK_RCX: + z_clock_hw_cycles_per_sec = lpc_clock_state.rcx_freq; + break; + case SMARTBOND_CLK_RC32K: + z_clock_hw_cycles_per_sec = lpc_clock_state.rc32k_freq; + break; + default: + break; + } +#endif } static void xtal32k_settle_work_cb(struct k_work *work) @@ -350,6 +367,19 @@ int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk) } if (rc == 0) { +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + switch (lp_clk) { + case SMARTBOND_CLK_RCX: + z_clock_hw_cycles_per_sec = lpc_clock_state.rcx_freq; + break; + case SMARTBOND_CLK_RC32K: + z_clock_hw_cycles_per_sec = lpc_clock_state.rc32k_freq; + break; + default: + z_clock_hw_cycles_per_sec = 32768; + break; + } +#endif CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel; } diff --git a/soc/renesas/smartbond/da1469x/Kconfig b/soc/renesas/smartbond/da1469x/Kconfig index c987b579c10329..b07c4274ad6932 100644 --- a/soc/renesas/smartbond/da1469x/Kconfig +++ b/soc/renesas/smartbond/da1469x/Kconfig @@ -14,3 +14,4 @@ config SOC_SERIES_DA1469X select CLOCK_CONTROL_SMARTBOND select PLATFORM_SPECIFIC_INIT select PM_DEVICE if PM + imply TIMER_READS_ITS_FREQUENCY_AT_RUNTIME From bedd22b88bd64fd797ebea65b32450a032315b8c Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:12 +0200 Subject: [PATCH 0866/1389] tests: smbus_emul: Remove unnecessary definition pcie_prob() has been deprecated and it is not needed in the test. Signed-off-by: Flavio Ceolin --- tests/drivers/smbus/smbus_emul/src/smbus.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/drivers/smbus/smbus_emul/src/smbus.c b/tests/drivers/smbus/smbus_emul/src/smbus.c index fee5a18b449161..b590470ff70eab 100644 --- a/tests/drivers/smbus/smbus_emul/src/smbus.c +++ b/tests/drivers/smbus/smbus_emul/src/smbus.c @@ -49,7 +49,6 @@ static void mock_conf_write(pcie_bdf_t bdf, unsigned int reg, uint32_t data) #define CONFIG_SMBUS_INTEL_PCH_ACCESS_IO #define device_map(a, b, c, d) -#define pcie_probe(bdf, id) 1 #define pcie_set_cmd(a, b, c) #define SMBUS_EMUL "smbus_emul" From 9605bef7d155039476a4c7076774833f3213c439 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0867/1389] drivers: pcie: Remove deprecated pcie_probe pcie_probe() was deprecated before 3.3 release. Time to remove it. Signed-off-by: Flavio Ceolin --- drivers/pcie/host/pcie.c | 17 ----------------- include/zephyr/drivers/pcie/pcie.h | 12 ------------ 2 files changed, 29 deletions(-) diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 9acca131a98d20..734ffbd67e4b7a 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -37,23 +37,6 @@ static bool prt_en; /* functions documented in drivers/pcie/pcie.h */ -bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id) -{ - uint32_t data; - - data = pcie_conf_read(bdf, PCIE_CONF_ID); - - if (!PCIE_ID_IS_VALID(data)) { - return false; - } - - if (id == PCIE_ID_NONE) { - return true; - } - - return (id == data); -} - void pcie_set_cmd(pcie_bdf_t bdf, uint32_t bits, bool on) { uint32_t cmdstat; diff --git a/include/zephyr/drivers/pcie/pcie.h b/include/zephyr/drivers/pcie/pcie.h index ff3cb078064025..fd75adaa57ac0d 100644 --- a/include/zephyr/drivers/pcie/pcie.h +++ b/include/zephyr/drivers/pcie/pcie.h @@ -235,18 +235,6 @@ struct pcie_scan_opt { */ int pcie_scan(const struct pcie_scan_opt *opt); -/** - * @brief Probe for the presence of a PCI(e) endpoint. - * - * @deprecated - * @see DEVICE_PCIE_DECLARE - * - * @param bdf the endpoint to probe - * @param id the endpoint ID to expect, or PCIE_ID_NONE for "any device" - * @return true if the device is present, false otherwise - */ -__deprecated extern bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id); - /** * @brief Get the MBAR at a specific BAR index * @param bdf the PCI(e) endpoint From 12569ba4ba7a612bf32c4a569689e7013d9d4dce Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0868/1389] drivers: pcie: Remove deprecated pcie_bdf_lookup pcie_bdf_lookup() was deprecated before 3.3 release. Time to remove it. Signed-off-by: Flavio Ceolin --- drivers/pcie/host/pcie.c | 34 ------------------------------ include/zephyr/drivers/pcie/pcie.h | 14 ------------ 2 files changed, 48 deletions(-) diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 734ffbd67e4b7a..c2261af5de4e77 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -368,40 +368,6 @@ void pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq) irq_enable(irq); } -struct lookup_data { - pcie_bdf_t bdf; - pcie_id_t id; -}; - -static bool lookup_cb(pcie_bdf_t bdf, pcie_id_t id, void *cb_data) -{ - struct lookup_data *data = cb_data; - - if (id == data->id) { - data->bdf = bdf; - return false; - } - - return true; -} - -pcie_bdf_t pcie_bdf_lookup(pcie_id_t id) -{ - struct lookup_data data = { - .bdf = PCIE_BDF_NONE, - .id = id, - }; - struct pcie_scan_opt opt = { - .cb = lookup_cb, - .cb_data = &data, - .flags = (PCIE_SCAN_RECURSIVE | PCIE_SCAN_CB_ALL), - }; - - pcie_scan(&opt); - - return data.bdf; -} - static bool scan_flag(const struct pcie_scan_opt *opt, uint32_t flag) { return ((opt->flags & flag) != 0U); diff --git a/include/zephyr/drivers/pcie/pcie.h b/include/zephyr/drivers/pcie/pcie.h index fd75adaa57ac0d..cb55dffd5b8ca2 100644 --- a/include/zephyr/drivers/pcie/pcie.h +++ b/include/zephyr/drivers/pcie/pcie.h @@ -158,20 +158,6 @@ struct pcie_bar { * These functions are arch-, board-, or SoC-specific. */ -/** - * @brief Look up the BDF based on PCI(e) vendor & device ID - * - * This function is used to look up the BDF for a device given its - * vendor and device ID. - * - * @deprecated - * @see DEVICE_PCIE_DECLARE - * - * @param id PCI(e) vendor & device ID encoded using PCIE_ID() - * @return The BDF for the device, or PCIE_BDF_NONE if it was not found - */ -__deprecated extern pcie_bdf_t pcie_bdf_lookup(pcie_id_t id); - /** * @brief Read a 32-bit word from an endpoint's configuration space. * From aaedba1000646742cd0cb5588ded37dd62e618f9 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0869/1389] doc: release-notes-3.7: Removed PCIe APIs Add information about PCIe APIs removed in this release. Signed-off-by: Flavio Ceolin --- doc/releases/release-notes-3.7.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index d4c2352b0755b2..bada6224280036 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -40,6 +40,8 @@ Removed APIs in this release * The Bluetooth subsystem specific debug symbols are removed. They have been replaced with the Zephyr logging ones. + * Removed deprecated ``pcie_probe`` and ``pcie_bdf_lookup`` functions from the PCIe APIs. + Deprecated in this release ========================== From 6645943d7629d032d54f9da67ae3bba7f8f3d947 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0870/1389] drivers: sdhc: sdhc_spi: release bus on error Properly release SPI bus on transmit error within the SDHC SPI driver. In these cases return code is not checked, as we wish to return the error code from the failed transfer to the SD stack. Fixes #72364 Signed-off-by: Daniel DeGrasse --- drivers/sdhc/sdhc_spi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/sdhc/sdhc_spi.c b/drivers/sdhc/sdhc_spi.c index 7462e711dcd407..234fb99743a886 100644 --- a/drivers/sdhc/sdhc_spi.c +++ b/drivers/sdhc/sdhc_spi.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -143,6 +143,7 @@ static int sdhc_spi_init_card(const struct device *dev) spi_cfg->operation |= SPI_CS_ACTIVE_HIGH; ret = sdhc_spi_rx(config->spi_dev, spi_cfg, data->scratch, 10); if (ret != 0) { + spi_release(config->spi_dev, spi_cfg); spi_cfg->operation &= ~SPI_CS_ACTIVE_HIGH; return ret; } @@ -638,6 +639,8 @@ static int sdhc_spi_request(const struct device *dev, } while ((ret != 0) && (retries-- > 0)); } if (ret) { + /* Release SPI bus */ + spi_release(config->spi_dev, dev_data->spi_cfg); return ret; } /* Release SPI bus */ From 6074b591bd42ed09f58e65bdbbcb18285b9b7536 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0871/1389] drivers: sdhc: sdhc_spi: rework CMD12 failure logic Rework CMD12 failure logic for SDHC SPI driver. Previously, the error code of CMD12 was not checked, so even if CMD12 failed to send the initial command would be retried. Change this behavior to retry CMD12 until it succeeds. If CMD12 fails, its error code will be propagated to the caller. Otherwise, the return code from the command being sent by the caller will be propagated. Fixes #72365 Signed-off-by: Daniel DeGrasse --- drivers/sdhc/sdhc_spi.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/sdhc/sdhc_spi.c b/drivers/sdhc/sdhc_spi.c index 234fb99743a886..7e7e22b9f17aca 100644 --- a/drivers/sdhc/sdhc_spi.c +++ b/drivers/sdhc/sdhc_spi.c @@ -604,7 +604,7 @@ static int sdhc_spi_request(const struct device *dev, { const struct sdhc_spi_config *config = dev->config; struct sdhc_spi_data *dev_data = dev->data; - int ret, retries = cmd->retries; + int ret, stop_ret, retries = cmd->retries; const struct sdhc_command stop_cmd = { .opcode = SD_STOP_TRANSMISSION, .arg = 0, @@ -618,6 +618,7 @@ static int sdhc_spi_request(const struct device *dev, } while ((ret != 0) && (retries-- > 0)); } else { do { + retries--; ret = sdhc_spi_send_cmd(dev, cmd, true); if (ret) { continue; @@ -629,14 +630,23 @@ static int sdhc_spi_request(const struct device *dev, ret = sdhc_spi_read_data(dev, data); } if (ret || (cmd->opcode == SD_READ_MULTIPLE_BLOCK)) { + int stop_retries = cmd->retries; + /* CMD12 is required after multiple read, or * to retry failed transfer */ - sdhc_spi_send_cmd(dev, + stop_ret = sdhc_spi_send_cmd(dev, (struct sdhc_command *)&stop_cmd, false); + while ((stop_ret != 0) && (stop_retries > 0)) { + /* Retry stop command */ + ret = stop_ret = sdhc_spi_send_cmd(dev, + (struct sdhc_command *)&stop_cmd, + false); + stop_retries--; + } } - } while ((ret != 0) && (retries-- > 0)); + } while ((ret != 0) && (retries > 0)); } if (ret) { /* Release SPI bus */ From 9996bd18778185dc8701fa77e18eca7c2881275d Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0872/1389] sensors: Add channel specifier Use a structured channel specifier rather than a single enum when specifying channels to read in the new read/decoder API. Replaces usages of a seperate channel and channel_index parameter where previously used with a struct sensor_chan_spec. Signed-off-by: Tom Burdick --- drivers/sensor/amd_sb_tsi/sb_tsi_emul.c | 8 +- .../asahi_kasei/akm09918c/akm09918c_decoder.c | 19 ++- .../asahi_kasei/akm09918c/akm09918c_emul.c | 8 +- drivers/sensor/bosch/bma4xx/bma4xx.c | 46 ++++--- drivers/sensor/bosch/bma4xx/bma4xx_emul.c | 12 +- drivers/sensor/bosch/bmi160/emul_bmi160.c | 42 +++---- drivers/sensor/default_rtio_sensor.c | 116 ++++++++++-------- drivers/sensor/f75303/f75303_emul.c | 12 +- drivers/sensor/sensor_shell.c | 73 ++++++----- .../sensor/tdk/icm42688/icm42688_decoder.c | 48 ++++---- .../sensor/tdk/icm42688/icm42688_decoder.h | 2 +- drivers/sensor/tdk/icm42688/icm42688_emul.c | 16 +-- drivers/sensor/tdk/icm42688/icm42688_rtio.c | 2 +- include/zephyr/drivers/emul_sensor.h | 21 ++-- include/zephyr/drivers/sensor.h | 78 ++++++++---- .../build_all/sensor/src/generic_test.c | 25 ++-- tests/drivers/sensor/bmi160/src/fixture.c | 4 +- 17 files changed, 295 insertions(+), 237 deletions(-) diff --git a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c index f33e5cd9134f85..08ef4026ccf5b1 100644 --- a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c +++ b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c @@ -99,7 +99,7 @@ static int sb_tsi_emul_init(const struct emul *target, const struct device *pare return 0; } -static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channel chan, +static int sb_tsi_emul_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { struct sb_tsi_emul_data *data = target->data; @@ -107,7 +107,7 @@ static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channe int32_t millicelsius; int32_t reg_value; - if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + if (ch.chan_type != SENSOR_CHAN_AMBIENT_TEMP && ch.chan_idx != 0) { return -ENOTSUP; } @@ -121,10 +121,10 @@ static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channe return 0; } -static int sb_tsi_emul_get_sample_range(const struct emul *target, enum sensor_channel chan, +static int sb_tsi_emul_get_sample_range(const struct emul *target, struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { - if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + if (ch.chan_type != SENSOR_CHAN_AMBIENT_TEMP || ch.chan_idx != 0) { return -ENOTSUP; } diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c index 9bd6b312b7a0e0..9f13cc4b31d16b 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c @@ -5,22 +5,22 @@ #include "akm09918c.h" -static int akm09918c_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count) +static int akm09918c_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) { ARG_UNUSED(buffer); - ARG_UNUSED(channel); - ARG_UNUSED(channel_idx); + ARG_UNUSED(chan_spec); /* This sensor lacks a FIFO; there will always only be one frame at a time. */ *frame_count = 1; return 0; } -static int akm09918c_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, +static int akm09918c_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size, size_t *frame_size) { - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: @@ -48,9 +48,8 @@ static int akm09918c_convert_raw_to_q31(int16_t reading, q31_t *out) return 0; } -static int akm09918c_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, - uint16_t max_count, void *data_out) +static int akm09918c_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct akm09918c_encoded_data *edata = (const struct akm09918c_encoded_data *)buffer; @@ -58,7 +57,7 @@ static int akm09918c_decoder_decode(const uint8_t *buffer, enum sensor_channel c return 0; } - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c index db541b8b4fb4b5..5dce0d0d82716a 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c @@ -133,7 +133,7 @@ static int akm09918c_emul_init(const struct emul *target, const struct device *p return 0; } -static int akm09918c_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int akm09918c_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { if (!target || !target->data) { @@ -143,7 +143,7 @@ static int akm09918c_emul_backend_set_channel(const struct emul *target, enum se struct akm09918c_emul_data *data = target->data; uint8_t reg; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_MAGN_X: reg = AKM09918C_REG_HXL; break; @@ -178,7 +178,7 @@ static int akm09918c_emul_backend_set_channel(const struct emul *target, enum se } static int akm09918c_emul_backend_get_sample_range(const struct emul *target, - enum sensor_channel ch, q31_t *lower, + struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { ARG_UNUSED(target); @@ -187,7 +187,7 @@ static int akm09918c_emul_backend_get_sample_range(const struct emul *target, return -EINVAL; } - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: diff --git a/drivers/sensor/bosch/bma4xx/bma4xx.c b/drivers/sensor/bosch/bma4xx/bma4xx.c index 9d8656d67aa808..db717cc0c04e00 100644 --- a/drivers/sensor/bosch/bma4xx/bma4xx.c +++ b/drivers/sensor/bosch/bma4xx/bma4xx.c @@ -343,7 +343,7 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq struct bma4xx_data *bma4xx = dev->data; const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; - const enum sensor_channel *const channels = cfg->channels; + const struct sensor_chan_spec *const channels = cfg->channels; const size_t num_channels = cfg->count; uint32_t min_buf_len = sizeof(struct bma4xx_encoded_data); @@ -370,7 +370,11 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq /* Determine what channels we need to fetch */ for (int i = 0; i < num_channels; i++) { - switch (channels[i]) { + if (channels[i].chan_idx != 0) { + LOG_ERR("Only channel index 0 supported"); + return -ENOTSUP; + } + switch (channels[i].chan_type) { case SENSOR_CHAN_ALL: edata->has_accel = 1; #ifdef CONFIG_BMA4XX_TEMPERATURE @@ -389,7 +393,8 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq break; #endif /* CONFIG_BMA4XX_TEMPERATURE */ default: - LOG_ERR("Requested unsupported channel ID %d", channels[i]); + LOG_ERR("Requested unsupported channel type %d, idx %d", + channels[i].chan_type, channels[i].chan_idx); return -ENOTSUP; } } @@ -436,18 +441,18 @@ static int bma4xx_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_ * RTIO decoder */ -static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count) +static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec ch, + uint16_t *frame_count) { const struct bma4xx_encoded_data *edata = (const struct bma4xx_encoded_data *)buffer; const struct bma4xx_decoder_header *header = &edata->header; - if (channel_idx != 0) { + if (ch.chan_idx != 0) { return -ENOTSUP; } if (!header->is_fifo) { - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -467,10 +472,10 @@ static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, enum sensor_cha return -ENOTSUP; } -static int bma4xx_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, +static int bma4xx_decoder_get_size_info(struct sensor_chan_spec ch, size_t *base_size, size_t *frame_size) { - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -487,9 +492,9 @@ static int bma4xx_decoder_get_size_info(enum sensor_channel channel, size_t *bas } } -static int bma4xx_get_shift(enum sensor_channel channel, uint8_t accel_fs, int8_t *shift) +static int bma4xx_get_shift(struct sensor_chan_spec ch, uint8_t accel_fs, int8_t *shift) { - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -562,9 +567,8 @@ static void bma4xx_convert_raw_temp_to_q31(int8_t raw_val, q31_t *out) } #endif /* CONFIG_BMA4XX_TEMPERATURE */ -static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int bma4xx_one_shot_decode(const uint8_t *buffer, struct sensor_chan_spec ch, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct bma4xx_encoded_data *edata = (const struct bma4xx_encoded_data *)buffer; const struct bma4xx_decoder_header *header = &edata->header; @@ -573,11 +577,11 @@ static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel cha if (*fit != 0) { return 0; } - if (max_count == 0 || channel_idx != 0) { + if (max_count == 0 || ch.chan_idx != 0) { return -EINVAL; } - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -590,7 +594,9 @@ static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel cha out->header.base_timestamp_ns = edata->header.timestamp; out->header.reading_count = 1; - rc = bma4xx_get_shift(SENSOR_CHAN_ACCEL_XYZ, header->accel_fs, &out->shift); + rc = bma4xx_get_shift((struct sensor_chan_spec){.chan_type = SENSOR_CHAN_ACCEL_XYZ, + .chan_idx = 0}, + header->accel_fs, &out->shift); if (rc != 0) { return -EINVAL; } @@ -628,8 +634,8 @@ static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel cha } } -static int bma4xx_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, +static int bma4xx_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec ch, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct bma4xx_decoder_header *header = (const struct bma4xx_decoder_header *)buffer; @@ -639,7 +645,7 @@ static int bma4xx_decoder_decode(const uint8_t *buffer, enum sensor_channel chan return -ENOTSUP; } - return bma4xx_one_shot_decode(buffer, channel, channel_idx, fit, max_count, data_out); + return bma4xx_one_shot_decode(buffer, ch, fit, max_count, data_out); } SENSOR_DECODER_API_DT_DEFINE() = { diff --git a/drivers/sensor/bosch/bma4xx/bma4xx_emul.c b/drivers/sensor/bosch/bma4xx/bma4xx_emul.c index efc4012e29c560..ec5f069da536e7 100644 --- a/drivers/sensor/bosch/bma4xx/bma4xx_emul.c +++ b/drivers/sensor/bosch/bma4xx/bma4xx_emul.c @@ -216,7 +216,7 @@ void bma4xx_emul_set_accel_data(const struct emul *target, q31_t value, int8_t s data->regs[reg + 1] = FIELD_GET(GENMASK(11, 4), reg_val); } -static int bma4xx_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int bma4xx_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { @@ -226,7 +226,7 @@ static int bma4xx_emul_backend_set_channel(const struct emul *target, enum senso struct bma4xx_emul_data *data = target->data; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: bma4xx_emul_set_accel_data(target, value[0], shift, BMA4XX_REG_DATA_8); break; @@ -250,15 +250,15 @@ static int bma4xx_emul_backend_set_channel(const struct emul *target, enum senso return 0; } -static int bma4xx_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, - q31_t *lower, q31_t *upper, q31_t *epsilon, - int8_t *shift) +static int bma4xx_emul_backend_get_sample_range(const struct emul *target, + struct sensor_chan_spec ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) { if (!lower || !upper || !epsilon || !shift) { return -EINVAL; } - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: diff --git a/drivers/sensor/bosch/bmi160/emul_bmi160.c b/drivers/sensor/bosch/bmi160/emul_bmi160.c index 38c74a98813d1f..9fc33b48b6aa97 100644 --- a/drivers/sensor/bosch/bmi160/emul_bmi160.c +++ b/drivers/sensor/bosch/bmi160/emul_bmi160.c @@ -279,7 +279,7 @@ static struct i2c_emul_api bmi160_emul_api_i2c = { }; #endif -static int bmi160_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int bmi160_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { const struct bmi160_emul_cfg *cfg = target->cfg; @@ -288,11 +288,11 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso int8_t scale_shift = 0; int reg_lsb; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: - reg_lsb = BMI160_REG_DATA_ACC_X + (ch - SENSOR_CHAN_ACCEL_X) * 2; + reg_lsb = BMI160_REG_DATA_ACC_X + (ch.chan_type - SENSOR_CHAN_ACCEL_X) * 2; scale = 0x4e7404ea; switch (FIELD_GET(GENMASK(3, 0), cfg->reg[BMI160_REG_ACC_RANGE])) { @@ -313,7 +313,7 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso case SENSOR_CHAN_GYRO_X: case SENSOR_CHAN_GYRO_Y: case SENSOR_CHAN_GYRO_Z: - reg_lsb = BMI160_REG_DATA_GYR_X + (ch - SENSOR_CHAN_GYRO_X) * 2; + reg_lsb = BMI160_REG_DATA_GYR_X + (ch.chan_type - SENSOR_CHAN_GYRO_X) * 2; scale = 0x45d02bea; switch (FIELD_GET(GENMASK(2, 0), cfg->reg[BMI160_REG_GYR_RANGE])) { @@ -353,7 +353,7 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso intermediate <<= shift - scale_shift; } - if (ch == SENSOR_CHAN_DIE_TEMP) { + if (ch.chan_type == SENSOR_CHAN_DIE_TEMP) { /* Need to subtract 23C */ intermediate -= INT64_C(23) << (31 - scale_shift); } @@ -366,13 +366,13 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso return 0; } -static int bmi160_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, - q31_t *lower, q31_t *upper, q31_t *epsilon, - int8_t *shift) +static int bmi160_emul_backend_get_sample_range(const struct emul *target, + struct sensor_chan_spec ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) { const struct bmi160_emul_cfg *cfg = target->cfg; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -440,10 +440,10 @@ static int bmi160_emul_backend_get_sample_range(const struct emul *target, enum } } -static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor_channel ch, +static int bmi160_emul_backend_set_offset(const struct emul *target, struct sensor_chan_spec ch, const q31_t *values, int8_t shift) { - if (ch != SENSOR_CHAN_ACCEL_XYZ && ch != SENSOR_CHAN_GYRO_XYZ) { + if (ch.chan_type != SENSOR_CHAN_ACCEL_XYZ && ch.chan_type != SENSOR_CHAN_GYRO_XYZ) { return -EINVAL; } @@ -452,20 +452,20 @@ static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor int8_t scale_shift = 0; if (values[0] == 0 && values[1] == 0 && values[2] == 0) { - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { cfg->reg[BMI160_REG_OFFSET_EN] &= ~BIT(BMI160_ACC_OFS_EN_POS); } else { cfg->reg[BMI160_REG_OFFSET_EN] &= ~BIT(BMI160_GYR_OFS_EN_POS); } } else { - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { cfg->reg[BMI160_REG_OFFSET_EN] |= BIT(BMI160_ACC_OFS_EN_POS); } else { cfg->reg[BMI160_REG_OFFSET_EN] |= BIT(BMI160_GYR_OFS_EN_POS); } } - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { /* * bits = (values[i]mps2 / 9.80665g/mps2) / 0.0039g * = values[i] / 0.038245935mps2/bit @@ -493,11 +493,11 @@ static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor int64_t reg_value = intermediate / scale; - __ASSERT_NO_MSG(ch != SENSOR_CHAN_ACCEL_XYZ || + __ASSERT_NO_MSG(ch.chan_type != SENSOR_CHAN_ACCEL_XYZ || (reg_value >= INT8_MIN && reg_value <= INT8_MAX)); - __ASSERT_NO_MSG(ch != SENSOR_CHAN_GYRO_XYZ || + __ASSERT_NO_MSG(ch.chan_type != SENSOR_CHAN_GYRO_XYZ || (reg_value >= -0x1ff - 1 && reg_value <= 0x1ff)); - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { cfg->reg[BMI160_REG_OFFSET_ACC_X + i] = reg_value & 0xff; } else { cfg->reg[BMI160_REG_OFFSET_GYR_X + i] = reg_value & 0xff; @@ -510,11 +510,11 @@ static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor return 0; } -static int bmi160_emul_backend_set_attribute(const struct emul *target, enum sensor_channel ch, +static int bmi160_emul_backend_set_attribute(const struct emul *target, struct sensor_chan_spec ch, enum sensor_attribute attribute, const void *value) { if (attribute == SENSOR_ATTR_OFFSET && - (ch == SENSOR_CHAN_ACCEL_XYZ || ch == SENSOR_CHAN_GYRO_XYZ)) { + (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ || ch.chan_type == SENSOR_CHAN_GYRO_XYZ)) { const struct sensor_three_axis_attribute *attribute_value = value; return bmi160_emul_backend_set_offset(target, ch, attribute_value->values, @@ -524,12 +524,12 @@ static int bmi160_emul_backend_set_attribute(const struct emul *target, enum sen } static int bmi160_emul_backend_get_attribute_metadata(const struct emul *target, - enum sensor_channel ch, + struct sensor_chan_spec ch, enum sensor_attribute attribute, q31_t *min, q31_t *max, q31_t *increment, int8_t *shift) { ARG_UNUSED(target); - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: diff --git a/drivers/sensor/default_rtio_sensor.c b/drivers/sensor/default_rtio_sensor.c index c21736f792aa2f..dec4faacc3b734 100644 --- a/drivers/sensor/default_rtio_sensor.c +++ b/drivers/sensor/default_rtio_sensor.c @@ -13,10 +13,10 @@ LOG_MODULE_REGISTER(sensor_compat, CONFIG_SENSOR_LOG_LEVEL); /* - * Ensure that the size of the generic header aligns with the sensor channel enum. If it doesn't, - * then cores that require aligned memory access will fail to read channel[0]. + * Ensure that the size of the generic header aligns with the sensor channel specifier . If it + * doesn't, then cores that require aligned memory access will fail to read channel[0]. */ -BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(enum sensor_channel)) == 0); +BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(struct sensor_chan_spec)) == 0); static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); @@ -46,12 +46,13 @@ const struct rtio_iodev_api __sensor_iodev_api = { * @param[in] num_channels Number of channels on the @p channels array * @return The number of samples required to read the given channels */ -static inline int compute_num_samples(const enum sensor_channel *channels, size_t num_channels) +static inline int compute_num_samples(const struct sensor_chan_spec *const channels, + size_t num_channels) { int num_samples = 0; for (size_t i = 0; i < num_channels; ++i) { - num_samples += SENSOR_CHANNEL_3_AXIS(channels[i]) ? 3 : 1; + num_samples += SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1; } return num_samples; @@ -68,7 +69,7 @@ static inline int compute_num_samples(const enum sensor_channel *channels, size_ static inline uint32_t compute_header_size(int num_output_samples) { uint32_t size = sizeof(struct sensor_data_generic_header) + - (num_output_samples * sizeof(enum sensor_channel)); + (num_output_samples * sizeof(struct sensor_chan_spec)); return (size + 3) & ~0x3; } @@ -92,12 +93,12 @@ static inline uint32_t compute_min_buf_len(int num_output_samples) * @return Index of the @p channel if found or negative if not found */ static inline int check_header_contains_channel(const struct sensor_data_generic_header *header, - enum sensor_channel channel, int num_channels) + struct sensor_chan_spec chan_spec, int num_channels) { - __ASSERT_NO_MSG(!SENSOR_CHANNEL_3_AXIS(channel)); + __ASSERT_NO_MSG(!SENSOR_CHANNEL_3_AXIS(chan_spec.chan_type)); for (int i = 0; i < num_channels; ++i) { - if (header->channels[i] == channel) { + if (sensor_chan_spec_eq(header->channels[i], chan_spec)) { return i; } } @@ -113,7 +114,7 @@ static inline int check_header_contains_channel(const struct sensor_data_generic static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; - const enum sensor_channel *const channels = cfg->channels; + const struct sensor_chan_spec *const channels = cfg->channels; const int num_output_samples = compute_num_samples(channels, cfg->count); uint32_t min_buf_len = compute_min_buf_len(num_output_samples); uint64_t timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks()); @@ -148,23 +149,34 @@ static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_s /* Populate values, update shift, and set channels */ for (size_t i = 0, sample_idx = 0; i < cfg->count; ++i) { struct sensor_value value[3]; - const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i]) ? 3 : 1; + const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1; /* Get the current channel requested by the user */ - rc = sensor_channel_get(dev, channels[i], value); + rc = sensor_channel_get(dev, channels[i].chan_type, value); if (num_samples == 3) { - header->channels[sample_idx++] = - rc == 0 ? channels[i] - 3 : SENSOR_CHAN_MAX; - header->channels[sample_idx++] = - rc == 0 ? channels[i] - 2 : SENSOR_CHAN_MAX; - header->channels[sample_idx++] = - rc == 0 ? channels[i] - 1 : SENSOR_CHAN_MAX; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type - 3 : SENSOR_CHAN_MAX, + 0 + }; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type - 2 : SENSOR_CHAN_MAX, + 0 + }; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type - 1 : SENSOR_CHAN_MAX, + 0 + }; } else { - header->channels[sample_idx++] = rc == 0 ? channels[i] : SENSOR_CHAN_MAX; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type : SENSOR_CHAN_MAX, + 0 + }; } if (rc != 0) { + LOG_DBG("Failed to get channel (type: %d, index %d), skipping", + channels[i].chan_type, channels[i].chan_idx); continue; } @@ -277,45 +289,41 @@ void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callbac * @param[out] frame_count The number of frames in the buffer (always 1) * @return 0 in all cases */ -static int get_frame_count(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, +static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channel, uint16_t *frame_count) { struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer; - size_t count = 0; - switch (channel) { + switch (channel.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: - channel = SENSOR_CHAN_ACCEL_X; + channel.chan_type = SENSOR_CHAN_ACCEL_X; break; case SENSOR_CHAN_GYRO_XYZ: - channel = SENSOR_CHAN_GYRO_X; + channel.chan_type = SENSOR_CHAN_GYRO_X; break; case SENSOR_CHAN_MAGN_XYZ: - channel = SENSOR_CHAN_MAGN_X; + channel.chan_type = SENSOR_CHAN_MAGN_X; break; default: break; } for (size_t i = 0; i < header->num_channels; ++i) { - if (header->channels[i] == channel) { - if (channel_idx == count) { - *frame_count = 1; - return 0; - } - ++count; + if (sensor_chan_spec_eq(header->channels[i], channel)) { + *frame_count = 1; + return 0; } } return -ENOTSUP; } -int sensor_natively_supported_channel_size_info(enum sensor_channel channel, size_t *base_size, +int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size, size_t *frame_size) { __ASSERT_NO_MSG(base_size != NULL); __ASSERT_NO_MSG(frame_size != NULL); - switch (channel) { + switch (channel.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -391,19 +399,13 @@ int sensor_natively_supported_channel_size_info(enum sensor_channel channel, siz } static int get_q31_value(const struct sensor_data_generic_header *header, const q31_t *values, - enum sensor_channel channel, size_t channel_idx, q31_t *out) + struct sensor_chan_spec chan_spec, q31_t *out) { - size_t count = 0; - for (size_t i = 0; i < header->num_channels; ++i) { - if (channel != header->channels[i]) { - continue; - } - if (count == channel_idx) { + if (sensor_chan_spec_eq(chan_spec, header->channels[i])) { *out = values[i]; return 0; } - ++count; } return -EINVAL; } @@ -419,15 +421,18 @@ static int decode_three_axis(const struct sensor_data_generic_header *header, co data_out->shift = header->shift; data_out->readings[0].timestamp_delta = 0; - rc = get_q31_value(header, values, x, channel_idx, &data_out->readings[0].values[0]); + rc = get_q31_value(header, values, (struct sensor_chan_spec){x, channel_idx}, + &data_out->readings[0].values[0]); if (rc < 0) { return rc; } - rc = get_q31_value(header, values, y, channel_idx, &data_out->readings[0].values[1]); + rc = get_q31_value(header, values, (struct sensor_chan_spec){y, channel_idx}, + &data_out->readings[0].values[1]); if (rc < 0) { return rc; } - rc = get_q31_value(header, values, z, channel_idx, &data_out->readings[0].values[2]); + rc = get_q31_value(header, values, (struct sensor_chan_spec){z, channel_idx}, + &data_out->readings[0].values[2]); if (rc < 0) { return rc; } @@ -435,8 +440,7 @@ static int decode_three_axis(const struct sensor_data_generic_header *header, co } static int decode_q31(const struct sensor_data_generic_header *header, const q31_t *values, - struct sensor_q31_data *data_out, enum sensor_channel channel, - size_t channel_idx) + struct sensor_q31_data *data_out, struct sensor_chan_spec chan_spec) { int rc; @@ -445,7 +449,7 @@ static int decode_q31(const struct sensor_data_generic_header *header, const q31 data_out->shift = header->shift; data_out->readings[0].timestamp_delta = 0; - rc = get_q31_value(header, values, channel, channel_idx, &data_out->readings[0].value); + rc = get_q31_value(header, values, chan_spec, &data_out->readings[0].value); if (rc < 0) { return rc; } @@ -469,7 +473,7 @@ static int decode_q31(const struct sensor_data_generic_header *header, const q31 * @return >0 the number of decoded frames * @return <0 on error */ -static int decode(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, +static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, uint32_t *fit, uint16_t max_count, void *data_out) { const struct sensor_data_generic_header *header = @@ -482,33 +486,37 @@ static int decode(const uint8_t *buffer, enum sensor_channel channel, size_t cha } /* Check for 3d channel mappings */ - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: case SENSOR_CHAN_ACCEL_XYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_ACCEL_X, - SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z, channel_idx); + SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z, + chan_spec.chan_idx); break; case SENSOR_CHAN_GYRO_X: case SENSOR_CHAN_GYRO_Y: case SENSOR_CHAN_GYRO_Z: case SENSOR_CHAN_GYRO_XYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_GYRO_X, - SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z, channel_idx); + SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z, + chan_spec.chan_idx); break; case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: case SENSOR_CHAN_MAGN_XYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_MAGN_X, - SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z, channel_idx); + SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z, + chan_spec.chan_idx); break; case SENSOR_CHAN_POS_DX: case SENSOR_CHAN_POS_DY: case SENSOR_CHAN_POS_DZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_POS_DX, - SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, channel_idx); + SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, + chan_spec.chan_idx); break; case SENSOR_CHAN_DIE_TEMP: case SENSOR_CHAN_AMBIENT_TEMP: @@ -550,7 +558,7 @@ static int decode(const uint8_t *buffer, enum sensor_channel channel, size_t cha case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: - count = decode_q31(header, q, data_out, channel, channel_idx); + count = decode_q31(header, q, data_out, chan_spec); break; default: break; diff --git a/drivers/sensor/f75303/f75303_emul.c b/drivers/sensor/f75303/f75303_emul.c index 7e906af5f04d70..fe1dbc5d3452f0 100644 --- a/drivers/sensor/f75303/f75303_emul.c +++ b/drivers/sensor/f75303/f75303_emul.c @@ -103,7 +103,7 @@ static int f75303_emul_init(const struct emul *target, const struct device *pare return 0; } -static int f75303_emul_set_channel(const struct emul *target, enum sensor_channel chan, +static int f75303_emul_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { struct f75303_emul_data *data = target->data; @@ -112,7 +112,7 @@ static int f75303_emul_set_channel(const struct emul *target, enum sensor_channe int32_t reg_value; uint8_t reg_h, reg_l; - switch ((int32_t)chan) { + switch ((int32_t)ch.chan_type) { case SENSOR_CHAN_AMBIENT_TEMP: reg_h = F75303_LOCAL_TEMP_H; reg_l = F75303_LOCAL_TEMP_L; @@ -139,12 +139,12 @@ static int f75303_emul_set_channel(const struct emul *target, enum sensor_channe return 0; } -static int f75303_emul_get_sample_range(const struct emul *target, enum sensor_channel chan, +static int f75303_emul_get_sample_range(const struct emul *target, struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { - if (chan != SENSOR_CHAN_AMBIENT_TEMP && - chan != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE1 && - chan != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE2) { + if (ch.chan_type != SENSOR_CHAN_AMBIENT_TEMP && + ch.chan_type != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE1 && + ch.chan_type != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE2) { return -ENOTSUP; } diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 758e658816a948..84d11f152c23a8 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -217,7 +217,7 @@ static enum dynamic_command_context current_cmd_ctx = NONE; K_MUTEX_DEFINE(cmd_get_mutex); /* Crate a single common config for one-shot reading */ -static enum sensor_channel iodev_sensor_shell_channels[SENSOR_CHAN_ALL]; +static struct sensor_chan_spec iodev_sensor_shell_channels[SENSOR_CHAN_ALL]; static struct sensor_read_config iodev_sensor_shell_read_config = { .sensor = NULL, .is_streaming = false, @@ -330,23 +330,32 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len : sensor_trigger_table[trigger].name)); } - for (int channel = 0; channel < SENSOR_CHAN_ALL; ++channel) { + + + for (struct sensor_chan_spec ch = {0, 0}; ch.chan_type < SENSOR_CHAN_ALL; ch.chan_type++) { uint32_t fit = 0; size_t base_size; size_t frame_size; size_t channel_idx = 0; uint16_t frame_count; - if (channel == SENSOR_CHAN_ACCEL_X || channel == SENSOR_CHAN_ACCEL_Y || - channel == SENSOR_CHAN_ACCEL_Z || channel == SENSOR_CHAN_GYRO_X || - channel == SENSOR_CHAN_GYRO_Y || channel == SENSOR_CHAN_GYRO_Z || - channel == SENSOR_CHAN_MAGN_X || channel == SENSOR_CHAN_MAGN_Y || - channel == SENSOR_CHAN_MAGN_Z || channel == SENSOR_CHAN_POS_DY || - channel == SENSOR_CHAN_POS_DZ) { + /* Channels with multi-axis equivalents are skipped */ + switch (ch.chan_type) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_POS_DY: + case SENSOR_CHAN_POS_DZ: continue; } - rc = decoder->get_size_info(channel, &base_size, &frame_size); + rc = decoder->get_size_info(ch, &base_size, &frame_size); if (rc != 0) { /* Channel not supported, skipping */ continue; @@ -354,19 +363,18 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len if (base_size > ARRAY_SIZE(decoded_buffer)) { shell_error(ctx->sh, - "Channel (%d) requires %zu bytes to decode, but only %zu are " - "available", - channel, base_size, ARRAY_SIZE(decoded_buffer)); + "Channel (type %d, idx %d) requires %zu bytes to decode, but " + "only %zu are available", + ch.chan_type, ch.chan_idx, base_size, + ARRAY_SIZE(decoded_buffer)); continue; } - while (decoder->get_frame_count(buf, channel, channel_idx, &frame_count) == 0) { + while (decoder->get_frame_count(buf, ch, &frame_count) == 0) { fit = 0; memset(&accumulator_buffer, 0, sizeof(accumulator_buffer)); - while (decoder->decode(buf, channel, channel_idx, &fit, 1, decoded_buffer) > - 0) { - - switch (channel) { + while (decoder->decode(buf, ch, &fit, 1, decoded_buffer) > 0) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: @@ -420,7 +428,7 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len } /* Print the accumulated value average */ - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: @@ -442,10 +450,10 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len data->readings[0].values[2] = (q31_t)(accumulator_buffer.values[2] / accumulator_buffer.count); shell_info(ctx->sh, - "channel idx=%d %s shift=%d num_samples=%d " + "channel type=%d(%s) index=%d shift=%d num_samples=%d " "value=%" PRIsensor_three_axis_data, - channel, sensor_channel_name[channel], - data->shift, accumulator_buffer.count, + ch.chan_type, sensor_channel_name[ch.chan_type], + ch.chan_idx, data->shift, accumulator_buffer.count, PRIsensor_three_axis_data_arg(*data, 0)); break; } @@ -463,10 +471,10 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len accumulator_buffer.values[0] / accumulator_buffer.count; shell_info(ctx->sh, - "channel idx=%d %s num_samples=%d " + "channel type=%d(%s) index=%d num_samples=%d " "value=%" PRIsensor_byte_data(is_near), - channel, sensor_channel_name[channel], - accumulator_buffer.count, + ch.chan_type, sensor_channel_name[ch.chan_type], + ch.chan_idx, accumulator_buffer.count, PRIsensor_byte_data_arg(*data, 0, is_near)); break; } @@ -485,12 +493,13 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len accumulator_buffer.count); shell_info(ctx->sh, - "channel idx=%d %s shift=%d num_samples=%d " + "channel type=%d(%s) index=%d shift=%d num_samples=%d " "value=%" PRIsensor_q31_data, - channel, - (channel >= ARRAY_SIZE(sensor_channel_name)) + ch.chan_type, + (ch.chan_type >= ARRAY_SIZE(sensor_channel_name)) ? "" - : sensor_channel_name[channel], + : sensor_channel_name[ch.chan_type], + ch.chan_idx, data->shift, accumulator_buffer.count, PRIsensor_q31_data_arg(*data, 0)); } @@ -521,12 +530,12 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) } if (argc == 2) { - /* read all channels */ + /* read all channel types */ for (int i = 0; i < ARRAY_SIZE(iodev_sensor_shell_channels); ++i) { if (SENSOR_CHANNEL_3_AXIS(i)) { continue; } - iodev_sensor_shell_channels[count++] = i; + iodev_sensor_shell_channels[count++] = (struct sensor_chan_spec){i, 0}; } } else { /* read specific channels */ @@ -538,7 +547,8 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) shell_error(sh, "Failed to read channel (%s)", argv[i]); continue; } - iodev_sensor_shell_channels[count++] = chan; + iodev_sensor_shell_channels[count++] = + (struct sensor_chan_spec){chan, 0}; } } @@ -570,7 +580,6 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) return 0; } - static int cmd_sensor_attr_set(const struct shell *shell_ptr, size_t argc, char *argv[]) { const struct device *dev; diff --git a/drivers/sensor/tdk/icm42688/icm42688_decoder.c b/drivers/sensor/tdk/icm42688/icm42688_decoder.c index 3dc556ac61c7c3..b71d06b7f3a6df 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_decoder.c +++ b/drivers/sensor/tdk/icm42688/icm42688_decoder.c @@ -178,7 +178,7 @@ static uint8_t icm42688_encode_channel(enum sensor_channel chan) return encode_bmask; } -int icm42688_encode(const struct device *dev, const enum sensor_channel *const channels, +int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *const channels, const size_t num_channels, uint8_t *buf) { struct icm42688_dev_data *data = dev->data; @@ -187,7 +187,7 @@ int icm42688_encode(const struct device *dev, const enum sensor_channel *const c edata->channels = 0; for (int i = 0; i < num_channels; i++) { - edata->channels |= icm42688_encode_channel(channels[i]); + edata->channels |= icm42688_encode_channel(channels[i].chan_type); } edata->header.is_fifo = false; @@ -345,9 +345,8 @@ static uint32_t gyro_period_ns[] = { [ICM42688_GYRO_ODR_32000] = UINT32_C(1000000) / 32, }; -static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int icm42688_fifo_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct icm42688_fifo_data *edata = (const struct icm42688_fifo_data *)buffer; const uint8_t *buffer_end = buffer + sizeof(struct icm42688_fifo_data) + edata->fifo_count; @@ -356,7 +355,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann int count = 0; int rc; - if ((uintptr_t)buffer_end <= *fit || channel_idx != 0) { + if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) { return 0; } @@ -388,7 +387,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann buffer = frame_end; continue; } - if (channel == SENSOR_CHAN_DIE_TEMP) { + if (chan_spec.chan_type == SENSOR_CHAN_DIE_TEMP) { struct sensor_q31_data *data = (struct sensor_q31_data *)data_out; data->shift = 9; @@ -401,7 +400,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann } data->readings[count].temperature = icm42688_read_temperature_from_packet(buffer); - } else if (IS_ACCEL(channel) && has_accel) { + } else if (IS_ACCEL(chan_spec.chan_type) && has_accel) { /* Decode accel */ struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out; @@ -422,7 +421,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann buffer = frame_end; continue; } - } else if (IS_GYRO(channel) && has_gyro) { + } else if (IS_GYRO(chan_spec.chan_type) && has_gyro) { /* Decode gyro */ struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out; @@ -451,9 +450,8 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann return count; } -static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int icm42688_one_shot_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct icm42688_encoded_data *edata = (const struct icm42688_encoded_data *)buffer; const struct icm42688_decoder_header *header = &edata->header; @@ -467,11 +465,11 @@ static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel c if (*fit != 0) { return 0; } - if (max_count == 0 || channel_idx != 0) { + if (max_count == 0 || chan_spec.chan_idx != 0) { return -EINVAL; } - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -570,31 +568,31 @@ static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel c } } -static int icm42688_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int icm42688_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct icm42688_decoder_header *header = (const struct icm42688_decoder_header *)buffer; if (header->is_fifo) { - return icm42688_fifo_decode(buffer, channel, channel_idx, fit, max_count, data_out); + return icm42688_fifo_decode(buffer, chan_spec, fit, max_count, data_out); } - return icm42688_one_shot_decode(buffer, channel, channel_idx, fit, max_count, data_out); + return icm42688_one_shot_decode(buffer, chan_spec, fit, max_count, data_out); } -static int icm42688_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count) +static int icm42688_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) { const struct icm42688_fifo_data *data = (const struct icm42688_fifo_data *)buffer; const struct icm42688_decoder_header *header = &data->header; - if (channel_idx != 0) { + if (chan_spec.chan_idx != 0) { return -ENOTSUP; } if (!header->is_fifo) { - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -643,10 +641,10 @@ static int icm42688_decoder_get_frame_count(const uint8_t *buffer, enum sensor_c return 0; } -static int icm42688_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, +static int icm42688_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size, size_t *frame_size) { - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: diff --git a/drivers/sensor/tdk/icm42688/icm42688_decoder.h b/drivers/sensor/tdk/icm42688/icm42688_decoder.h index 499cf3d0801554..9eadcbcecad574 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_decoder.h +++ b/drivers/sensor/tdk/icm42688/icm42688_decoder.h @@ -36,7 +36,7 @@ struct icm42688_encoded_data { int16_t readings[7]; }; -int icm42688_encode(const struct device *dev, const enum sensor_channel *const channels, +int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *const channels, const size_t num_channels, uint8_t *buf); int icm42688_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); diff --git a/drivers/sensor/tdk/icm42688/icm42688_emul.c b/drivers/sensor/tdk/icm42688/icm42688_emul.c index 5bf60aa4fd12cd..41b6b11ea5f24f 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_emul.c +++ b/drivers/sensor/tdk/icm42688/icm42688_emul.c @@ -295,15 +295,15 @@ static void icm42688_emul_get_gyro_ranges(const struct emul *target, q31_t *lowe *lower = -*upper; } -static int icm42688_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, - q31_t *lower, q31_t *upper, q31_t *epsilon, - int8_t *shift) +static int icm42688_emul_backend_get_sample_range(const struct emul *target, + struct sensor_chan_spec ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) { if (!lower || !upper || !epsilon || !shift) { return -EINVAL; } - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_DIE_TEMP: /* degrees C = ([16-bit signed temp_data register] / 132.48) + 25 */ *shift = 9; @@ -328,7 +328,7 @@ static int icm42688_emul_backend_get_sample_range(const struct emul *target, enu return 0; } -static int icm42688_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int icm42688_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { if (!target || !target->data) { @@ -343,7 +343,7 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen int64_t value_unshifted = shift < 0 ? ((int64_t)*value >> -shift) : ((int64_t)*value << shift); - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_DIE_TEMP: reg_addr = REG_TEMP_DATA1; reg_val = ((value_unshifted - (25 * Q31_SCALE)) * 13248) / (100 * Q31_SCALE); @@ -351,7 +351,7 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: reg_addr = REG_ACCEL_DATA_X1; break; @@ -370,7 +370,7 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen case SENSOR_CHAN_GYRO_X: case SENSOR_CHAN_GYRO_Y: case SENSOR_CHAN_GYRO_Z: - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_GYRO_X: reg_addr = REG_GYRO_DATA_X1; break; diff --git a/drivers/sensor/tdk/icm42688/icm42688_rtio.c b/drivers/sensor/tdk/icm42688/icm42688_rtio.c index ccb9532ee45a2c..ad00fd7abf25ad 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_rtio.c +++ b/drivers/sensor/tdk/icm42688/icm42688_rtio.c @@ -46,7 +46,7 @@ static int icm42688_rtio_sample_fetch(const struct device *dev, int16_t readings static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; - const enum sensor_channel *const channels = cfg->channels; + const struct sensor_chan_spec *const channels = cfg->channels; const size_t num_channels = cfg->count; uint32_t min_buf_len = sizeof(struct icm42688_encoded_data); int rc; diff --git a/include/zephyr/drivers/emul_sensor.h b/include/zephyr/drivers/emul_sensor.h index 9bbbd8d30525ac..265505d5e5aca0 100644 --- a/include/zephyr/drivers/emul_sensor.h +++ b/include/zephyr/drivers/emul_sensor.h @@ -27,16 +27,16 @@ */ __subsystem struct emul_sensor_driver_api { /** Sets a given fractional value for a given sensor channel. */ - int (*set_channel)(const struct emul *target, enum sensor_channel ch, const q31_t *value, - int8_t shift); + int (*set_channel)(const struct emul *target, struct sensor_chan_spec ch, + const q31_t *value, int8_t shift); /** Retrieve a range of sensor values to use with test. */ - int (*get_sample_range)(const struct emul *target, enum sensor_channel ch, q31_t *lower, + int (*get_sample_range)(const struct emul *target, struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift); /** Set the attribute value(s) of a given chanel. */ - int (*set_attribute)(const struct emul *target, enum sensor_channel ch, + int (*set_attribute)(const struct emul *target, struct sensor_chan_spec ch, enum sensor_attribute attribute, const void *value); /** Get metadata about an attribute. */ - int (*get_attribute_metadata)(const struct emul *target, enum sensor_channel ch, + int (*get_attribute_metadata)(const struct emul *target, struct sensor_chan_spec ch, enum sensor_attribute attribute, q31_t *min, q31_t *max, q31_t *increment, int8_t *shift); }; @@ -68,8 +68,9 @@ static inline bool emul_sensor_backend_is_supported(const struct emul *target) * @return -ENOTSUP if no backend API or if channel not supported by emul * @return -ERANGE if provided value is not in the sensor's supported range */ -static inline int emul_sensor_backend_set_channel(const struct emul *target, enum sensor_channel ch, - const q31_t *value, int8_t shift) +static inline int emul_sensor_backend_set_channel(const struct emul *target, + struct sensor_chan_spec ch, const q31_t *value, + int8_t shift) { if (!target || !target->backend_api) { return -ENOTSUP; @@ -101,7 +102,7 @@ static inline int emul_sensor_backend_set_channel(const struct emul *target, enu * */ static inline int emul_sensor_backend_get_sample_range(const struct emul *target, - enum sensor_channel ch, q31_t *lower, + struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { if (!target || !target->backend_api) { @@ -127,7 +128,7 @@ static inline int emul_sensor_backend_get_sample_range(const struct emul *target * @return < 0 on error */ static inline int emul_sensor_backend_set_attribute(const struct emul *target, - enum sensor_channel ch, + struct sensor_chan_spec ch, enum sensor_attribute attribute, const void *value) { @@ -161,7 +162,7 @@ static inline int emul_sensor_backend_set_attribute(const struct emul *target, * @return < 0 on error */ static inline int emul_sensor_backend_get_attribute_metadata(const struct emul *target, - enum sensor_channel ch, + struct sensor_chan_spec ch, enum sensor_attribute attribute, q31_t *min, q31_t *max, q31_t *increment, int8_t *shift) diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index f110a47989648a..2bd6b5c5b892d8 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -418,6 +418,40 @@ typedef int (*sensor_channel_get_t)(const struct device *dev, enum sensor_channel chan, struct sensor_value *val); +/** + * @brief Sensor Channel Specification + * + * A sensor channel specification is a unique identifier per sensor device describing + * a measurement channel. + * + * @note Typically passed by value as the size of a sensor_chan_spec is a single word. + */ +struct sensor_chan_spec { + uint16_t chan_type; /**< A sensor channel type */ + uint16_t chan_idx; /**< A sensor channel index */ +}; + +/** @cond INTERNAL_HIDDEN */ +/* Ensure sensor_chan_spec is sensibly sized to pass by value */ +BUILD_ASSERT(sizeof(struct sensor_chan_spec) <= sizeof(uintptr_t), + "sensor_chan_spec size should be equal or less than the size of a machine word"); +/** @endcond */ + +/** + * @brief Check if channel specs are equivalent + * + * @param chan_spec0 First chan spec + * @param chan_spec1 Second chan spec + * @retval true If equivalent + * @retval false If not equivalent + */ +static inline bool sensor_chan_spec_eq(struct sensor_chan_spec chan_spec0, + struct sensor_chan_spec chan_spec1) +{ + return chan_spec0.chan_type == chan_spec1.chan_type && + chan_spec0.chan_idx == chan_spec1.chan_idx; +} + /** * @brief Decodes a single raw data buffer * @@ -430,13 +464,12 @@ struct sensor_decoder_api { * * @param[in] buffer The buffer provided on the @ref rtio context. * @param[in] channel The channel to get the count for - * @param[in] channel_idx The index of the channel * @param[out] frame_count The number of frames on the buffer (at least 1) * @return 0 on success * @return -ENOTSUP if the channel/channel_idx aren't found */ - int (*get_frame_count)(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count); + int (*get_frame_count)(const uint8_t *buffer, struct sensor_chan_spec channel, + uint16_t *frame_count); /** * @brief Get the size required to decode a given channel @@ -450,7 +483,8 @@ struct sensor_decoder_api { * @return 0 on success * @return -ENOTSUP if the channel is not supported */ - int (*get_size_info)(enum sensor_channel channel, size_t *base_size, size_t *frame_size); + int (*get_size_info)(struct sensor_chan_spec channel, size_t *base_size, + size_t *frame_size); /** * @brief Decode up to @p max_count samples from the buffer @@ -470,7 +504,6 @@ struct sensor_decoder_api { * * @param[in] buffer The buffer provided on the @ref rtio context * @param[in] channel The channel to decode - * @param[in] channel_idx The index of the channel * @param[in,out] fit The current frame iterator * @param[in] max_count The maximum number of channels to decode. * @param[out] data_out The decoded data @@ -478,8 +511,8 @@ struct sensor_decoder_api { * @return >0 the number of decoded frames * @return <0 on error */ - int (*decode)(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, - uint32_t *fit, uint16_t max_count, void *data_out); + int (*decode)(const uint8_t *buffer, struct sensor_chan_spec channel, uint32_t *fit, + uint16_t max_count, void *data_out); /** * @brief Check if the given trigger type is present @@ -518,20 +551,18 @@ struct sensor_decoder_api { struct sensor_decode_context { const struct sensor_decoder_api *decoder; const uint8_t *buffer; - enum sensor_channel channel; - size_t channel_idx; + struct sensor_chan_spec channel; uint32_t fit; }; /** * @brief Initialize a sensor_decode_context */ -#define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_, channel_index_) \ +#define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_type_, channel_index_) \ { \ .decoder = (decoder_), \ .buffer = (buffer_), \ - .channel = (channel_), \ - .channel_idx = (channel_index_), \ + .channel = {.chan_type = (channel_type_), .chan_idx = (channel_index_)}, \ .fit = 0, \ } @@ -545,11 +576,10 @@ struct sensor_decode_context { */ static inline int sensor_decode(struct sensor_decode_context *ctx, void *out, uint16_t max_count) { - return ctx->decoder->decode(ctx->buffer, ctx->channel, ctx->channel_idx, &ctx->fit, - max_count, out); + return ctx->decoder->decode(ctx->buffer, ctx->channel, &ctx->fit, max_count, out); } -int sensor_natively_supported_channel_size_info(enum sensor_channel channel, size_t *base_size, +int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size, size_t *frame_size); /** @@ -582,6 +612,7 @@ struct sensor_stream_trigger { { \ .trigger = (_trigger), .opt = (_opt), \ } + /* * Internal data structure used to store information about the IODevice for async reading and * streaming sensor data. @@ -590,7 +621,7 @@ struct sensor_read_config { const struct device *sensor; const bool is_streaming; union { - enum sensor_channel *const channels; + struct sensor_chan_spec *const channels; struct sensor_stream_trigger *const triggers; }; size_t count; @@ -604,7 +635,8 @@ struct sensor_read_config { * * @code(.c) * SENSOR_DT_READ_IODEV(icm42688_accelgyro, DT_NODELABEL(icm42688), - * SENSOR_CHAN_ACCEL_XYZ, SENSOR_CHAN_GYRO_XYZ); + * { SENSOR_CHAN_ACCEL_XYZ, 0 }, + * { SENSOR_CHAN_GYRO_XYZ, 0 }); * * int main(void) { * sensor_read(&icm42688_accelgyro, &rtio); @@ -612,7 +644,7 @@ struct sensor_read_config { * @endcode */ #define SENSOR_DT_READ_IODEV(name, dt_node, ...) \ - static enum sensor_channel _CONCAT(__channel_array_, name)[] = {__VA_ARGS__}; \ + static struct sensor_chan_spec _CONCAT(__channel_array_, name)[] = {__VA_ARGS__}; \ static struct sensor_read_config _CONCAT(__sensor_read_config_, name) = { \ .sensor = DEVICE_DT_GET(dt_node), \ .is_streaming = false, \ @@ -886,10 +918,10 @@ struct __attribute__((__packed__)) sensor_data_generic_header { int8_t shift; /* This padding is needed to make sure that the 'channels' field is aligned */ - int8_t _padding[sizeof(enum sensor_channel) - 1]; + int8_t _padding[sizeof(struct sensor_chan_spec) - 1]; /* Channels present in the frame */ - enum sensor_channel channels[0]; + struct sensor_chan_spec channels[0]; }; /** @@ -949,12 +981,12 @@ static inline int z_impl_sensor_get_decoder(const struct device *dev, * @return < 0 on error */ __syscall int sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor, - const enum sensor_channel *channels, + const struct sensor_chan_spec *channels, size_t num_channels); static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor, - const enum sensor_channel *channels, + const struct sensor_chan_spec *channels, size_t num_channels) { struct sensor_read_config *cfg = (struct sensor_read_config *)iodev->data; @@ -964,7 +996,7 @@ static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, } cfg->sensor = sensor; - memcpy(cfg->channels, channels, num_channels * sizeof(enum sensor_channel)); + memcpy(cfg->channels, channels, num_channels * sizeof(struct sensor_chan_spec)); cfg->count = num_channels; return 0; } diff --git a/tests/drivers/build_all/sensor/src/generic_test.c b/tests/drivers/build_all/sensor/src/generic_test.c index 2d5e0c1df86a9e..30d4d72f5676de 100644 --- a/tests/drivers/build_all/sensor/src/generic_test.c +++ b/tests/drivers/build_all/sensor/src/generic_test.c @@ -30,7 +30,7 @@ union sensor_data_union { * Set up an RTIO context that can be shared for all sensors */ -static enum sensor_channel iodev_all_channels[SENSOR_CHAN_ALL]; +static struct sensor_chan_spec iodev_all_channels[SENSOR_CHAN_ALL]; static struct sensor_read_config iodev_read_config = { .channels = iodev_all_channels, .max = SENSOR_CHAN_ALL, @@ -110,8 +110,9 @@ static void run_generic_test(const struct device *dev) q31_t lower, upper; int8_t shift; + struct sensor_chan_spec ch_spec = {.chan_type = ch, .chan_idx = 0}; - if (emul_sensor_backend_get_sample_range(emul, ch, &lower, &upper, + if (emul_sensor_backend_get_sample_range(emul, ch_spec, &lower, &upper, &channel_table[ch].epsilon, &shift) == 0) { /* This channel is supported */ channel_table[ch].supported = true; @@ -120,7 +121,7 @@ static void run_generic_test(const struct device *dev) channel_table[ch].epsilon, shift); /* Add to the list of channels to read */ - iodev_all_channels[iodev_read_config.count++] = ch; + iodev_all_channels[iodev_read_config.count++].chan_type = ch; /* Generate a set of CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS test * values. @@ -155,16 +156,18 @@ static void run_generic_test(const struct device *dev) /* Set this iteration's expected values in emul for every supported channel */ for (size_t i = 0; i < iodev_read_config.count; i++) { - enum sensor_channel ch = iodev_all_channels[i]; + struct sensor_chan_spec ch_spec = iodev_all_channels[i]; rv = emul_sensor_backend_set_channel( - emul, ch, &channel_table[ch].expected_values[iteration], - channel_table[ch].expected_value_shift); - zassert_ok( - rv, - "Cannot set value 0x%08x on channel %d (error %d, iteration %d/%d)", - channel_table[i].expected_values[iteration], ch, rv, iteration + 1, - CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS); + emul, ch_spec, + &channel_table[ch_spec.chan_type].expected_values[iteration], + channel_table[ch_spec.chan_type].expected_value_shift); + zassert_ok(rv, + "Cannot set value 0x%08x on channel (type: %d, index: %d) " + "(error %d, iteration %d/%d)", + channel_table[i].expected_values[iteration], ch_spec.chan_type, + ch_spec.chan_idx, rv, iteration + 1, + CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS); } /* Perform the actual sensor read */ diff --git a/tests/drivers/sensor/bmi160/src/fixture.c b/tests/drivers/sensor/bmi160/src/fixture.c index a97be2cb7840bb..3f36744e3d1f81 100644 --- a/tests/drivers/sensor/bmi160/src/fixture.c +++ b/tests/drivers/sensor/bmi160/src/fixture.c @@ -33,7 +33,9 @@ static void sensor_bmi160_setup_emulator(const struct device *dev, const struct zassert_ok(sensor_attr_set(dev, SENSOR_CHAN_GYRO_XYZ, SENSOR_ATTR_FULL_SCALE, &scale)); for (size_t i = 0; i < ARRAY_SIZE(values); ++i) { - zassert_ok(emul_sensor_backend_set_channel(emulator, values[i].channel, + struct sensor_chan_spec chan_spec = {.chan_type = values[i].channel, .chan_idx = 0}; + + zassert_ok(emul_sensor_backend_set_channel(emulator, chan_spec, &values[i].value, 3)); } } From 5d4553b95b7df44ab86c858b8267038d640f24ce Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0873/1389] drivers: apic_tsc: Use toolchain cpuid() We have already code using toolchain provided __get_cpuid(), clean up apic_tsc and make it consistent with the rest of the code. Signed-off-by: Andrei Emeltchenko --- drivers/timer/apic_tsc.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 6b4035d976da69..3c6ab1e0a6dff9 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -2,7 +2,11 @@ * Copyright (c) 2021 Intel Corporation * SPDX-License-Identifier: Apache-2.0 */ + +#include /* Header provided by the toolchain. */ + #include +#include #include #include #include @@ -149,28 +153,21 @@ void smp_timer_init(void) irq_enable(timer_irq()); } -static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) -{ - __asm__ volatile("cpuid" - : "=b"(*ebx), "=c"(*ecx), "=d"(*edx) - : "a"(*eax), "c"(*ecx)); -} - static int sys_clock_driver_init(void) { #ifdef CONFIG_ASSERT uint32_t eax, ebx, ecx, edx; - eax = 1; ecx = 0; - cpuid(&eax, &ebx, &ecx, &edx); + ecx = 0; /* prevent compiler warning */ + __get_cpuid(CPUID_BASIC_INFO_1, &eax, &ebx, &ecx, &edx); __ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support"); - eax = 0x80000007; ecx = 0; - cpuid(&eax, &ebx, &ecx, &edx); + edx = 0; /* prevent compiler warning */ + __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); __ASSERT((edx & BIT(8)) != 0, "No Invariant TSC support"); - eax = 7; ecx = 0; - cpuid(&eax, &ebx, &ecx, &edx); + ebx = 0; /* prevent compiler warning */ + __get_cpuid_count(CPUID_EXTENDED_FEATURES_LVL, 0, &eax, &ebx, &ecx, &edx); __ASSERT((ebx & BIT(1)) != 0, "No TSC_ADJUST MSR support"); #endif From 05b3c18cbfa77e14747c9376d2542731e3493426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0874/1389] tests: drivers: uart: uart_mix_fifo_poll: Add nrf54h20dk overlays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlays for nrf54h20dk (cpuapp and cpurad). Signed-off-by: Krzysztof Chruściński --- .../boards/nrf54h20dk_nrf54h20_common.dtsi | 36 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 11 ++++++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 16 +++++++++ .../uart/uart_mix_fifo_poll/testcase.yaml | 14 ++++++++ 4 files changed, 77 insertions(+) create mode 100644 tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_common.dtsi create mode 100644 tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 00000000000000..c102d617f900d1 --- /dev/null +++ b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&pinctrl { + uart137_default_alt: uart137_default_alt { + group1 { + psels = , + , + , + ; + }; + }; + + uart137_sleep_alt: uart137_sleep_alt { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +dut: &uart137 { + status = "okay"; + pinctrl-0 = <&uart137_default_alt>; + pinctrl-1 = <&uart137_sleep_alt>; + pinctrl-names = "default", "sleep"; + current-speed = <115200>; + hw-flow-control; +}; + +/* Use timer137 as only this one can generate interrupts on cpusys. */ +counter_dev: &timer137 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..c6ff4eb77af378 --- /dev/null +++ b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&dut { + memory-regions = <&cpuapp_dma_region>; +}; + +&grtc { + interrupts = <109 2>; +}; diff --git a/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000000..2bde29c9fc51e3 --- /dev/null +++ b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&cpurad_dma_region { + /* Default space is not enough. */ + reg = <0x1e80 0x100>; +}; + +&dut { + memory-regions = <&cpurad_dma_region>; +}; + +&grtc { + interrupts = <109 2>; +}; diff --git a/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml b/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml index 7736e085f3429f..8be2429492e914 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml +++ b/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml @@ -9,6 +9,8 @@ common: - nrf9160dk/nrf9160 - nrf5340dk/nrf5340/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad - nrf52_bsim integration_platforms: - nrf52840dk/nrf52840 @@ -79,6 +81,10 @@ tests: - CONFIG_UART_ASYNC_API=n - CONFIG_UART_0_ENHANCED_POLL_OUT=n - CONFIG_UART_NRFX_UARTE_LEGACY_SHIM=y + platform_exclude: + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad drivers.uart.legacy.uart_mix_poll_fifo: extra_configs: @@ -86,6 +92,10 @@ tests: - CONFIG_UART_0_INTERRUPT_DRIVEN=y - CONFIG_UART_0_ENHANCED_POLL_OUT=n - CONFIG_UART_NRFX_UARTE_LEGACY_SHIM=y + platform_exclude: + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad drivers.uart.legacy.uart_mix_poll_async_api: extra_configs: @@ -97,3 +107,7 @@ tests: - CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 - CONFIG_NRFX_TIMER2=y - CONFIG_UART_NRFX_UARTE_LEGACY_SHIM=y + platform_exclude: + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad From 8607516e6a12af08f2cf70d00ed87371209b2d76 Mon Sep 17 00:00:00 2001 From: Pete Skeggs Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0875/1389] net: lib: coap_client: Improve cancel function Improve coap_client_cancel_requests(). Ensure it can be called from a callback. Report error to waiting callbacks. Clear active flag. This is useful when the network becomes unavailable or prior to disconnecting in order to save power. Signed-off-by: Pete Skeggs --- include/zephyr/net/coap_client.h | 7 ++-- subsys/net/lib/coap/coap_client.c | 55 +++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index 819559e9d936f2..3997a394f5809a 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -84,6 +84,7 @@ struct coap_client_internal_request { uint32_t last_id; uint8_t request_tkl; bool request_ongoing; + atomic_t in_callback; struct coap_block_context recv_blk_ctx; struct coap_block_context send_blk_ctx; struct coap_pending pending; @@ -140,14 +141,14 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr /** * @brief Cancel all current requests. * - * This is intended for canceling long-running requests (e.g. GETs with the OBSERVE option set) - * which has gone stale for some reason. + * This is intended for canceling long-running requests (e.g. GETs with the OBSERVE option set, + * or a block transfer) which have gone stale for some reason. It is also intended for responding + * to network connectivity issues. * * @param client Client instance. */ void coap_client_cancel_requests(struct coap_client *client); - /** * @} */ diff --git a/subsys/net/lib/coap/coap_client.c b/subsys/net/lib/coap/coap_client.c index 33b66acf7dce92..f80c440a839ffd 100644 --- a/subsys/net/lib/coap/coap_client.c +++ b/subsys/net/lib/coap/coap_client.c @@ -27,6 +27,7 @@ static atomic_t coap_client_recv_active; static int send_request(int sock, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { + LOG_HEXDUMP_DBG(buf, len, "Send CoAP Request:"); if (addrlen == 0) { return zsock_sendto(sock, buf, len, flags, NULL, 0); } else { @@ -37,11 +38,17 @@ static int send_request(int sock, const void *buf, size_t len, int flags, static int receive(int sock, void *buf, size_t max_len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { + ssize_t err; + if (*addrlen == 0) { - return zsock_recvfrom(sock, buf, max_len, flags, NULL, NULL); + err = zsock_recvfrom(sock, buf, max_len, flags, NULL, NULL); } else { - return zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen); + err = zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen); + } + if (err > 0) { + LOG_HEXDUMP_DBG(buf, err, "Receive CoAP Response:"); } + return err; } static void reset_block_contexts(struct coap_client_internal_request *request) @@ -282,6 +289,7 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr struct coap_client_internal_request *internal_req = get_free_request(client); if (internal_req == NULL) { + LOG_DBG("No more free requests"); return -EAGAIN; } @@ -320,6 +328,7 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr reset_internal_request(internal_req); if (k_mutex_lock(&client->send_mutex, K_NO_WAIT)) { + LOG_DBG("Could not immediately lock send_mutex"); return -EAGAIN; } @@ -380,8 +389,13 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr static void report_callback_error(struct coap_client_internal_request *internal_req, int error_code) { if (internal_req->coap_request.cb) { - internal_req->coap_request.cb(error_code, 0, NULL, 0, true, - internal_req->coap_request.user_data); + if (!atomic_set(&internal_req->in_callback, 1)) { + internal_req->coap_request.cb(error_code, 0, NULL, 0, true, + internal_req->coap_request.user_data); + atomic_clear(&internal_req->in_callback); + } else { + LOG_DBG("Cannot call the callback; already in it."); + } } } @@ -400,7 +414,9 @@ static int resend_request(struct coap_client *client, { int ret = 0; - if (internal_req->pending.timeout != 0 && coap_pending_cycle(&internal_req->pending)) { + if (internal_req->request_ongoing && + internal_req->pending.timeout != 0 && + coap_pending_cycle(&internal_req->pending)) { LOG_ERR("Timeout in poll, retrying send"); /* Reset send block context as it was updated in previous init from packet */ @@ -765,10 +781,16 @@ static int handle_response(struct coap_client *client, const struct coap_packet /* Call user callback */ if (internal_req->coap_request.cb) { - internal_req->coap_request.cb(response_code, internal_req->offset, payload, - payload_len, last_block, - internal_req->coap_request.user_data); - + if (!atomic_set(&internal_req->in_callback, 1)) { + internal_req->coap_request.cb(response_code, internal_req->offset, payload, + payload_len, last_block, + internal_req->coap_request.user_data); + atomic_clear(&internal_req->in_callback); + } + if (!internal_req->request_ongoing) { + /* User callback must have called coap_client_cancel_requests(). */ + goto fail; + } /* Update the offset for next callback in a blockwise transfer */ if (blockwise_transfer) { internal_req->offset += payload_len; @@ -820,8 +842,21 @@ static int handle_response(struct coap_client *client, const struct coap_packet void coap_client_cancel_requests(struct coap_client *client) { for (int i = 0; i < ARRAY_SIZE(client->requests); i++) { - client->requests[i].request_ongoing = false; + if (client->requests[i].request_ongoing == true) { + LOG_DBG("Cancelling request %d", i); + /* Report the request was cancelled. This will be skipped if + * this function was called from the user's callback so we + * do not reenter it. In that case, the user knows their + * request was cancelled anyway. + */ + report_callback_error(&client->requests[i], -ECANCELED); + client->requests[i].request_ongoing = false; + } } + atomic_clear(&coap_client_recv_active); + + /* Wait until after zsock_poll() can time out and return. */ + k_sleep(K_MSEC(COAP_PERIODIC_TIMEOUT)); } void coap_client_recv(void *coap_cl, void *a, void *b) From 66a6c6196ae94e4a3b3dcfd5f6d176b561250de7 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0876/1389] samples: drivers: spi_flash: Add nRF54H20DK support Verified on nRF54H20DK, useful for testing external flash access. Signed-off-by: Chaitanya Tata --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 samples/drivers/spi_flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/samples/drivers/spi_flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/spi_flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..d03419690bdf61 --- /dev/null +++ b/samples/drivers/spi_flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25uw63 { + status = "okay"; +}; + + +/ { + aliases { + spi-flash0 = &mx25uw63; + }; +}; From 0046d6dd629368caa3b572684b952d86837b411f Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0877/1389] drivers: nsos: initial support for getsockopt() and setsockopt() Add initial support for getsockopt() and setsockopt() on SOL_SOCKET level. Signed-off-by: Marcin Niestroj --- drivers/net/nsos.h | 4 + drivers/net/nsos_adapt.c | 164 ++++++++++++++++++++ drivers/net/nsos_socket.h | 83 ++++++++++ drivers/net/nsos_sockets.c | 305 +++++++++++++++++++++++++++++++++++++ 4 files changed, 556 insertions(+) create mode 100644 drivers/net/nsos_socket.h diff --git a/drivers/net/nsos.h b/drivers/net/nsos.h index 1ba4584a4a6c7d..bafb40542e040b 100644 --- a/drivers/net/nsos.h +++ b/drivers/net/nsos.h @@ -126,6 +126,10 @@ int nsos_adapt_sendto(int fd, const void *buf, size_t len, int flags, int nsos_adapt_sendmsg(int fd, const struct nsos_mid_msghdr *msg_mid, int flags); int nsos_adapt_recvfrom(int fd, void *buf, size_t len, int flags, struct nsos_mid_sockaddr *addr, size_t *addrlen); +int nsos_adapt_getsockopt(int fd, int level, int optname, + void *optval, size_t *optlen); +int nsos_adapt_setsockopt(int fd, int level, int optname, + const void *optval, size_t optlen); void nsos_adapt_poll_add(struct nsos_mid_pollfd *pollfd); void nsos_adapt_poll_remove(struct nsos_mid_pollfd *pollfd); diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 86aaa743681dbf..104aa392fa826e 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -10,6 +10,8 @@ * Linux (bottom) side of NSOS (Native Simulator Offloaded Sockets). */ +#define _DEFAULT_SOURCE + #include #include #include @@ -25,6 +27,7 @@ #include "nsos_errno.h" #include "nsos_fcntl.h" #include "nsos_netdb.h" +#include "nsos_socket.h" #include "board_soc.h" #include "irq_ctrl.h" @@ -511,6 +514,167 @@ int nsos_adapt_recvfrom(int fd, void *buf, size_t len, int flags, return ret; } +static int nsos_adapt_getsockopt_int(int fd, int level, int optname, + void *optval, size_t *nsos_mid_optlen) +{ + socklen_t optlen = *nsos_mid_optlen; + int ret; + + ret = getsockopt(fd, level, optname, optval, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + *nsos_mid_optlen = optlen; + + return 0; +} + +int nsos_adapt_getsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, + void *nsos_mid_optval, size_t *nsos_mid_optlen) +{ + switch (nsos_mid_level) { + case NSOS_MID_SOL_SOCKET: + switch (nsos_mid_optname) { + case NSOS_MID_SO_ERROR: { + int err; + socklen_t optlen = sizeof(err); + int ret; + + ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + *(int *)nsos_mid_optval = errno_to_nsos_mid(err); + + return 0; + } + case NSOS_MID_SO_TYPE: { + int type; + socklen_t optlen = sizeof(type); + int ret; + int err; + + ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + err = socket_type_to_nsos_mid(type, nsos_mid_optval); + if (err) { + return err; + } + + return 0; + } + case NSOS_MID_SO_PROTOCOL: { + int proto; + socklen_t optlen = sizeof(proto); + int ret; + int err; + + ret = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &proto, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + err = socket_proto_to_nsos_mid(proto, nsos_mid_optval); + if (err) { + return err; + } + + return 0; + } + case NSOS_MID_SO_DOMAIN: { + int family; + socklen_t optlen = sizeof(family); + int ret; + int err; + + ret = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &family, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + err = socket_family_to_nsos_mid(family, nsos_mid_optval); + if (err) { + return err; + } + + return 0; + } + case NSOS_MID_SO_RCVBUF: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_SNDBUF: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEADDR: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEPORT: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_LINGER: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_LINGER, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_KEEPALIVE: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, + nsos_mid_optval, nsos_mid_optlen); + } + } + + return -NSOS_MID_EOPNOTSUPP; +} + +static int nsos_adapt_setsockopt_int(int fd, int level, int optname, + const void *optval, size_t optlen) +{ + int ret; + + ret = setsockopt(fd, level, optname, optval, optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; +} + +int nsos_adapt_setsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, + const void *nsos_mid_optval, size_t nsos_mid_optlen) +{ + switch (nsos_mid_level) { + case NSOS_MID_SOL_SOCKET: + switch (nsos_mid_optname) { + case NSOS_MID_SO_PRIORITY: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, + nsos_mid_optval, nsos_mid_optlen); + + case NSOS_MID_SO_RCVBUF: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_SNDBUF: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEADDR: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEPORT: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_LINGER: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_LINGER, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_KEEPALIVE: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, + nsos_mid_optval, nsos_mid_optlen); + } + } + + return -NSOS_MID_EOPNOTSUPP; +} + #define MAP_POLL_EPOLL(_event_from, _event_to) \ if (events_from & (_event_from)) { \ events_from &= ~(_event_from); \ diff --git a/drivers/net/nsos_socket.h b/drivers/net/nsos_socket.h new file mode 100644 index 00000000000000..dbc14997559c00 --- /dev/null +++ b/drivers/net/nsos_socket.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2024 Marcin Niestroj + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DRIVERS_NET_NSOS_SOCKET_H__ +#define __DRIVERS_NET_NSOS_SOCKET_H__ + +/** + * @name Socket level options (NSOS_MID_SOL_SOCKET) + * @{ + */ +/** Socket-level option */ +#define NSOS_MID_SOL_SOCKET 1 + +/* Socket options for NSOS_MID_SOL_SOCKET level */ + +/** Recording debugging information (ignored, for compatibility) */ +#define NSOS_MID_SO_DEBUG 1 +/** address reuse */ +#define NSOS_MID_SO_REUSEADDR 2 +/** Type of the socket */ +#define NSOS_MID_SO_TYPE 3 +/** Async error */ +#define NSOS_MID_SO_ERROR 4 +/** Bypass normal routing and send directly to host (ignored, for compatibility) */ +#define NSOS_MID_SO_DONTROUTE 5 +/** Transmission of broadcast messages is supported (ignored, for compatibility) */ +#define NSOS_MID_SO_BROADCAST 6 + +/** Size of socket send buffer */ +#define NSOS_MID_SO_SNDBUF 7 +/** Size of socket recv buffer */ +#define NSOS_MID_SO_RCVBUF 8 + +/** Enable sending keep-alive messages on connections */ +#define NSOS_MID_SO_KEEPALIVE 9 +/** Place out-of-band data into receive stream (ignored, for compatibility) */ +#define NSOS_MID_SO_OOBINLINE 10 +/** Socket priority */ +#define NSOS_MID_SO_PRIORITY 12 +/** Socket lingers on close (ignored, for compatibility) */ +#define NSOS_MID_SO_LINGER 13 +/** Allow multiple sockets to reuse a single port */ +#define NSOS_MID_SO_REUSEPORT 15 + +/** Receive low watermark (ignored, for compatibility) */ +#define NSOS_MID_SO_RCVLOWAT 18 +/** Send low watermark (ignored, for compatibility) */ +#define NSOS_MID_SO_SNDLOWAT 19 + +/** + * Receive timeout + * Applies to receive functions like recv(), but not to connect() + */ +#define NSOS_MID_SO_RCVTIMEO 20 +/** Send timeout */ +#define NSOS_MID_SO_SNDTIMEO 21 + +/** Bind a socket to an interface */ +#define NSOS_MID_SO_BINDTODEVICE 25 + +/** Socket accepts incoming connections (ignored, for compatibility) */ +#define NSOS_MID_SO_ACCEPTCONN 30 + +/** Timestamp TX packets */ +#define NSOS_MID_SO_TIMESTAMPING 37 +/** Protocol used with the socket */ +#define NSOS_MID_SO_PROTOCOL 38 + +/** Domain used with SOCKET */ +#define NSOS_MID_SO_DOMAIN 39 + +/** Enable SOCKS5 for Socket */ +#define NSOS_MID_SO_SOCKS5 60 + +/** Socket TX time (when the data should be sent) */ +#define NSOS_MID_SO_TXTIME 61 + +/** @} */ + +#endif /* __DRIVERS_NET_NSOS_SOCKET_H__ */ diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index c1773425995494..24d686f536a1b5 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -28,6 +28,7 @@ #include "nsos_errno.h" #include "nsos_fcntl.h" #include "nsos_netdb.h" +#include "nsos_socket.h" #include "nsi_host_trampolines.h" @@ -795,6 +796,308 @@ static ssize_t nsos_recvmsg(void *obj, struct msghdr *msg, int flags) return -1; } +static int socket_type_from_nsos_mid(int type_mid, int *type) +{ + switch (type_mid) { + case NSOS_MID_SOCK_STREAM: + *type = SOCK_STREAM; + break; + case NSOS_MID_SOCK_DGRAM: + *type = SOCK_DGRAM; + break; + case NSOS_MID_SOCK_RAW: + *type = SOCK_RAW; + break; + default: + return -NSOS_MID_ESOCKTNOSUPPORT; + } + + return 0; +} + +static int socket_proto_from_nsos_mid(int proto_mid, int *proto) +{ + switch (proto_mid) { + case NSOS_MID_IPPROTO_IP: + *proto = IPPROTO_IP; + break; + case NSOS_MID_IPPROTO_ICMP: + *proto = IPPROTO_ICMP; + break; + case NSOS_MID_IPPROTO_IGMP: + *proto = IPPROTO_IGMP; + break; + case NSOS_MID_IPPROTO_IPIP: + *proto = IPPROTO_IPIP; + break; + case NSOS_MID_IPPROTO_TCP: + *proto = IPPROTO_TCP; + break; + case NSOS_MID_IPPROTO_UDP: + *proto = IPPROTO_UDP; + break; + case NSOS_MID_IPPROTO_IPV6: + *proto = IPPROTO_IPV6; + break; + case NSOS_MID_IPPROTO_RAW: + *proto = IPPROTO_RAW; + break; + default: + return -NSOS_MID_EPROTONOSUPPORT; + } + + return 0; +} + +static int socket_family_from_nsos_mid(int family_mid, int *family) +{ + switch (family_mid) { + case NSOS_MID_AF_UNSPEC: + *family = AF_UNSPEC; + break; + case NSOS_MID_AF_INET: + *family = AF_INET; + break; + case NSOS_MID_AF_INET6: + *family = AF_INET6; + break; + default: + return -NSOS_MID_EAFNOSUPPORT; + } + + return 0; +} + +static int nsos_getsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int nsos_mid_optname, + void *optval, socklen_t *optlen) +{ + size_t nsos_mid_optlen = sizeof(int); + int err; + + if (*optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_KEEPALIVE, optval, &nsos_mid_optlen); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + *optlen = nsos_mid_optlen; + + return 0; +} + +static int nsos_getsockopt(void *obj, int level, int optname, + void *optval, socklen_t *optlen) +{ + struct nsos_socket *sock = obj; + + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_ERROR: { + int nsos_mid_err; + int err; + + if (*optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_ERROR, &nsos_mid_err, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + *(int *)optval = errno_from_nsos_mid(nsos_mid_err); + + return 0; + } + case SO_TYPE: { + int nsos_mid_type; + int err; + + if (*optlen != sizeof(nsos_mid_type)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_TYPE, &nsos_mid_type, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + err = socket_type_from_nsos_mid(nsos_mid_type, optval); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_PROTOCOL: { + int nsos_mid_proto; + int err; + + if (*optlen != sizeof(nsos_mid_proto)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_PROTOCOL, &nsos_mid_proto, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + err = socket_proto_from_nsos_mid(nsos_mid_proto, optval); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_DOMAIN: { + int nsos_mid_family; + int err; + + if (*optlen != sizeof(nsos_mid_family)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_DOMAIN, &nsos_mid_family, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + err = socket_family_from_nsos_mid(nsos_mid_family, optval); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_RCVBUF: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF, + optval, optlen); + case SO_SNDBUF: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_SNDBUF, + optval, optlen); + case SO_REUSEADDR: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEADDR, + optval, optlen); + case SO_REUSEPORT: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEPORT, + optval, optlen); + case SO_KEEPALIVE: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, + optval, optlen); + } + } + + errno = EOPNOTSUPP; + return -1; +} + +static int nsos_setsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int nsos_mid_optname, + const void *optval, socklen_t optlen) +{ + int err; + + if (optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_setsockopt(sock->pollfd.fd, nsos_mid_level, nsos_mid_optname, + optval, optlen); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; +} + +static int nsos_setsockopt(void *obj, int level, int optname, + const void *optval, socklen_t optlen) +{ + struct nsos_socket *sock = obj; + + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_PRIORITY: { + int nsos_mid_priority; + int err; + + if (optlen != sizeof(uint8_t)) { + errno = EINVAL; + return -1; + } + + nsos_mid_priority = *(uint8_t *)optval; + + err = nsos_adapt_setsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_PRIORITY, &nsos_mid_priority, + sizeof(nsos_mid_priority)); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_RCVBUF: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF, + optval, optlen); + case SO_SNDBUF: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_SNDBUF, + optval, optlen); + case SO_REUSEADDR: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEADDR, + optval, optlen); + case SO_REUSEPORT: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEPORT, + optval, optlen); + case SO_LINGER: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_LINGER, + optval, optlen); + case SO_KEEPALIVE: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, + optval, optlen); + } + } + + errno = EOPNOTSUPP; + return -1; +} + static const struct socket_op_vtable nsos_socket_fd_op_vtable = { .fd_vtable = { .read = nsos_read, @@ -810,6 +1113,8 @@ static const struct socket_op_vtable nsos_socket_fd_op_vtable = { .sendmsg = nsos_sendmsg, .recvfrom = nsos_recvfrom, .recvmsg = nsos_recvmsg, + .getsockopt = nsos_getsockopt, + .setsockopt = nsos_setsockopt, }; static bool nsos_is_supported(int family, int type, int proto) From b65174bb7651a6b4bd00ae4c5f6d8386c711ac29 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0878/1389] drivers: nsos: support setsockopt(SO_RCVTIMEO) Handle timeout on receive that is configured using SO_RCVTIMEO. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_adapt.c | 16 ++++++++++++++++ drivers/net/nsos_socket.h | 7 +++++++ drivers/net/nsos_sockets.c | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 104aa392fa826e..d3f787762c468e 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -651,6 +651,22 @@ int nsos_adapt_setsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_RCVTIMEO: { + const struct nsos_mid_timeval *nsos_mid_tv = nsos_mid_optval; + struct timeval tv = { + .tv_sec = nsos_mid_tv->tv_sec, + .tv_usec = nsos_mid_tv->tv_usec, + }; + int ret; + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, + &tv, sizeof(tv)); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; + } case NSOS_MID_SO_RCVBUF: return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, nsos_mid_optval, nsos_mid_optlen); diff --git a/drivers/net/nsos_socket.h b/drivers/net/nsos_socket.h index dbc14997559c00..10db34cdcf11ed 100644 --- a/drivers/net/nsos_socket.h +++ b/drivers/net/nsos_socket.h @@ -7,6 +7,8 @@ #ifndef __DRIVERS_NET_NSOS_SOCKET_H__ #define __DRIVERS_NET_NSOS_SOCKET_H__ +#include + /** * @name Socket level options (NSOS_MID_SOL_SOCKET) * @{ @@ -78,6 +80,11 @@ /** Socket TX time (when the data should be sent) */ #define NSOS_MID_SO_TXTIME 61 +struct nsos_mid_timeval { + int64_t tv_sec; + int64_t tv_usec; +}; + /** @} */ #endif /* __DRIVERS_NET_NSOS_SOCKET_H__ */ diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 24d686f536a1b5..5dd528e91013c8 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -42,6 +42,8 @@ struct nsos_socket { struct nsos_mid_pollfd pollfd; struct k_poll_signal poll; + k_timeout_t recv_timeout; + sys_dnode_t node; }; @@ -180,6 +182,7 @@ static int nsos_socket_create(int family, int type, int proto) } sock->fd = fd; + sock->recv_timeout = K_FOREVER; sock->pollfd.fd = nsos_adapt_socket(family_mid, type_mid, proto_mid); if (sock->pollfd.fd < 0) { @@ -550,7 +553,7 @@ static int nsos_wait_for_pollin(struct nsos_socket *sock) return ret; } - ret = k_poll(poll_events, ARRAY_SIZE(poll_events), K_FOREVER); + ret = k_poll(poll_events, ARRAY_SIZE(poll_events), sock->recv_timeout); if (ret != 0 && ret != -EAGAIN && ret != -EINTR) { return ret; } @@ -1067,6 +1070,35 @@ static int nsos_setsockopt(void *obj, int level, int optname, return 0; } + case SO_RCVTIMEO: { + const struct zsock_timeval *tv = optval; + struct nsos_mid_timeval nsos_mid_tv; + int err; + + if (optlen != sizeof(struct zsock_timeval)) { + errno = EINVAL; + return -1; + } + + nsos_mid_tv.tv_sec = tv->tv_sec; + nsos_mid_tv.tv_usec = tv->tv_usec; + + err = nsos_adapt_setsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_RCVTIMEO, &nsos_mid_tv, + sizeof(nsos_mid_tv)); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + if (tv->tv_sec == 0 && tv->tv_usec == 0) { + sock->recv_timeout = K_FOREVER; + } else { + sock->recv_timeout = K_USEC(tv->tv_sec * 1000000LL + tv->tv_usec); + } + + return 0; + } case SO_RCVBUF: return nsos_setsockopt_int(sock, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF, From 7218516f96f61d2c23f993cd64b9fe1733324393 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0879/1389] drivers: nsos: support ioctl(FIONREAD) This further increases compatibility with tests defined in 'tests/net/socket/udp/'. Signed-off-by: Marcin Niestroj --- drivers/net/nsos.h | 2 ++ drivers/net/nsos_adapt.c | 13 +++++++++++++ drivers/net/nsos_sockets.c | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/drivers/net/nsos.h b/drivers/net/nsos.h index bafb40542e040b..911e49dff2c3e5 100644 --- a/drivers/net/nsos.h +++ b/drivers/net/nsos.h @@ -138,6 +138,8 @@ void nsos_adapt_poll_update(struct nsos_mid_pollfd *pollfd); int nsos_adapt_fcntl_getfl(int fd); int nsos_adapt_fcntl_setfl(int fd, int flags); +int nsos_adapt_fionread(int fd, int *avail); + int nsos_adapt_getaddrinfo(const char *node, const char *service, const struct nsos_mid_addrinfo *hints, struct nsos_mid_addrinfo **res, diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index d3f787762c468e..7e3363c73f8400 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -939,6 +940,18 @@ int nsos_adapt_fcntl_setfl(int fd, int flags) return 0; } +int nsos_adapt_fionread(int fd, int *avail) +{ + int ret; + + ret = ioctl(fd, FIONREAD, avail); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; +} + static void nsos_adapt_init(void) { nsos_epoll_fd = epoll_create(1); diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 5dd528e91013c8..df6f97e8745c67 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -371,6 +371,15 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) return -errno_from_nsos_mid(-ret); } + + case ZFD_IOCTL_FIONREAD: { + int *avail = va_arg(args, int *); + int ret; + + ret = nsos_adapt_fionread(sock->pollfd.fd, avail); + + return -errno_from_nsos_mid(-ret); + } } return -EINVAL; From 495d042c45ec9749a2edc3103d94ad9d4cef2932 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0880/1389] drivers: nsos: support IPPROTO_TCP getsockopt() and setsockopt() Handle IPPROTO_TCP specific options in getsockopt() and setsockopt() APIs. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_adapt.c | 33 +++++++++++++++++++++++++++++++ drivers/net/nsos_socket.h | 16 +++++++++++++++ drivers/net/nsos_sockets.c | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 7e3363c73f8400..9e1a3dd062b4ef 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -624,6 +625,22 @@ int nsos_adapt_getsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, nsos_mid_optval, nsos_mid_optlen); } + + case NSOS_MID_IPPROTO_TCP: + switch (nsos_mid_optname) { + case NSOS_MID_TCP_NODELAY: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPIDLE: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPIDLE, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPINTVL: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPINTVL, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPCNT: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPCNT, + nsos_mid_optval, nsos_mid_optlen); + } } return -NSOS_MID_EOPNOTSUPP; @@ -687,6 +704,22 @@ int nsos_adapt_setsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, nsos_mid_optval, nsos_mid_optlen); } + + case NSOS_MID_IPPROTO_TCP: + switch (nsos_mid_optname) { + case NSOS_MID_TCP_NODELAY: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPIDLE: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPIDLE, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPINTVL: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPINTVL, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPCNT: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPCNT, + nsos_mid_optval, nsos_mid_optlen); + } } return -NSOS_MID_EOPNOTSUPP; diff --git a/drivers/net/nsos_socket.h b/drivers/net/nsos_socket.h index 10db34cdcf11ed..f63b8b30049323 100644 --- a/drivers/net/nsos_socket.h +++ b/drivers/net/nsos_socket.h @@ -87,4 +87,20 @@ struct nsos_mid_timeval { /** @} */ +/** + * @name TCP level options (NSOS_MID_IPPROTO_TCP) + * @{ + */ +/* Socket options for NSOS_MID_IPPROTO_TCP level */ +/** Disable TCP buffering (ignored, for compatibility) */ +#define NSOS_MID_TCP_NODELAY 1 +/** Start keepalives after this period (seconds) */ +#define NSOS_MID_TCP_KEEPIDLE 2 +/** Interval between keepalives (seconds) */ +#define NSOS_MID_TCP_KEEPINTVL 3 +/** Number of keepalives before dropping connection */ +#define NSOS_MID_TCP_KEEPCNT 4 + +/** @} */ + #endif /* __DRIVERS_NET_NSOS_SOCKET_H__ */ diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index df6f97e8745c67..40cb6a62f90d1c 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -1024,6 +1024,26 @@ static int nsos_getsockopt(void *obj, int level, int optname, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, optval, optlen); } + + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_NODELAY, + optval, optlen); + case TCP_KEEPIDLE: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPIDLE, + optval, optlen); + case TCP_KEEPINTVL: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPINTVL, + optval, optlen); + case TCP_KEEPCNT: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT, + optval, optlen); + } } errno = EOPNOTSUPP; @@ -1133,6 +1153,26 @@ static int nsos_setsockopt(void *obj, int level, int optname, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, optval, optlen); } + + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_NODELAY, + optval, optlen); + case TCP_KEEPIDLE: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPIDLE, + optval, optlen); + case TCP_KEEPINTVL: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPINTVL, + optval, optlen); + case TCP_KEEPCNT: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT, + optval, optlen); + } } errno = EOPNOTSUPP; From 63374eeabb6949f0433c7f180118aa756dc22e5a Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0881/1389] drivers: nsos: support IPV6_V6ONLY getsockopt() and setsockopt() Handle IPV6_V6ONLY option in getsockopt() and setsockopt() APIs. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_adapt.c | 14 ++++++++++++++ drivers/net/nsos_socket.h | 28 ++++++++++++++++++++++++++++ drivers/net/nsos_sockets.c | 16 ++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 9e1a3dd062b4ef..a9b5fb1b33fb04 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -641,6 +641,13 @@ int nsos_adapt_getsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPCNT, nsos_mid_optval, nsos_mid_optlen); } + + case NSOS_MID_IPPROTO_IPV6: + switch (nsos_mid_optname) { + case NSOS_MID_IPV6_V6ONLY: + return nsos_adapt_getsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, + nsos_mid_optval, nsos_mid_optlen); + } } return -NSOS_MID_EOPNOTSUPP; @@ -720,6 +727,13 @@ int nsos_adapt_setsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPCNT, nsos_mid_optval, nsos_mid_optlen); } + + case NSOS_MID_IPPROTO_IPV6: + switch (nsos_mid_optname) { + case NSOS_MID_IPV6_V6ONLY: + return nsos_adapt_setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, + nsos_mid_optval, nsos_mid_optlen); + } } return -NSOS_MID_EOPNOTSUPP; diff --git a/drivers/net/nsos_socket.h b/drivers/net/nsos_socket.h index f63b8b30049323..66f54130d175d0 100644 --- a/drivers/net/nsos_socket.h +++ b/drivers/net/nsos_socket.h @@ -103,4 +103,32 @@ struct nsos_mid_timeval { /** @} */ +/** + * @name IPv6 level options (NSOS_MID_IPPROTO_IPV6) + * @{ + */ +/* Socket options for NSOS_MID_IPPROTO_IPV6 level */ +/** Set the unicast hop limit for the socket. */ +#define NSOS_MID_IPV6_UNICAST_HOPS 16 + +/** Set the multicast hop limit for the socket. */ +#define NSOS_MID_IPV6_MULTICAST_HOPS 18 + +/** Join IPv6 multicast group. */ +#define NSOS_MID_IPV6_ADD_MEMBERSHIP 20 + +/** Leave IPv6 multicast group. */ +#define NSOS_MID_IPV6_DROP_MEMBERSHIP 21 + +/** Don't support IPv4 access */ +#define NSOS_MID_IPV6_V6ONLY 26 + +/** Pass an IPV6_RECVPKTINFO ancillary message that contains a + * in6_pktinfo structure that supplies some information about the + * incoming packet. See RFC 3542. + */ +#define NSOS_MID_IPV6_RECVPKTINFO 49 + +/** @} */ + #endif /* __DRIVERS_NET_NSOS_SOCKET_H__ */ diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 40cb6a62f90d1c..54b1af8b246135 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -1044,6 +1044,14 @@ static int nsos_getsockopt(void *obj, int level, int optname, NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT, optval, optlen); } + + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_IPV6, NSOS_MID_IPV6_V6ONLY, + optval, optlen); + } } errno = EOPNOTSUPP; @@ -1173,6 +1181,14 @@ static int nsos_setsockopt(void *obj, int level, int optname, NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT, optval, optlen); } + + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_IPV6, NSOS_MID_IPV6_V6ONLY, + optval, optlen); + } } errno = EOPNOTSUPP; From 105edb70bd6f1ef3ec9dee3804424a00d76f01b6 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0882/1389] tests: socket: udp: reduce SO_PRIORITY from 8 to 6 for NSOS compatbility According to 'man 7 socket' about SO_PRIORITY: Setting a priority outside the range 0 to 6 requires the CAP_NET_ADMIN capability. So use 6 instead of 8, in order to make UDP socket tests pass with native offloaded sockets on native_sim platform. Signed-off-by: Marcin Niestroj --- tests/net/socket/udp/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/socket/udp/src/main.c b/tests/net/socket/udp/src/main.c index f13a8e3c9829e0..3d27e4121a5d2f 100644 --- a/tests/net/socket/udp/src/main.c +++ b/tests/net/socket/udp/src/main.c @@ -343,7 +343,7 @@ ZTEST(net_socket_udp, test_07_so_priority) sizeof(optval)); zassert_equal(rv, 0, "setsockopt failed (%d)", errno); - optval = 8; + optval = 6; rv = zsock_setsockopt(sock2, SOL_SOCKET, SO_PRIORITY, &optval, sizeof(optval)); zassert_equal(rv, 0, "setsockopt failed"); From cd2a33c4f529beee258f3eeeed5262978edc5778 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0883/1389] samples: net: echo_server: set IPV6_V6ONLY This sample assumes that two separate sockets can be bound on IPv4 and IPv6. On Linux (via Native Simulator Offloaded Sockets) this is possible when there is no IPv4 to IPv6 mapping. Same can be true to other offloaded sockets. CONFIG_NET_IPV4_MAPPING_TO_IPV6 is disabled for this sample, so IPv4 to IPv6 mapping is disabled for Zephyr native IPv6 layer. For offloaded sockets this option does not define whether mapping is enabled or not, so try to unconditionally (and without error checking) disable it. This patch fixes compatibility with NSOS, since two separate sockets can be bound on the same address and port, one for IPv4 and second for IPv6. Signed-off-by: Marcin Niestroj --- samples/net/sockets/echo_server/src/tcp.c | 10 +++++++++- samples/net/sockets/echo_server/src/udp.c | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/samples/net/sockets/echo_server/src/tcp.c b/samples/net/sockets/echo_server/src/tcp.c index 3df5ceaec9a76e..c9d5cc68ebd290 100644 --- a/samples/net/sockets/echo_server/src/tcp.c +++ b/samples/net/sockets/echo_server/src/tcp.c @@ -101,12 +101,20 @@ static int start_tcp_proto(struct data *data, } #endif - /* Prefer IPv6 temporary addresses */ if (bind_addr->sa_family == AF_INET6) { + /* Prefer IPv6 temporary addresses */ optval = IPV6_PREFER_SRC_PUBLIC; (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &optval, sizeof(optval)); + + /* + * Bind only to IPv6 without mapping to IPv4, since we bind to + * IPv4 using another socket + */ + optval = 1; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_V6ONLY, + &optval, sizeof(optval)); } ret = bind(data->tcp.sock, bind_addr, bind_addrlen); diff --git a/samples/net/sockets/echo_server/src/udp.c b/samples/net/sockets/echo_server/src/udp.c index 6707410381fa5d..3afe29301514dd 100644 --- a/samples/net/sockets/echo_server/src/udp.c +++ b/samples/net/sockets/echo_server/src/udp.c @@ -78,12 +78,20 @@ static int start_udp_proto(struct data *data, struct sockaddr *bind_addr, } #endif - /* Prefer IPv6 temporary addresses */ if (bind_addr->sa_family == AF_INET6) { + /* Prefer IPv6 temporary addresses */ optval = IPV6_PREFER_SRC_PUBLIC; (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &optval, sizeof(optval)); + + /* + * Bind only to IPv6 without mapping to IPv4, since we bind to + * IPv4 using another socket + */ + optval = 1; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_V6ONLY, + &optval, sizeof(optval)); } ret = bind(data->udp.sock, bind_addr, bind_addrlen); From eece6ba253545ef6a2c240d3eca354777f3dc9fd Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0884/1389] drivers: sensor: st: vbat: check for ADC nodes The vbat driver requires the adc node to be enabled: ```c .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)) ``` Update its Kconfig to depend on `DT_HAS_ST_STM32_ADC_ENABLED`, which is the `"st,stm32-adc"` compat that all ST ADC bindings include, this will guarantee that at least one ADC node is enabled, but not necessarily the ADC used by the vbat node. To make sure that it at least compiles, we init the `adc` pointer only if the specified ADC node is enabled, otherwise it will points to `NULL`. Finally, check if the `adc` points to `NULL` in `stm32_vbat_init`. We are not relying on the existing `device_is_ready` check because `DEVICE_DT_GET` will not return `NULL` if the ADC is enabled. `adc == NULL` means that the ADC node is not enabled in the devicetree. Signed-off-by: Yong Cong Sin --- drivers/sensor/st/stm32_vbat/Kconfig | 1 + drivers/sensor/st/stm32_vbat/stm32_vbat.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/sensor/st/stm32_vbat/Kconfig b/drivers/sensor/st/stm32_vbat/Kconfig index 2638269224dcca..f5430c91a6b740 100644 --- a/drivers/sensor/st/stm32_vbat/Kconfig +++ b/drivers/sensor/st/stm32_vbat/Kconfig @@ -7,6 +7,7 @@ config STM32_VBAT bool "STM32 Vbat Sensor" default y depends on DT_HAS_ST_STM32_VBAT_ENABLED + depends on DT_HAS_ST_STM32_ADC_ENABLED depends on SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X select ADC help diff --git a/drivers/sensor/st/stm32_vbat/stm32_vbat.c b/drivers/sensor/st/stm32_vbat/stm32_vbat.c index 84511c1a4ccc50..352c5a22920cd2 100644 --- a/drivers/sensor/st/stm32_vbat/stm32_vbat.c +++ b/drivers/sensor/st/stm32_vbat/stm32_vbat.c @@ -101,6 +101,11 @@ static int stm32_vbat_init(const struct device *dev) k_mutex_init(&data->mutex); + if (data->adc == NULL) { + LOG_ERR("ADC is not enabled"); + return -ENODEV; + } + if (!device_is_ready(data->adc)) { LOG_ERR("Device %s is not ready", data->adc->name); return -ENODEV; @@ -116,9 +121,13 @@ static int stm32_vbat_init(const struct device *dev) return 0; } +#define STM32_VBAT_GET_ADC_OR_NULL(inst) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_IO_CHANNELS_CTLR(inst), okay), \ + (DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst))), (NULL)) + #define STM32_VBAT_DEFINE(inst) \ static struct stm32_vbat_data stm32_vbat_dev_data_##inst = { \ - .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ + .adc = STM32_VBAT_GET_ADC_OR_NULL(inst), \ .adc_base = (ADC_TypeDef *)DT_REG_ADDR(DT_INST_IO_CHANNELS_CTLR(0)), \ .adc_cfg = { \ .gain = ADC_GAIN_1, \ @@ -136,6 +145,6 @@ static int stm32_vbat_init(const struct device *dev) SENSOR_DEVICE_DT_INST_DEFINE(inst, stm32_vbat_init, NULL, \ &stm32_vbat_dev_data_##inst, &stm32_vbat_dev_config_##inst, \ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ - &stm32_vbat_driver_api); \ + &stm32_vbat_driver_api); DT_INST_FOREACH_STATUS_OKAY(STM32_VBAT_DEFINE) From 3554742d63096c26fa6c64d945a101e450337903 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Sun, 26 May 2024 22:39:13 +0200 Subject: [PATCH 0885/1389] drivers: dai: sai: write some data into TX FIFO before start While running the following command: aplay ... | arecord ... multiple times, it was discovered that the SAI transmit FIFO goes into underrun. This only happened in the beginning, a few BCLK cycles after unmasking the transmit data line. With the following flow: 1) Trigger start on RX a) Do TX and RX software reset b) Enable RX FIFO error interrupt c) Enable RX DMA requests d) Enable receive data line e) Enable transmitter f) Enable receiver ..... some time has passed ..... 2) Trigger start on TX a) Enable DMA requests b) Enable transmit data line and configuration in mind: 1) RX is SYNC with TX 2) TX is ASYNC 3) Each FSYNC edge is 32-bit wide 4) Each frame contains 2 32-bit words this points to the following possibilites: 1) The transmitter is enabled so close to the start of a new frame that even though the DMA requests are asserted, the DMAC doesn't have enough time to service them until the module goes into underrun => the timing is bad. 2) The transmitter is enabled somewhat close to the start of a new frame such that the DMAC is not fast enough to service the module until it goes into underrun => DMAC is too slow AND the timing is bad. Although the exact cause was not pinpointed, this patch aims to fix the problem by writing a frame's worth of 0s in the transmit FIFO. This way, even if we're dealing with scenario 1) or 2), the DMAC has plenty of time to perform the transfer (i.e: a frame), thus avoiding the underrun. Signed-off-by: Laurentiu Mihalcea --- drivers/dai/nxp/sai/sai.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/dai/nxp/sai/sai.c b/drivers/dai/nxp/sai/sai.c index c61e6115a807b3..8deb17e06a19ba 100644 --- a/drivers/dai/nxp/sai/sai.c +++ b/drivers/dai/nxp/sai/sai.c @@ -696,7 +696,7 @@ static int sai_trigger_start(const struct device *dev, struct sai_data *data; const struct sai_config *cfg; uint32_t old_state; - int ret; + int ret, i; data = dev->data; cfg = dev->config; @@ -733,7 +733,12 @@ static int sai_trigger_start(const struct device *dev, SAI_TX_RX_ENABLE_DISABLE_IRQ(dir, data->regmap, kSAI_FIFOErrorInterruptEnable, true); - /* TODO: is there a need to write some words to the FIFO to avoid starvation? */ + /* avoid initial underrun by writing a frame's worth of 0s */ + if (dir == DAI_DIR_TX) { + for (i = 0; i < data->cfg.channels; i++) { + SAI_WriteData(UINT_TO_I2S(data->regmap), cfg->tx_dline, 0x0); + } + } /* TODO: for now, only DMA mode is supported */ SAI_TX_RX_DMA_ENABLE_DISABLE(dir, data->regmap, true); From 76878dc234cfbbca53e5e7d05a7dd2079759c78b Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0886/1389] ARC: nSIM: west: launch cores in direct order for simulation run We've reversed core launch order to workaround issue of ARConnect initialization interfere with secondary cores startup (we don't want to workaround it in runtime as it's only possible in case of debug session). However it bring us new issues with the simulation run: - mismatch arcnum (core ID) with ARConnect ID - mismatch arcnum (core ID) with CPU name in nSIM instruction traces To avoid these issues let's use direct core order for simulation runs. Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- scripts/west_commands/runners/mdb.py | 12 +++++++++++- scripts/west_commands/tests/test_mdb.py | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/west_commands/runners/mdb.py b/scripts/west_commands/runners/mdb.py index 656d41618a64ac..cc44390e279f6a 100644 --- a/scripts/west_commands/runners/mdb.py +++ b/scripts/west_commands/runners/mdb.py @@ -34,6 +34,16 @@ def is_flash_cmd_need_exit_immediately(mdb_runner): else: return True +def smp_core_order(mdb_runner, id): + if is_simulation_run(mdb_runner): + # for simulation targets we start cores in direct order (core 0 first, core 1 second, etc...) + # otherwise we face mismatch arcnum (code ID) with ARConnect ID and core ID in instruction traces + return id + else: + # for HW targets we want to start the primary core last, to avoid ARConnect initialization interfere + # with secondary cores startup - so we reverse start order + return mdb_runner.cores - 1 - id + def mdb_do_run(mdb_runner, command): commander = "mdb64" @@ -81,7 +91,7 @@ def mdb_do_run(mdb_runner, command): if i > 0: mdb_sub_cmd += ['-prop=download=2'] mdb_sub_cmd += mdb_basic_options + mdb_target + [mdb_runner.elf_name] mdb_runner.check_call(mdb_sub_cmd, cwd=mdb_runner.build_dir) - mdb_multifiles += ('core{}'.format(mdb_runner.cores-1-i) if i == 0 else ',core{}'.format(mdb_runner.cores-1-i)) + mdb_multifiles += ('core{}' if i == 0 else ',core{}').format(smp_core_order(mdb_runner, i)) # to enable multi-core aware mode for use with the MetaWare debugger, # need to set the NSIM_MULTICORE environment variable to a non-zero value diff --git a/scripts/west_commands/tests/test_mdb.py b/scripts/west_commands/tests/test_mdb.py index ca07b5d1640cb6..275674902829ac 100644 --- a/scripts/west_commands/tests/test_mdb.py +++ b/scripts/west_commands/tests/test_mdb.py @@ -55,7 +55,7 @@ '-prop=download=2', '-nooptions', '-nogoifmain', '-toggle=include_local_symbols=1', '-nsim', TEST_BOARD_NSIM_ARGS, RC_KERNEL_ELF] -TEST_NSIM_CORES_LAUNCH = [TEST_DRIVER_CMD, '-multifiles=core1,core0', +TEST_NSIM_CORES_LAUNCH = [TEST_DRIVER_CMD, '-multifiles=core0,core1', '-run', '-cl'] # mdb-hw From 62a1067b4d9e72b06244914c99d270b80bb60037 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0887/1389] ARC: nSIM: cmake: launch cores in direct order for simulation run Align cmake launch script with west runners Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- cmake/emu/nsim.cmake | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmake/emu/nsim.cmake b/cmake/emu/nsim.cmake index a187cdad03e6f8..323593fc1d829e 100644 --- a/cmake/emu/nsim.cmake +++ b/cmake/emu/nsim.cmake @@ -13,14 +13,13 @@ if(CONFIG_MP_MAX_NUM_CPUS GREATER 1) set(MULTIFILES ${MDB} -multifiles=) foreach(val RANGE ${CONFIG_MP_MAX_NUM_CPUS}) if(val LESS CONFIG_MP_MAX_NUM_CPUS) - MATH(EXPR PSET_NUM "${CONFIG_MP_MAX_NUM_CPUS}-${val}") - MATH(EXPR CORE_NUM "${CONFIG_MP_MAX_NUM_CPUS}-${val}-1") - if(PSET_NUM GREATER 0) - list(APPEND MDB_OPTIONS &&) - endif() - list(APPEND MDB_OPTIONS ${MDB} -pset=${PSET_NUM} -psetname=core${CORE_NUM}) + MATH(EXPR PSET_NUM "${val}+1") + set(CORE_NUM ${val}) + list(APPEND MDB_OPTIONS && ${MDB} -pset=${PSET_NUM} -psetname=core${CORE_NUM}) if(PSET_NUM GREATER 1) list(APPEND MDB_OPTIONS -prop=download=2) + endif() + if(PSET_NUM LESS ${CONFIG_MP_MAX_NUM_CPUS}) set(MULTIFILES ${MULTIFILES}core${CORE_NUM},) else() set(MULTIFILES ${MULTIFILES}core${CORE_NUM}) From 4081d1b094f1fc6e94d288c138632b80708855cc Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0888/1389] Bluetooth samples: Keep broadcast assistant connected When Broadcast Sink is connected to Broadcast Assistant then keep connection when Broadcast Source is removed. Signed-off-by: Jens Rehhoff Thomsen --- .../bluetooth/broadcast_audio_sink/src/main.c | 243 ++++++++++++------ 1 file changed, 159 insertions(+), 84 deletions(-) diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c index ae55ca13b128e8..860434d428af42 100644 --- a/samples/bluetooth/broadcast_audio_sink/src/main.c +++ b/samples/bluetooth/broadcast_audio_sink/src/main.c @@ -64,6 +64,7 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_SCAN_SELF) || IS_ENABLED(CONFIG_SCAN_OFFLOAD), #define USB_RING_BUF_SIZE (5 * LC3_MAX_NUM_SAMPLES_STEREO) /* 5 SDUs*/ #endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +static K_SEM_DEFINE(sem_broadcast_sink_stopped, 0U, 1U); static K_SEM_DEFINE(sem_connected, 0U, 1U); static K_SEM_DEFINE(sem_disconnected, 0U, 1U); static K_SEM_DEFINE(sem_broadcaster_found, 0U, 1U); @@ -75,7 +76,9 @@ static K_SEM_DEFINE(sem_broadcast_code_received, 0U, 1U); static K_SEM_DEFINE(sem_pa_request, 0U, 1U); static K_SEM_DEFINE(sem_past_request, 0U, 1U); static K_SEM_DEFINE(sem_bis_sync_requested, 0U, 1U); -static K_SEM_DEFINE(sem_bis_synced, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); +static K_SEM_DEFINE(sem_stream_connected, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); +static K_SEM_DEFINE(sem_stream_started, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); +static K_SEM_DEFINE(sem_big_synced, 0U, 1U); /* Sample assumes that we only have a single Scan Delegator receive state */ static const struct bt_bap_scan_delegator_recv_state *req_recv_state; @@ -107,8 +110,11 @@ static struct broadcast_sink_stream { } streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; +static volatile bool big_synced; +static volatile bool base_received; static struct bt_conn *broadcast_assistant_conn; static struct bt_le_ext_adv *ext_adv; +static volatile uint8_t stream_count; static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( BT_AUDIO_CODEC_CAP_FREQ_16KHZ | BT_AUDIO_CODEC_CAP_FREQ_24KHZ, @@ -480,6 +486,25 @@ static void usb_data_written_cb(const struct device *dev, struct net_buf *buf, s } #endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +static void stream_connected_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p connected\n", stream); + + k_sem_give(&sem_stream_connected); +} + +static void stream_disconnected_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + int err; + + printk("Stream %p disconnected with reason 0x%02X\n", stream, reason); + + err = k_sem_take(&sem_stream_connected, K_NO_WAIT); + if (err != 0) { + printk("Failed to take sem_stream_connected: %d\n", err); + } +} + static void stream_started_cb(struct bt_bap_stream *stream) { struct broadcast_sink_stream *sink_stream = @@ -509,7 +534,11 @@ static void stream_started_cb(struct bt_bap_stream *stream) } #endif /* CONFIG_LIBLC3 */ - k_sem_give(&sem_bis_synced); + k_sem_give(&sem_stream_started); + if (k_sem_count_get(&sem_stream_started) == stream_count) { + big_synced = true; + k_sem_give(&sem_big_synced); + } } static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) @@ -518,9 +547,13 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) printk("Stream %p stopped with reason 0x%02X\n", stream, reason); - err = k_sem_take(&sem_bis_synced, K_NO_WAIT); + err = k_sem_take(&sem_stream_started, K_NO_WAIT); if (err != 0) { - printk("Failed to take sem_bis_synced: %d\n", err); + printk("Failed to take sem_stream_started: %d\n", err); + } + + if (k_sem_count_get(&sem_stream_started) != stream_count) { + big_synced = false; } } @@ -563,6 +596,8 @@ static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_rec } static struct bt_bap_stream_ops stream_ops = { + .connected = stream_connected_cb, + .disconnected = stream_disconnected_cb, .started = stream_started_cb, .stopped = stream_stopped_cb, .recv = stream_recv_cb, @@ -794,7 +829,7 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap uint32_t base_bis_index_bitfield = 0U; int err; - if (k_sem_count_get(&sem_base_received) != 0U) { + if (base_received) { return; } @@ -817,17 +852,23 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; + printk("bis_index_bitfield = 0x%08x\n", bis_index_bitfield); + if (broadcast_assistant_conn == NULL) { /* No broadcast assistant requesting anything */ requested_bis_sync = BT_BAP_BIS_SYNC_NO_PREF; k_sem_give(&sem_bis_sync_requested); } + base_received = true; k_sem_give(&sem_base_received); } static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo) { + printk("Broadcast sink (%p) is syncable, BIG %s\n", (void *)sink, + biginfo->encryption ? "encrypted" : "not encrypted"); + k_sem_give(&sem_syncable); if (!biginfo->encryption) { @@ -903,6 +944,18 @@ static int pa_sync_past(struct bt_conn *conn, uint16_t pa_interval) return err; } +static void recv_state_updated_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + printk("Receive state updated, pa sync state: %u\n", recv_state->pa_sync_state); + + for (uint8_t i = 0; i < recv_state->num_subgroups; i++) { + printk("subgroup %d bis_sync: 0x%08x\n", i, recv_state->subgroups[i].bis_sync); + } + + req_recv_state = recv_state; +} + static int pa_sync_req_cb(struct bt_conn *conn, const struct bt_bap_scan_delegator_recv_state *recv_state, bool past_avail, uint16_t pa_interval) @@ -951,15 +1004,22 @@ static int pa_sync_term_req_cb(struct bt_conn *conn, { int err; + printk("PA sync termination req, pa sync state: %u\n", recv_state->pa_sync_state); + + for (uint8_t i = 0; i < recv_state->num_subgroups; i++) { + printk("subgroup %d bis_sync: 0x%08x\n", i, recv_state->subgroups[i].bis_sync); + } + req_recv_state = recv_state; - err = bt_bap_broadcast_sink_delete(broadcast_sink); + printk("Delete periodic advertising sync\n"); + err = bt_le_per_adv_sync_delete(pa_sync); if (err != 0) { + printk("Could not delete per adv sync: %d\n", err); + return err; } - broadcast_sink = NULL; - return 0; } @@ -982,13 +1042,12 @@ static int bis_sync_req_cb(struct bt_conn *conn, const struct bt_bap_scan_delegator_recv_state *recv_state, const uint32_t bis_sync_req[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]) { - const bool bis_synced = k_sem_count_get(&sem_bis_synced) > 0U; - - printk("BIS sync request received for %p: 0x%08x\n", - recv_state, bis_sync_req[0]); + printk("BIS sync request received for %p: 0x%08x->0x%08x, broadcast id: 0x%06x, (%s)\n", + recv_state, requested_bis_sync, bis_sync_req[0], recv_state->broadcast_id, + big_synced ? "BIG synced" : "BIG not synced"); /* We only care about a single subgroup in this sample */ - if (bis_synced && requested_bis_sync != bis_sync_req[0]) { + if (big_synced && requested_bis_sync != bis_sync_req[0]) { /* If the BIS sync request is received while we are already * synced, it means that the requested BIS sync has changed. */ @@ -996,8 +1055,8 @@ static int bis_sync_req_cb(struct bt_conn *conn, /* The stream stopped callback will be called as part of this, * and we do not need to wait for any events from the - * controller. Thus, when this returns, the `sem_bis_synced` - * is back to 0. + * controller. Thus, when this returns, the `big_synced` + * is back to false. */ err = bt_bap_broadcast_sink_stop(broadcast_sink); if (err != 0) { @@ -1005,6 +1064,8 @@ static int bis_sync_req_cb(struct bt_conn *conn, return err; } + + k_sem_give(&sem_broadcast_sink_stopped); } requested_bis_sync = bis_sync_req[0]; @@ -1017,6 +1078,7 @@ static int bis_sync_req_cb(struct bt_conn *conn, } static struct bt_bap_scan_delegator_cb scan_delegator_cbs = { + .recv_state_updated = recv_state_updated_cb, .pa_sync_req = pa_sync_req_cb, .pa_sync_term_req = pa_sync_term_req_cb, .broadcast_code = broadcast_code_cb, @@ -1099,21 +1161,19 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) printk("Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X\n", broadcast_id, le_addr, info->sid); - if (broadcast_assistant_conn == NULL) { - /* Not requested by Broadcast Assistant */ - k_sem_give(&sem_broadcaster_found); - } else if (req_recv_state != NULL && - bt_addr_le_eq(info->addr, &req_recv_state->addr) && - info->sid == req_recv_state->adv_sid && - broadcast_id == req_recv_state->broadcast_id) { + if (broadcast_assistant_conn == NULL /* Not requested by Broadcast Assistant */ || + (req_recv_state != NULL && bt_addr_le_eq(info->addr, &req_recv_state->addr) && + info->sid == req_recv_state->adv_sid && + broadcast_id == req_recv_state->broadcast_id)) { + + /* Store info for PA sync parameters */ + memcpy(&broadcaster_info, info, sizeof(broadcaster_info)); + bt_addr_le_copy(&broadcaster_addr, info->addr); + broadcaster_broadcast_id = broadcast_id; + printk("broadcaster_broadcast_id = 0x%06X\n", broadcaster_broadcast_id); k_sem_give(&sem_broadcaster_found); } - /* Store info for PA sync parameters */ - memcpy(&broadcaster_info, info, sizeof(broadcaster_info)); - bt_addr_le_copy(&broadcaster_addr, info->addr); - broadcaster_broadcast_id = broadcast_id; - /* Stop parsing */ return false; } @@ -1160,11 +1220,11 @@ static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct if (info->interval != 0U) { /* call to bt_data_parse consumes netbufs so shallow clone for verbose output */ - /* If req_recv_state is NULL then we have been requested by a broadcast assistant to - * sync to a specific broadcast source. In that case we do not apply our own - * broadcast name filter. + /* If req_recv_state is not NULL then we have been requested by a broadcast + * assistant to sync to a specific broadcast source. In that case we do not apply + * our own broadcast name filter. */ - if (req_recv_state != NULL && strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { + if (req_recv_state == NULL && strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { struct net_buf_simple buf_copy; char name[NAME_LEN] = {0}; @@ -1271,9 +1331,14 @@ static int reset(void) { int err; + printk("Reset\n"); + bis_index_bitfield = 0U; requested_bis_sync = 0U; req_recv_state = NULL; + big_synced = false; + base_received = false; + stream_count = 0U; (void)memset(sink_broadcast_code, 0, sizeof(sink_broadcast_code)); (void)memset(&broadcaster_info, 0, sizeof(broadcaster_info)); (void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr)); @@ -1301,35 +1366,6 @@ static int reset(void) pa_sync = NULL; } - if (IS_ENABLED(CONFIG_SCAN_OFFLOAD)) { - if (broadcast_assistant_conn != NULL) { - err = bt_conn_disconnect(broadcast_assistant_conn, - BT_HCI_ERR_REMOTE_USER_TERM_CONN); - if (err) { - printk("Disconnecting Broadcast Assistant failed (err %d)\n", - err); - - return err; - } - - err = k_sem_take(&sem_disconnected, SEM_TIMEOUT); - if (err != 0) { - printk("Failed to take sem_disconnected: %d\n", err); - - return err; - } - } - - if (ext_adv != NULL) { - stop_adv(); - } - - k_sem_reset(&sem_connected); - k_sem_reset(&sem_disconnected); - k_sem_reset(&sem_pa_request); - k_sem_reset(&sem_past_request); - } - k_sem_reset(&sem_broadcaster_found); k_sem_reset(&sem_pa_synced); k_sem_reset(&sem_base_received); @@ -1337,7 +1373,10 @@ static int reset(void) k_sem_reset(&sem_pa_sync_lost); k_sem_reset(&sem_broadcast_code_received); k_sem_reset(&sem_bis_sync_requested); - k_sem_reset(&sem_bis_synced); + k_sem_reset(&sem_stream_connected); + k_sem_reset(&sem_stream_started); + k_sem_reset(&sem_broadcast_sink_stopped); + return 0; } @@ -1443,28 +1482,46 @@ int main(void) } if (IS_ENABLED(CONFIG_SCAN_OFFLOAD)) { - printk("Starting advertising\n"); - err = start_adv(); - if (err != 0) { - printk("Unable to start advertising connectable: %d\n", - err); + if (broadcast_assistant_conn == NULL) { + k_sem_reset(&sem_connected); - return 0; - } - - printk("Waiting for Broadcast Assistant\n"); - err = k_sem_take(&sem_connected, ADV_TIMEOUT); - if (err != 0) { - printk("No Broadcast Assistant connected\n"); + printk("Starting advertising\n"); + /* Stop advertising before starting if needed */ + if (ext_adv != NULL) { + err = stop_adv(); + if (err != 0) { + printk("Unable to stop advertising: %d\n", err); - err = stop_adv(); + return 0; + } + } + err = start_adv(); if (err != 0) { - printk("Unable to stop advertising: %d\n", + printk("Unable to start advertising connectable: %d\n", err); return 0; } - } else { + + printk("Waiting for Broadcast Assistant\n"); + err = k_sem_take(&sem_connected, ADV_TIMEOUT); + if (err != 0) { + printk("No Broadcast Assistant connected\n"); + + err = stop_adv(); + if (err != 0) { + printk("Unable to stop advertising: %d\n", err); + + return 0; + } + } + } + + if (broadcast_assistant_conn != NULL) { + k_sem_reset(&sem_pa_request); + k_sem_reset(&sem_past_request); + k_sem_reset(&sem_disconnected); + /* Wait for the PA request to determine if we * should start scanning, or wait for PAST */ @@ -1483,8 +1540,8 @@ int main(void) } if (strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { - printk("Scanning for broadcast sources containing`" - CONFIG_TARGET_BROADCAST_NAME "`\n"); + printk("Scanning for broadcast sources containing " + "`" CONFIG_TARGET_BROADCAST_NAME "`\n"); } else { printk("Scanning for broadcast sources\n"); } @@ -1496,12 +1553,12 @@ int main(void) return 0; } + printk("Waiting for Broadcaster\n"); err = k_sem_take(&sem_broadcaster_found, SEM_TIMEOUT); if (err != 0) { printk("sem_broadcaster_found timed out, resetting\n"); continue; } - printk("Broadcast source found, waiting for PA sync\n"); err = bt_le_scan_stop(); if (err != 0) { @@ -1539,8 +1596,8 @@ int main(void) printk("sem_base_received timed out, resetting\n"); continue; } - printk("BASE received, waiting for syncable\n"); + printk("BASE received, waiting for syncable\n"); err = k_sem_take(&sem_syncable, SEM_TIMEOUT); if (err != 0) { printk("sem_syncable timed out, resetting\n"); @@ -1565,7 +1622,17 @@ int main(void) } sync_bitfield = bis_index_bitfield & requested_bis_sync; - printk("Syncing to broadcast with bitfield: 0x%08x\n", sync_bitfield); + stream_count = 0; + for (int i = 1; i < BT_ISO_MAX_GROUP_ISO_COUNT; i++) { + if ((sync_bitfield & BIT(i)) != 0) { + stream_count++; + } + } + + printk("Syncing to broadcast with bitfield: 0x%08x = 0x%08x (bis_index) & 0x%08x " + "(req_bis_sync), stream_count = %u\n", + sync_bitfield, bis_index_bitfield, requested_bis_sync, stream_count); + err = bt_bap_broadcast_sink_sync(broadcast_sink, sync_bitfield, streams_p, sink_broadcast_code); if (err != 0) { @@ -1573,15 +1640,23 @@ int main(void) return 0; } - printk("Waiting for BIG sync\n"); - err = k_sem_take(&sem_bis_synced, SEM_TIMEOUT); + printk("Waiting for stream(s) started\n"); + err = k_sem_take(&sem_big_synced, SEM_TIMEOUT); if (err != 0) { - printk("sem_bis_synced timed out, resetting\n"); + printk("sem_big_synced timed out, resetting\n"); continue; } printk("Waiting for PA disconnected\n"); k_sem_take(&sem_pa_sync_lost, K_FOREVER); + + printk("Wainting for sink to stop\n"); + err = k_sem_take(&sem_broadcast_sink_stopped, SEM_TIMEOUT); + if (err != 0) { + printk("sem_broadcast_sink_stopped timed out, resetting\n"); + continue; + } } + return 0; } From 01a1be607faec06371ef06fbccc5059ffb761a9e Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0889/1389] Bluetooth: Audio: Upgrade from experimental to unstable This commit upgrades the LE audio API and implementation from experimental to unstable. LE Audio have existing for quite a few years in Zephyr and is not going anywhere, but at the same time it still has significant effort remaining before it can be considered stable. Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/audio/aics.h | 4 +++- include/zephyr/bluetooth/audio/cap.h | 6 +++--- include/zephyr/bluetooth/audio/csip.h | 5 +++-- include/zephyr/bluetooth/audio/has.h | 6 +++--- include/zephyr/bluetooth/audio/mcc.h | 6 +++--- include/zephyr/bluetooth/audio/mcs.h | 6 +++--- include/zephyr/bluetooth/audio/media_proxy.h | 6 +++--- include/zephyr/bluetooth/audio/micp.h | 6 +++--- include/zephyr/bluetooth/audio/pbp.h | 6 +++--- include/zephyr/bluetooth/audio/vcp.h | 6 +++--- include/zephyr/bluetooth/audio/vocs.h | 5 +++-- subsys/bluetooth/audio/Kconfig | 3 +-- subsys/bluetooth/audio/Kconfig.aics | 6 ++---- subsys/bluetooth/audio/Kconfig.bap | 18 ++++++------------ subsys/bluetooth/audio/Kconfig.cap | 9 +++------ subsys/bluetooth/audio/Kconfig.csip | 6 ++---- subsys/bluetooth/audio/Kconfig.gmap | 3 +-- subsys/bluetooth/audio/Kconfig.has | 6 ++---- subsys/bluetooth/audio/Kconfig.mcs | 2 -- subsys/bluetooth/audio/Kconfig.mctl | 1 - subsys/bluetooth/audio/Kconfig.micp | 6 ++---- subsys/bluetooth/audio/Kconfig.mpl | 1 - subsys/bluetooth/audio/Kconfig.pbp | 3 +-- subsys/bluetooth/audio/Kconfig.tmap | 3 +-- subsys/bluetooth/audio/Kconfig.vcp | 6 ++---- subsys/bluetooth/audio/Kconfig.vocs | 6 ++---- 26 files changed, 58 insertions(+), 83 deletions(-) diff --git a/include/zephyr/bluetooth/audio/aics.h b/include/zephyr/bluetooth/audio/aics.h index dbaf7383e652c5..55f2eab2f931ab 100644 --- a/include/zephyr/bluetooth/audio/aics.h +++ b/include/zephyr/bluetooth/audio/aics.h @@ -12,6 +12,9 @@ * * @defgroup bt_gatt_aics Audio Input Control Service (AICS) * + * @since 2.6 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * @@ -23,7 +26,6 @@ * automatically handle any changes to that. If out of date, the client implementation will * autonomously read the change counter value when executing a write request. * - * [Experimental] Users should note that the APIs can change as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index 9c785b87e98437..a6cfcb418d6eaf 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -12,11 +12,11 @@ * * @defgroup bt_cap Common Audio Profile (CAP) * + * @since 3.2 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/csip.h b/include/zephyr/bluetooth/audio/csip.h index a302a698867297..1981a23458fee9 100644 --- a/include/zephyr/bluetooth/audio/csip.h +++ b/include/zephyr/bluetooth/audio/csip.h @@ -12,10 +12,11 @@ * * @defgroup bt_gatt_csip Coordinated Set Identification Profile (CSIP) * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * * - * [Experimental] Users should note that the APIs can change as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/has.h b/include/zephyr/bluetooth/audio/has.h index 46be03e72ef2e9..0e5c165290215d 100644 --- a/include/zephyr/bluetooth/audio/has.h +++ b/include/zephyr/bluetooth/audio/has.h @@ -12,14 +12,14 @@ * * @defgroup bt_has Hearing Access Service (HAS) * + * @since 3.1 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * * The Hearing Access Service is used to identify a hearing aid and optionally * to control hearing aid presets. - * - * [Experimental] Users should note that the APIs can change as a part of - * ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/mcc.h b/include/zephyr/bluetooth/audio/mcc.h index f67eb768318100..14dba829225301 100644 --- a/include/zephyr/bluetooth/audio/mcc.h +++ b/include/zephyr/bluetooth/audio/mcc.h @@ -5,11 +5,11 @@ * * @defgroup bt_gatt_mcc Media Control Client (MCC) * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ /* diff --git a/include/zephyr/bluetooth/audio/mcs.h b/include/zephyr/bluetooth/audio/mcs.h index b234131281e4d5..7d9491944ef275 100644 --- a/include/zephyr/bluetooth/audio/mcs.h +++ b/include/zephyr/bluetooth/audio/mcs.h @@ -12,12 +12,12 @@ * * @defgroup bt_mcs Media Control Service (MCS) * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. - * * Definitions and types related to the Media Control Service and Media Control * Profile specifications. */ diff --git a/include/zephyr/bluetooth/audio/media_proxy.h b/include/zephyr/bluetooth/audio/media_proxy.h index 34e3e7126f6993..0e236a1fd4a072 100644 --- a/include/zephyr/bluetooth/audio/media_proxy.h +++ b/include/zephyr/bluetooth/audio/media_proxy.h @@ -11,6 +11,9 @@ * * @defgroup bt_media_proxy Media Proxy * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * @@ -31,9 +34,6 @@ * application, or it may be a Media Control Service relaying requests * from a remote Media Control Client. There may be either local or * remote control, or both, or even multiple instances of each. - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/micp.h b/include/zephyr/bluetooth/audio/micp.h index 27359ca7ffa5db..500eb2048395f3 100644 --- a/include/zephyr/bluetooth/audio/micp.h +++ b/include/zephyr/bluetooth/audio/micp.h @@ -12,11 +12,11 @@ * * @defgroup bt_gatt_micp Microphone Control Profile (MICP) * + * @since 2.7 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/pbp.h b/include/zephyr/bluetooth/audio/pbp.h index acc53adb5ad5d2..71d7d107b4e9c8 100644 --- a/include/zephyr/bluetooth/audio/pbp.h +++ b/include/zephyr/bluetooth/audio/pbp.h @@ -12,11 +12,11 @@ * * @defgroup bt_pbp Public Broadcast Profile (PBP) * + * @since 3.5 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/vcp.h b/include/zephyr/bluetooth/audio/vcp.h index 15d91fae330e2d..1128bf18d1e4b7 100644 --- a/include/zephyr/bluetooth/audio/vcp.h +++ b/include/zephyr/bluetooth/audio/vcp.h @@ -12,11 +12,11 @@ * * @defgroup bt_gatt_vcp Volume Control Profile (VCP) * + * @since 2.7 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/audio/vocs.h b/include/zephyr/bluetooth/audio/vocs.h index d34e6bcd16e9d3..8b6a51d8d64b49 100644 --- a/include/zephyr/bluetooth/audio/vocs.h +++ b/include/zephyr/bluetooth/audio/vocs.h @@ -12,6 +12,9 @@ * * @defgroup bt_gatt_vocs Volume Offset Control Service (VOCS) * + * @since 2.6 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * @@ -22,8 +25,6 @@ * Note that the API abstracts away the change counter in the volume offset control state and will * automatically handle any changes to that. If out of date, the client implementation will * autonomously read the change counter value when executing a write request. - * - * [Experimental] Users should note that the APIs can change as a part of ongoing development. */ #include diff --git a/subsys/bluetooth/audio/Kconfig b/subsys/bluetooth/audio/Kconfig index b60475c02e2661..f8e7769df349f1 100644 --- a/subsys/bluetooth/audio/Kconfig +++ b/subsys/bluetooth/audio/Kconfig @@ -8,8 +8,7 @@ # menuconfig BT_AUDIO - bool "Bluetooth Audio support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Bluetooth Audio support" help This option enables Bluetooth Audio support. The specific features that are available may depend on other features diff --git a/subsys/bluetooth/audio/Kconfig.aics b/subsys/bluetooth/audio/Kconfig.aics index 570fcbf58d4a66..b39c4027e81c00 100644 --- a/subsys/bluetooth/audio/Kconfig.aics +++ b/subsys/bluetooth/audio/Kconfig.aics @@ -9,7 +9,7 @@ ##################### Audio Input Control Service ##################### config BT_AICS_MAX_INSTANCE_COUNT - int "Audio Input Control Service max instance count [EXPERIMENTAL]" + int "Audio Input Control Service max instance count" default 0 range 0 15 help @@ -19,7 +19,6 @@ config BT_AICS_MAX_INSTANCE_COUNT config BT_AICS bool # hidden default y if BT_AICS_MAX_INSTANCE_COUNT > 0 - select EXPERIMENTAL select BT_GATT_DYNAMIC_DB help This hidden option enables support for Audio Input Control Service. @@ -38,7 +37,7 @@ endif # BT_AICS ##################### Audio Input Control Service Client ##################### config BT_AICS_CLIENT_MAX_INSTANCE_COUNT - int "Audio Input Control Service client max instance count [EXPERIMENTAL]" + int "Audio Input Control Service client max instance count" default 0 range 0 15 help @@ -48,6 +47,5 @@ config BT_AICS_CLIENT_MAX_INSTANCE_COUNT config BT_AICS_CLIENT bool # hidden default y if BT_AICS_CLIENT_MAX_INSTANCE_COUNT > 0 - select EXPERIMENTAL help This hidden option enables support for Audio Input Control Service. diff --git a/subsys/bluetooth/audio/Kconfig.bap b/subsys/bluetooth/audio/Kconfig.bap index a6771fc712eedf..93ab96f6279c2d 100644 --- a/subsys/bluetooth/audio/Kconfig.bap +++ b/subsys/bluetooth/audio/Kconfig.bap @@ -13,8 +13,7 @@ config BT_BAP_UNICAST select BT_ISO_UNICAST config BT_BAP_UNICAST_SERVER - bool "Bluetooth Unicast Audio Server Support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Bluetooth Unicast Audio Server Support" select BT_BAP_UNICAST select BT_GATT_DYNAMIC_DB select BT_GATT_CACHING @@ -27,8 +26,7 @@ config BT_BAP_UNICAST_SERVER using Isochronous channels. config BT_BAP_UNICAST_CLIENT - bool "Bluetooth Unicast Audio Client Support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Bluetooth Unicast Audio Client Support" select BT_BAP_UNICAST select BT_ISO_CENTRAL select BT_CENTRAL @@ -127,8 +125,7 @@ config BT_BAP_UNICAST_CLIENT_ASE_SRC endif # BT_BAP_UNICAST_CLIENT config BT_BAP_BROADCAST_SOURCE - bool "Bluetooth Broadcast Source Audio Support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Bluetooth Broadcast Source Audio Support" select BT_ISO_BROADCASTER select BT_AUDIO_TX help @@ -167,8 +164,7 @@ config BT_BAP_BROADCAST_SRC_STREAM_COUNT endif # BT_BAP_BROADCAST_SOURCE config BT_BAP_BROADCAST_SINK - bool "Bluetooth Broadcast Sink Audio Support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Bluetooth Broadcast Sink Audio Support" select BT_ISO_SYNC_RECEIVER select BT_AUDIO_RX select BT_PAC_SNK @@ -211,8 +207,7 @@ config BT_BAP_BROADCAST_SNK_STREAM_COUNT endif # BT_BAP_BROADCAST_SINK config BT_BAP_SCAN_DELEGATOR - bool "Basic Audio Profile Scan Delegator role support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Basic Audio Profile Scan Delegator role support" select BT_OBSERVER select BT_EXT_ADV select BT_PER_ADV_SYNC @@ -244,8 +239,7 @@ config BT_BAP_SCAN_DELEGATOR_BUF_TIMEOUT endif # BT_BAP_SCAN_DELEGATOR config BT_BAP_BROADCAST_ASSISTANT - bool "Basic Audio Profile Broadcast Assistant role support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Basic Audio Profile Broadcast Assistant role support" select BT_OBSERVER select BT_EXT_ADV select BT_PER_ADV_SYNC diff --git a/subsys/bluetooth/audio/Kconfig.cap b/subsys/bluetooth/audio/Kconfig.cap index 2a130f53d9a61b..5ba8a9bf2f035a 100644 --- a/subsys/bluetooth/audio/Kconfig.cap +++ b/subsys/bluetooth/audio/Kconfig.cap @@ -9,10 +9,9 @@ config BT_CAP def_bool BT_CAP_ACCEPTOR || BT_CAP_INITIATOR config BT_CAP_ACCEPTOR - bool "Common Audio Profile Acceptor Role Support [EXPERIMENTAL]" + bool "Common Audio Profile Acceptor Role Support" depends on BT_BAP_UNICAST_SERVER || (BT_BAP_BROADCAST_SINK && BT_BAP_SCAN_DELEGATOR) depends on BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE >= 4 - select EXPERIMENTAL help Enabling this will enable the CAP Acceptor role. This instantiates the common audio service (CAS). @@ -32,22 +31,20 @@ config BT_CAP_INITIATOR_UNICAST def_bool BT_CAP_INITIATOR && BT_BAP_UNICAST_CLIENT config BT_CAP_INITIATOR - bool "Common Audio Profile Initiator Role Support [EXPERIMENTAL]" + bool "Common Audio Profile Initiator Role Support" depends on (BT_BAP_UNICAST_CLIENT && BT_CSIP_SET_COORDINATOR) || BT_BAP_BROADCAST_SOURCE depends on BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE >= 4 - select EXPERIMENTAL help Enabling this will enable the CAP Initiator role. config BT_CAP_COMMANDER - bool "Common Audio Profile Initiator Role Support [EXPERIMENTAL]" + bool "Common Audio Profile Initiator Role Support" depends on (BT_BAP_BROADCAST_ASSISTANT && BT_BAP_SCAN_DELEGATOR && BT_CSIP_SET_COORDINATOR) || \ (BT_BAP_SCAN_DELEGATOR && BT_CSIP_SET_COORDINATOR) || \ (BT_VCP_VOL_CTLR && BT_CSIP_SET_COORDINATOR) || \ (BT_MICP_MIC_CTLR && BT_CSIP_SET_COORDINATOR) || \ BT_TBS_CLIENT || \ BT_MCC - select EXPERIMENTAL help Enabling this will enable the CAP Initiator role. diff --git a/subsys/bluetooth/audio/Kconfig.csip b/subsys/bluetooth/audio/Kconfig.csip index 878962feb410ff..ca72550843af88 100644 --- a/subsys/bluetooth/audio/Kconfig.csip +++ b/subsys/bluetooth/audio/Kconfig.csip @@ -9,9 +9,8 @@ #################### Coordinated Set Identification Service #################### config BT_CSIP_SET_MEMBER - bool "Coordinated Set Identification Profile Set Member support [EXPERIMENTAL]" + bool "Coordinated Set Identification Profile Set Member support" imply BT_EXT_ADV if BT_PRIVACY - select EXPERIMENTAL help This option enables support for Coordinated Set Identification Profile Set Member role and the Coordinated Set Identification @@ -57,10 +56,9 @@ endif # BT_CSIP_SET_MEMBER #################### Coordinated Set Identification Client #################### config BT_CSIP_SET_COORDINATOR - bool "Coordinated Set Identification Profile Set Coordinator Support [EXPERIMENTAL]" + bool "Coordinated Set Identification Profile Set Coordinator Support" select BT_GATT_CLIENT select BT_GATT_AUTO_DISCOVER_CCC - select EXPERIMENTAL help This option enables support for Coordinated Set Identification Profile Set Coordinator. diff --git a/subsys/bluetooth/audio/Kconfig.gmap b/subsys/bluetooth/audio/Kconfig.gmap index a9bd3024aa3666..bcf72962427c48 100644 --- a/subsys/bluetooth/audio/Kconfig.gmap +++ b/subsys/bluetooth/audio/Kconfig.gmap @@ -18,9 +18,8 @@ config BT_GMAP_BGR_SUPPORTED def_bool BT_CAP_ACCEPTOR && BT_BAP_BROADCAST_SINK && BT_VCP_VOL_REND config BT_GMAP - bool "Gaming Audio Profile [EXPERIMENTAL]" + bool "Gaming Audio Profile" depends on BT_CAP_ACCEPTOR || BT_CAP_INITIATOR - select EXPERIMENTAL help Enabling this will enable GMAP. diff --git a/subsys/bluetooth/audio/Kconfig.has b/subsys/bluetooth/audio/Kconfig.has index a66831d1eb7c17..f0d89d7b585b1d 100644 --- a/subsys/bluetooth/audio/Kconfig.has +++ b/subsys/bluetooth/audio/Kconfig.has @@ -5,8 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 menuconfig BT_HAS - bool "Hearing Access Service support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Hearing Access Service support" select UTF8 select BT_GATT_DYNAMIC_DB depends on BT_BAP_UNICAST_SERVER @@ -56,8 +55,7 @@ endif # BT_HAS_PRESET_SUPPORT endif # BT_HAS config BT_HAS_CLIENT - bool "Hearing Access Service Client support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Hearing Access Service Client support" select BT_GATT_CLIENT select BT_GATT_AUTO_DISCOVER_CCC select BT_GATT_AUTO_UPDATE_MTU diff --git a/subsys/bluetooth/audio/Kconfig.mcs b/subsys/bluetooth/audio/Kconfig.mcs index d0b139e90b19db..ccd3d55cdacdff 100644 --- a/subsys/bluetooth/audio/Kconfig.mcs +++ b/subsys/bluetooth/audio/Kconfig.mcs @@ -13,7 +13,6 @@ config BT_MCS depends on MCTL_LOCAL_PLAYER_REMOTE_CONTROL depends on UTF8 select BT_CCID - select EXPERIMENTAL select BT_GATT_DYNAMIC_DB help This option enables support for the Media Control Service. @@ -24,7 +23,6 @@ config BT_MCC bool "Media Control Client Support" select BT_GATT_CLIENT select BT_GATT_AUTO_DISCOVER_CCC - select EXPERIMENTAL help This option enables support for the Media Control Client. diff --git a/subsys/bluetooth/audio/Kconfig.mctl b/subsys/bluetooth/audio/Kconfig.mctl index cb14218068cf2a..ed632848d23a22 100644 --- a/subsys/bluetooth/audio/Kconfig.mctl +++ b/subsys/bluetooth/audio/Kconfig.mctl @@ -11,7 +11,6 @@ config MCTL bool "Support for media player control" - select EXPERIMENTAL help Enables support for control of local and remote media players To enable support for control of a local media player, support for diff --git a/subsys/bluetooth/audio/Kconfig.micp b/subsys/bluetooth/audio/Kconfig.micp index 15b8191d2f8b76..ef4f8928650fa3 100644 --- a/subsys/bluetooth/audio/Kconfig.micp +++ b/subsys/bluetooth/audio/Kconfig.micp @@ -9,8 +9,7 @@ ########### Microphone Control Profile Microphone Device ########### config BT_MICP_MIC_DEV - bool "Microphone Control Profile Microphone Device Support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Microphone Control Profile Microphone Device Support" select BT_GATT_DYNAMIC_DB help This option enables support for Microphone Control Profile @@ -39,10 +38,9 @@ endif # BT_MICP_MIC_DEV ########### Microphone Control Profile Microphone Controller ########### config BT_MICP_MIC_CTLR - bool "Microphone Control Profile Microphone Controller Support [EXPERIMENTAL]" + bool "Microphone Control Profile Microphone Controller Support" select BT_GATT_CLIENT select BT_GATT_AUTO_DISCOVER_CCC - select EXPERIMENTAL help This option enables support for the Microphone Control Profile Microphone Controller role diff --git a/subsys/bluetooth/audio/Kconfig.mpl b/subsys/bluetooth/audio/Kconfig.mpl index 2e7fcb384200a3..69efefe5b91cd2 100644 --- a/subsys/bluetooth/audio/Kconfig.mpl +++ b/subsys/bluetooth/audio/Kconfig.mpl @@ -9,7 +9,6 @@ config BT_MPL bool "Support for media player" select BT_CCID - select EXPERIMENTAL help Enables support for media player Note that the provided media player is a sample that only provides a diff --git a/subsys/bluetooth/audio/Kconfig.pbp b/subsys/bluetooth/audio/Kconfig.pbp index cb24845b202b75..3a0e7ed2c73e9e 100644 --- a/subsys/bluetooth/audio/Kconfig.pbp +++ b/subsys/bluetooth/audio/Kconfig.pbp @@ -6,7 +6,6 @@ # config BT_PBP - bool "Public Broadcast Profile [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Public Broadcast Profile" help Enabling this will enable PBP. diff --git a/subsys/bluetooth/audio/Kconfig.tmap b/subsys/bluetooth/audio/Kconfig.tmap index a2bc94d6fb9420..aa5dd7e727c663 100644 --- a/subsys/bluetooth/audio/Kconfig.tmap +++ b/subsys/bluetooth/audio/Kconfig.tmap @@ -6,9 +6,8 @@ # config BT_TMAP - bool "Telephony and Media Audio Profile [EXPERIMENTAL]" + bool "Telephony and Media Audio Profile" depends on BT_CAP_ACCEPTOR || BT_CAP_INITIATOR - select EXPERIMENTAL help Enabling this will enable TMAP. diff --git a/subsys/bluetooth/audio/Kconfig.vcp b/subsys/bluetooth/audio/Kconfig.vcp index ed227defc1b123..084f1397d0c376 100644 --- a/subsys/bluetooth/audio/Kconfig.vcp +++ b/subsys/bluetooth/audio/Kconfig.vcp @@ -9,8 +9,7 @@ ################### Volume Control Profile Volume Renderer ################### config BT_VCP_VOL_REND - bool "Volume Control Profile Volume Renderer Support [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Volume Control Profile Volume Renderer Support" select BT_GATT_DYNAMIC_DB help This option enables support for Volume Control Profile Volume Renderer @@ -58,10 +57,9 @@ endif # BT_VCP_VOL_REND ################### Volume Control Profile Volume Controller ################### config BT_VCP_VOL_CTLR - bool "Volume Control Profile Volume Controller Support [EXPERIMENTAL]" + bool "Volume Control Profile Volume Controller Support" select BT_GATT_CLIENT select BT_GATT_AUTO_DISCOVER_CCC - select EXPERIMENTAL help This option enables support for Volume Control Profile Volume Controller. diff --git a/subsys/bluetooth/audio/Kconfig.vocs b/subsys/bluetooth/audio/Kconfig.vocs index 2b1e4362b13e42..d582b2aaab4a9e 100644 --- a/subsys/bluetooth/audio/Kconfig.vocs +++ b/subsys/bluetooth/audio/Kconfig.vocs @@ -8,7 +8,7 @@ ##################### Volume Offset Control Service ##################### config BT_VOCS_MAX_INSTANCE_COUNT - int "Volume Offset Control Service max instance count [EXPERIMENTAL]" + int "Volume Offset Control Service max instance count" default 0 range 0 15 help @@ -18,7 +18,6 @@ config BT_VOCS_MAX_INSTANCE_COUNT config BT_VOCS bool # hidden default y if BT_VOCS_MAX_INSTANCE_COUNT > 0 - select EXPERIMENTAL help This hidden option enables support for Volume Control Service. @@ -36,7 +35,7 @@ endif # BT_VOCS ##################### Volume Offset Control Service Client ##################### config BT_VOCS_CLIENT_MAX_INSTANCE_COUNT - int "Volume Offset Control Service client max instance count [EXPERIMENTAL]" + int "Volume Offset Control Service client max instance count" default 0 range 0 15 help @@ -46,6 +45,5 @@ config BT_VOCS_CLIENT_MAX_INSTANCE_COUNT config BT_VOCS_CLIENT bool # hidden default y if BT_VOCS_CLIENT_MAX_INSTANCE_COUNT > 0 - select EXPERIMENTAL help This hidden option enables support for Volume Offset Control Service. From e6f0dde5faeec52be8ac67bb25c96cda6da8fc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0890/1389] arch: arm: cortex_m: pm_s2ram: Add option for custom marking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s2ram procedure used RAM magic word for marking suspend-to-RAM. This method may not work in some cases, e.g. when global reset does not reset RAM content. In that case resuming from s2ram is detected when global reset occurred. RAM magic word method is the default but with CONFIG_PM_S2RAM_CUSTOM_MARKING a custom implementation can be provided. Signed-off-by: Krzysztof Chruściński --- arch/arm/core/cortex_m/pm_s2ram.S | 37 ++++++++++----------------- arch/arm/core/cortex_m/pm_s2ram.c | 23 ++++++++++++++++- include/zephyr/arch/common/pm_s2ram.h | 25 +++++++++++++++++- subsys/pm/Kconfig | 7 +++++ 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/arch/arm/core/cortex_m/pm_s2ram.S b/arch/arm/core/cortex_m/pm_s2ram.S index aa715c8bbb90d1..1e5bca04fe294d 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.S +++ b/arch/arm/core/cortex_m/pm_s2ram.S @@ -14,12 +14,11 @@ #include #include -#define MAGIC (0xDABBAD00) - _ASM_FILE_PROLOGUE +GTEXT(pm_s2ram_mark_set) +GTEXT(pm_s2ram_mark_check_and_clear) GDATA(_cpu_context) -GDATA(marker) SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) /* @@ -64,11 +63,9 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) str r2, [r1, #___cpu_context_t_control_OFFSET] /* - * Set the marker to MAGIC value + * Mark entering suspend to RAM. */ - ldr r1, =marker - ldr r2, =MAGIC - str r2, [r1] + bl pm_s2ram_mark_set /* * Call the system_off function passed as parameter. This should never @@ -82,35 +79,29 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) */ /* - * Reset the marker + * Reset the marking of suspend to RAM, return is ignored. */ - ldr r1, =marker - mov r2, #0x0 - str r2, [r1] + push {r0} + bl pm_s2ram_mark_check_and_clear + pop {r0} pop {r4-r12, lr} bx lr + GTEXT(arch_pm_s2ram_resume) SECTION_FUNC(TEXT, arch_pm_s2ram_resume) /* - * Check if the marker is set + * Check if reset occurred after suspending to RAM. */ - ldr r0, =marker - ldr r0, [r0] - ldr r1, =MAGIC - cmp r0, r1 + push {lr} + bl pm_s2ram_mark_check_and_clear + cmp r0, #0x1 + pop {lr} beq resume bx lr resume: - /* - * Reset the marker - */ - ldr r0, =marker - mov r1, #0x0 - str r1, [r0] - /* * Restore the CPU context */ diff --git a/arch/arm/core/cortex_m/pm_s2ram.c b/arch/arm/core/cortex_m/pm_s2ram.c index 7b499278dd277e..2657d48dc32a12 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.c +++ b/arch/arm/core/cortex_m/pm_s2ram.c @@ -9,12 +9,33 @@ #include +#define MAGIC (0xDABBAD00) + /** * CPU context for S2RAM */ __noinit _cpu_context_t _cpu_context; +#ifndef CONFIG_PM_S2RAM_CUSTOM_MARKING /** * S2RAM Marker */ -__noinit uint32_t marker; +static __noinit uint32_t marker; + +void pm_s2ram_mark_set(void) +{ + marker = MAGIC; +} + +bool pm_s2ram_mark_check_and_clear(void) +{ + if (marker == MAGIC) { + marker = 0; + + return true; + } + + return false; +} + +#endif /* CONFIG_PM_S2RAM_CUSTOM_MARKING */ diff --git a/include/zephyr/arch/common/pm_s2ram.h b/include/zephyr/arch/common/pm_s2ram.h index 16443f2d105fdd..451794a53a2468 100644 --- a/include/zephyr/arch/common/pm_s2ram.h +++ b/include/zephyr/arch/common/pm_s2ram.h @@ -7,7 +7,6 @@ * * @brief public S2RAM APIs. * @defgroup pm_s2ram S2RAM APIs - * @ingroup subsys_pm * @{ */ @@ -57,6 +56,30 @@ typedef int (*pm_s2ram_system_off_fn_t)(void); */ int arch_pm_s2ram_suspend(pm_s2ram_system_off_fn_t system_off); +/** + * @brief Mark that core is entering suspend-to-RAM state. + * + * Function is called when system state is stored to RAM, just before going to system + * off. + * + * Default implementation is setting a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING + * allows custom implementation. + */ +void pm_s2ram_mark_set(void); + +/** + * @brief Check suspend-to-RAM marking and clear its state. + * + * Function is used to determine if resuming after suspend-to-RAM shall be performed + * or standard boot code shall be executed. + * + * Default implementation is checking a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING + * allows custom implementation. + * + * @retval true if marking is found which indicates resuming after suspend-to-RAM. + * @retval false if marking is not found which indicates standard boot. + */ +bool pm_s2ram_mark_check_and_clear(void); /** * @} */ diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index 621a5407ac6ceb..eda7569c917a30 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -37,6 +37,13 @@ config PM_S2RAM help This option enables suspend-to-RAM (S2RAM). +config PM_S2RAM_CUSTOM_MARKING + bool "Use custom marking functions" + depends on PM_S2RAM + help + By default a magic word in RAM is used to mark entering suspend-to-RAM. Enabling + this option allows custom implementation of functions which handles the marking. + config PM_NEED_ALL_DEVICES_IDLE bool "System Low Power Mode Needs All Devices Idle" depends on PM_DEVICE && !SMP From f0fd5f4a3cc44feefbd5469da2de4058aae1e94a Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0891/1389] drivers: sensor: sensor_shell: fix infinite loop when doing `sensor get` Should increment `ch.chan_idx` instead of `channel_idx`, otherwise we will be stucked in the loop forever. Signed-off-by: Yong Cong Sin --- drivers/sensor/sensor_shell.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 84d11f152c23a8..8b26b1fed8d85e 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -336,7 +336,6 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len uint32_t fit = 0; size_t base_size; size_t frame_size; - size_t channel_idx = 0; uint16_t frame_count; /* Channels with multi-axis equivalents are skipped */ @@ -504,7 +503,7 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len PRIsensor_q31_data_arg(*data, 0)); } } - ++channel_idx; + ++ch.chan_idx; } } } From a1f30291c15ebe1b588baddec9d817716245df3e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0892/1389] drivers: udc_dwc2: rework controller initialization Move most of the controller initialization to a separate function called during udc_enable(). This allows us to add support for the platform where the device controller is only available when VBUS is present and the PHY is powered. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_dwc2.c | 92 ++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 2f6825e52b709d..dba38aa6510932 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -1324,30 +1324,6 @@ static enum udc_bus_speed udc_dwc2_device_speed(const struct device *dev) } } -static int udc_dwc2_enable(const struct device *dev) -{ - struct usb_dwc2_reg *const base = dwc2_get_base(dev); - mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; - - /* Disable soft disconnect */ - sys_clear_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); - LOG_DBG("Enable device %p", base); - - return 0; -} - -static int udc_dwc2_disable(const struct device *dev) -{ - struct usb_dwc2_reg *const base = dwc2_get_base(dev); - mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; - - /* Enable soft disconnect */ - sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); - LOG_DBG("Disable device %p", dev); - - return 0; -} - static int dwc2_core_soft_reset(const struct device *dev) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); @@ -1386,7 +1362,7 @@ static int dwc2_core_soft_reset(const struct device *dev) return 0; } -static int udc_dwc2_init(const struct device *dev) +static int udc_dwc2_init_controller(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; struct udc_dwc2_data *const priv = udc_get_private(dev); @@ -1399,19 +1375,6 @@ static int udc_dwc2_init(const struct device *dev) uint32_t ghwcfg4; int ret; - if (config->quirks != NULL && config->quirks->clk_enable != NULL) { - LOG_DBG("Enable vendor clock"); - ret = config->quirks->clk_enable(dev); - if (ret) { - return ret; - } - } - - ret = dwc2_init_pinctrl(dev); - if (ret) { - return ret; - } - ret = dwc2_core_soft_reset(dev); if (ret) { return ret; @@ -1551,13 +1514,26 @@ static int udc_dwc2_init(const struct device *dev) USB_DWC2_GINTSTS_SOF, (mem_addr_t)&base->gintmsk); + return 0; +} + +static int udc_dwc2_enable(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + int err; + + err = udc_dwc2_init_controller(dev); + if (err) { + return err; + } /* Call vendor-specific function to enable peripheral */ if (config->quirks != NULL && config->quirks->pwr_on != NULL) { LOG_DBG("Enable vendor power"); - ret = config->quirks->pwr_on(dev); - if (ret) { - return ret; + err = config->quirks->pwr_on(dev); + if (err) { + return err; } } @@ -1565,13 +1541,22 @@ static int udc_dwc2_init(const struct device *dev) sys_set_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK); config->irq_enable_func(dev); + /* Disable soft disconnect */ + sys_clear_bits((mem_addr_t)&base->dctl, USB_DWC2_DCTL_SFTDISCON); + LOG_DBG("Enable device %p", base); + return 0; } -static int udc_dwc2_shutdown(const struct device *dev) +static int udc_dwc2_disable(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; - struct usb_dwc2_reg *const base = config->base; + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; + + /* Enable soft disconnect */ + sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); + LOG_DBG("Disable device %p", dev); config->irq_disable_func(dev); sys_clear_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK); @@ -1589,6 +1574,27 @@ static int udc_dwc2_shutdown(const struct device *dev) return 0; } +static int udc_dwc2_init(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + int ret; + + if (config->quirks != NULL && config->quirks->clk_enable != NULL) { + LOG_DBG("Enable vendor clock"); + ret = config->quirks->clk_enable(dev); + if (ret) { + return ret; + } + } + + return dwc2_init_pinctrl(dev); +} + +static int udc_dwc2_shutdown(const struct device *dev) +{ + return 0; +} + static int dwc2_driver_preinit(const struct device *dev) { const struct udc_dwc2_config *config = dev->config; From 1caaaed813c26eae9b8ea1e66f86fd603c1a09a9 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0893/1389] drivers: udc_dwc2: rework vendor quirks Rework and rename vendor quirks to better reflect where they intended to be called. Number of quirks probably not final and will be trimmed later. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_dwc2.c | 49 +++++++++++++++--------- drivers/usb/udc/udc_dwc2.h | 35 +++++++++++++++-- drivers/usb/udc/udc_dwc2_vendor_quirks.h | 29 +++++++++----- 3 files changed, 82 insertions(+), 31 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index dba38aa6510932..0f744ca439785e 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -6,7 +6,6 @@ #include "udc_common.h" #include "udc_dwc2.h" -#include "udc_dwc2_vendor_quirks.h" #include #include @@ -22,6 +21,7 @@ #include LOG_MODULE_REGISTER(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); +#include "udc_dwc2_vendor_quirks.h" enum dwc2_drv_event_type { /* Trigger next transfer, must not be used for control OUT */ @@ -904,9 +904,7 @@ static void udc_dwc2_isr_handler(const struct device *dev) } } - if (config->quirks != NULL && config->quirks->irq_clear != NULL) { - config->quirks->irq_clear(dev); - } + (void)dwc2_quirk_irq_clear(dev); } static int udc_dwc2_ep_enqueue(const struct device *dev, @@ -1523,18 +1521,21 @@ static int udc_dwc2_enable(const struct device *dev) struct usb_dwc2_reg *const base = dwc2_get_base(dev); int err; + err = dwc2_quirk_pre_enable(dev); + if (err) { + LOG_ERR("Quirk pre enable failed %d", err); + return err; + } + err = udc_dwc2_init_controller(dev); if (err) { return err; } - /* Call vendor-specific function to enable peripheral */ - if (config->quirks != NULL && config->quirks->pwr_on != NULL) { - LOG_DBG("Enable vendor power"); - err = config->quirks->pwr_on(dev); - if (err) { - return err; - } + err = dwc2_quirk_post_enable(dev); + if (err) { + LOG_ERR("Quirk post enable failed %d", err); + return err; } /* Enable global interrupt */ @@ -1553,6 +1554,7 @@ static int udc_dwc2_disable(const struct device *dev) const struct udc_dwc2_config *const config = dev->config; struct usb_dwc2_reg *const base = dwc2_get_base(dev); mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; + int err; /* Enable soft disconnect */ sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); @@ -1571,20 +1573,23 @@ static int udc_dwc2_disable(const struct device *dev) return -EIO; } + err = dwc2_quirk_disable(dev); + if (err) { + LOG_ERR("Quirk disable failed %d", err); + return err; + } + return 0; } static int udc_dwc2_init(const struct device *dev) { - const struct udc_dwc2_config *const config = dev->config; int ret; - if (config->quirks != NULL && config->quirks->clk_enable != NULL) { - LOG_DBG("Enable vendor clock"); - ret = config->quirks->clk_enable(dev); - if (ret) { - return ret; - } + ret = dwc2_quirk_init(dev); + if (ret) { + LOG_ERR("Quirk init failed %d", ret); + return ret; } return dwc2_init_pinctrl(dev); @@ -1592,6 +1597,14 @@ static int udc_dwc2_init(const struct device *dev) static int udc_dwc2_shutdown(const struct device *dev) { + int ret; + + ret = dwc2_quirk_shutdown(dev); + if (ret) { + LOG_ERR("Quirk shutdown failed %d", ret); + return ret; + } + return 0; } diff --git a/drivers/usb/udc/udc_dwc2.h b/drivers/usb/udc/udc_dwc2.h index 11d8178c135b0b..37c9a1eca38936 100644 --- a/drivers/usb/udc/udc_dwc2.h +++ b/drivers/usb/udc/udc_dwc2.h @@ -14,10 +14,17 @@ /* Vendor quirks per driver instance */ struct dwc2_vendor_quirks { - int (*clk_enable)(const struct device *dev); - int (*clk_disable)(const struct device *dev); - int (*pwr_on)(const struct device *dev); - int (*pwr_off)(const struct device *dev); + /* Called at the beginning of udc_dwc2_init() */ + int (*init)(const struct device *dev); + /* Called on udc_dwc2_enable() before the controller is initialized */ + int (*pre_enable)(const struct device *dev); + /* Called on udc_dwc2_enable() after the controller is initialized */ + int (*post_enable)(const struct device *dev); + /* Called at the end of udc_dwc2_disable() */ + int (*disable)(const struct device *dev); + /* Called at the end of udc_dwc2_shutdown() */ + int (*shutdown)(const struct device *dev); + /* Called at the end of IRQ handling */ int (*irq_clear)(const struct device *dev); }; @@ -37,4 +44,24 @@ struct udc_dwc2_config { void (*irq_disable_func)(const struct device *dev); }; +#define DWC2_QUIRK_FUNC_DEFINE(fname) \ +static inline int dwc2_quirk_##fname(const struct device *dev) \ +{ \ + const struct udc_dwc2_config *const config = dev->config; \ + struct dwc2_vendor_quirks *quirks = config->quirks; \ + \ + if (quirks != NULL && config->quirks->fname != NULL) { \ + return quirks->fname(dev); \ + } \ + \ + return 0; \ +} + +DWC2_QUIRK_FUNC_DEFINE(init) +DWC2_QUIRK_FUNC_DEFINE(pre_enable) +DWC2_QUIRK_FUNC_DEFINE(post_enable) +DWC2_QUIRK_FUNC_DEFINE(disable) +DWC2_QUIRK_FUNC_DEFINE(shutdown) +DWC2_QUIRK_FUNC_DEFINE(irq_clear) + #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_H */ diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index 104cb5cb8474f1..f96ad9312533c9 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -11,13 +11,13 @@ #include #include + +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) + #include #include - #include -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) - struct usb_dw_stm32_clk { const struct device *const dev; const struct stm32_pclken *const pclken; @@ -26,7 +26,7 @@ struct usb_dw_stm32_clk { #define DT_DRV_COMPAT snps_dwc2 -static inline int clk_enable_stm32f4_fsotg(const struct usb_dw_stm32_clk *const clk) +static inline int stm32f4_fsotg_enable_clk(const struct usb_dw_stm32_clk *const clk) { int ret; @@ -59,7 +59,7 @@ static inline int clk_enable_stm32f4_fsotg(const struct usb_dw_stm32_clk *const return clock_control_on(clk->dev, (void *)&clk->pclken[0]); } -static inline int pwr_on_stm32f4_fsotg(const struct device *dev) +static inline int stm32f4_fsotg_enable_phy(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio; @@ -69,6 +69,16 @@ static inline int pwr_on_stm32f4_fsotg(const struct device *dev) return 0; } +static inline int stm32f4_fsotg_disable_phy(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio; + + sys_clear_bits(ggpio_reg, USB_DWC2_GGPIO_STM32_PWRDWN | USB_DWC2_GGPIO_STM32_VBDEN); + + return 0; +} + #define QUIRK_STM32F4_FSOTG_DEFINE(n) \ static const struct stm32_pclken pclken_##n[] = STM32_DT_INST_CLOCKS(n);\ \ @@ -78,14 +88,15 @@ static inline int pwr_on_stm32f4_fsotg(const struct device *dev) .pclken_len = DT_INST_NUM_CLOCKS(n), \ }; \ \ - static int clk_enable_stm32f4_fsotg_##n(const struct device *dev) \ + static int stm32f4_fsotg_enable_clk_##n(const struct device *dev) \ { \ - return clk_enable_stm32f4_fsotg(&stm32f4_clk_##n); \ + return stm32f4_fsotg_enable_clk(&stm32f4_clk_##n); \ } \ \ struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ - .clk_enable = clk_enable_stm32f4_fsotg_##n, \ - .pwr_on = pwr_on_stm32f4_fsotg, \ + .pre_enable = stm32f4_fsotg_enable_clk_##n, \ + .post_enable = stm32f4_fsotg_enable_phy, \ + .disable = stm32f4_fsotg_disable_phy, \ .irq_clear = NULL, \ }; From 9d0e5cc9e1cbf3dfc5a30fec732adf73ba5d1ec0 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0894/1389] drivers: udc_dwc2: use devicetree to configure endpoint capabilities Although we can get the number of configured OUT and IN endpoints and endpoint capabilities from the DWC GHWCFGn registers, we need to configure the number of endpoint configuration structs at build time. On some platforms, we cannot access the hardware register at pre-init, so we use the GHWCFGn values from the devicetree to provide endpoint capabilities. This can be considered a workaround, and we may change the upper layer internals to avoid it in the future. Also, add a new vendor quirk to fill in platform-specific controller capabilities. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_dwc2.c | 110 ++++++++++++------ drivers/usb/udc/udc_dwc2.h | 10 +- dts/arm/intel_socfpga_std/socfpga.dtsi | 10 ++ dts/bindings/usb/snps,dwc2.yaml | 33 ++++++ .../usb/cdc_acm/nucleo_f413zh_dwc2.overlay | 5 + .../usb/shell/nucleo_f413zh_dwc2.overlay | 5 + 6 files changed, 138 insertions(+), 35 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 0f744ca439785e..f533490da259dd 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -54,12 +54,6 @@ K_MSGQ_DEFINE(drv_msgq, sizeof(struct dwc2_drv_event), /* TX FIFO0 depth in 32-bit words (used by control IN endpoint) */ #define UDC_DWC2_FIFO0_DEPTH 16U -/* Number of endpoints supported by the driver. - * This must be equal to or greater than the number supported by the hardware. - * (FIXME) - */ -#define UDC_DWC2_DRV_EP_NUM 8 - /* Get Data FIFO access register */ #define UDC_DWC2_EP_FIFO(base, idx) ((mem_addr_t)base + 0x1000 * (idx + 1)) @@ -1613,6 +1607,8 @@ static int dwc2_driver_preinit(const struct device *dev) const struct udc_dwc2_config *config = dev->config; struct udc_data *data = dev->data; uint16_t mps = 1023; + uint32_t numdeveps; + uint32_t ineps; int err; k_mutex_init(&data->mutex); @@ -1620,49 +1616,93 @@ static int dwc2_driver_preinit(const struct device *dev) data->caps.rwup = true; data->caps.addr_before_status = true; data->caps.mps0 = UDC_MPS0_64; - if (config->speed_idx == 2) { - data->caps.hs = true; + + (void)dwc2_quirk_caps(dev); + if (data->caps.hs) { mps = 1024; } - for (int i = 0; i < config->num_of_eps; i++) { - config->ep_cfg_out[i].caps.out = 1; + /* + * At this point, we cannot or do not want to access the hardware + * registers to get GHWCFGn values. For now, we will use devicetree to + * get GHWCFGn values and use them to determine the number and type of + * configured endpoints in the hardware. This can be considered a + * workaround, and we may change the upper layer internals to avoid it + * in the future. + */ + ineps = usb_dwc2_get_ghwcfg4_ineps(config->ghwcfg4) + 1U; + numdeveps = usb_dwc2_get_ghwcfg2_numdeveps(config->ghwcfg2) + 1U; + LOG_DBG("Number of endpoints (NUMDEVEPS + 1) %u", numdeveps); + LOG_DBG("Number of IN endpoints (INEPS + 1) %u", ineps); + + for (uint32_t i = 0, n = 0; i < numdeveps; i++) { + uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(config->ghwcfg1, i); + + if (epdir != USB_DWC2_GHWCFG1_EPDIR_OUT && + epdir != USB_DWC2_GHWCFG1_EPDIR_BDIR) { + continue; + } + if (i == 0) { - config->ep_cfg_out[i].caps.control = 1; - config->ep_cfg_out[i].caps.mps = 64; + config->ep_cfg_out[n].caps.control = 1; + config->ep_cfg_out[n].caps.mps = 64; } else { - config->ep_cfg_out[i].caps.bulk = 1; - config->ep_cfg_out[i].caps.interrupt = 1; - config->ep_cfg_out[i].caps.iso = 1; - config->ep_cfg_out[i].caps.mps = mps; + config->ep_cfg_out[n].caps.bulk = 1; + config->ep_cfg_out[n].caps.interrupt = 1; + config->ep_cfg_out[n].caps.iso = 1; + config->ep_cfg_out[n].caps.mps = mps; } - config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; - err = udc_register_ep(dev, &config->ep_cfg_out[i]); + config->ep_cfg_out[n].caps.out = 1; + config->ep_cfg_out[n].addr = USB_EP_DIR_OUT | i; + + LOG_DBG("Register ep 0x%02x (%u)", i, n); + err = udc_register_ep(dev, &config->ep_cfg_out[n]); if (err != 0) { LOG_ERR("Failed to register endpoint"); return err; } + + n++; + /* Also check the number of desired OUT endpoints in devicetree. */ + if (n >= config->num_out_eps) { + break; + } } - for (int i = 0; i < config->num_of_eps; i++) { - config->ep_cfg_in[i].caps.in = 1; + for (uint32_t i = 0, n = 0; i < numdeveps; i++) { + uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(config->ghwcfg1, i); + + if (epdir != USB_DWC2_GHWCFG1_EPDIR_IN && + epdir != USB_DWC2_GHWCFG1_EPDIR_BDIR) { + continue; + } + if (i == 0) { - config->ep_cfg_in[i].caps.control = 1; - config->ep_cfg_in[i].caps.mps = 64; + config->ep_cfg_in[n].caps.control = 1; + config->ep_cfg_in[n].caps.mps = 64; } else { - config->ep_cfg_in[i].caps.bulk = 1; - config->ep_cfg_in[i].caps.interrupt = 1; - config->ep_cfg_in[i].caps.iso = 1; - config->ep_cfg_in[i].caps.mps = mps; + config->ep_cfg_in[n].caps.bulk = 1; + config->ep_cfg_in[n].caps.interrupt = 1; + config->ep_cfg_in[n].caps.iso = 1; + config->ep_cfg_in[n].caps.mps = mps; } - config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; - err = udc_register_ep(dev, &config->ep_cfg_in[i]); + config->ep_cfg_in[n].caps.in = 1; + config->ep_cfg_in[n].addr = USB_EP_DIR_IN | i; + + LOG_DBG("Register ep 0x%02x (%u)", USB_EP_DIR_IN | i, n); + err = udc_register_ep(dev, &config->ep_cfg_in[n]); if (err != 0) { LOG_ERR("Failed to register endpoint"); return err; } + + n++; + /* Also check the number of desired IN endpoints in devicetree. */ + if (n >= MIN(ineps, config->num_in_eps)) { + break; + } } config->make_thread(dev); @@ -1770,19 +1810,23 @@ static const struct udc_api udc_dwc2_api = { irq_disable(DT_INST_IRQN(n)); \ } \ \ - static struct udc_ep_config ep_cfg_out[UDC_DWC2_DRV_EP_NUM]; \ - static struct udc_ep_config ep_cfg_in[UDC_DWC2_DRV_EP_NUM]; \ + static struct udc_ep_config ep_cfg_out[DT_INST_PROP(n, num_out_eps)]; \ + static struct udc_ep_config ep_cfg_in[DT_INST_PROP(n, num_in_eps)]; \ \ static const struct udc_dwc2_config udc_dwc2_config_##n = { \ - .num_of_eps = UDC_DWC2_DRV_EP_NUM, \ - .ep_cfg_in = ep_cfg_out, \ - .ep_cfg_out = ep_cfg_in, \ + .num_out_eps = DT_INST_PROP(n, num_out_eps), \ + .num_in_eps = DT_INST_PROP(n, num_in_eps), \ + .ep_cfg_in = ep_cfg_in, \ + .ep_cfg_out = ep_cfg_out, \ .make_thread = udc_dwc2_make_thread_##n, \ .base = (struct usb_dwc2_reg *)UDC_DWC2_DT_INST_REG_ADDR(n), \ .pcfg = UDC_DWC2_PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .irq_enable_func = udc_dwc2_irq_enable_func_##n, \ .irq_disable_func = udc_dwc2_irq_disable_func_##n, \ .quirks = UDC_DWC2_VENDOR_QUIRK_GET(n), \ + .ghwcfg1 = DT_INST_PROP(n, ghwcfg1), \ + .ghwcfg2 = DT_INST_PROP(n, ghwcfg2), \ + .ghwcfg4 = DT_INST_PROP(n, ghwcfg4), \ }; \ \ static struct udc_dwc2_data udc_priv_##n = { \ diff --git a/drivers/usb/udc/udc_dwc2.h b/drivers/usb/udc/udc_dwc2.h index 37c9a1eca38936..b54cb82fd2a712 100644 --- a/drivers/usb/udc/udc_dwc2.h +++ b/drivers/usb/udc/udc_dwc2.h @@ -26,14 +26,16 @@ struct dwc2_vendor_quirks { int (*shutdown)(const struct device *dev); /* Called at the end of IRQ handling */ int (*irq_clear)(const struct device *dev); + /* Called on driver pre-init */ + int (*caps)(const struct device *dev); }; /* Driver configuration per instance */ struct udc_dwc2_config { - size_t num_of_eps; + size_t num_in_eps; + size_t num_out_eps; struct udc_ep_config *ep_cfg_in; struct udc_ep_config *ep_cfg_out; - int speed_idx; struct usb_dwc2_reg *const base; /* Pointer to pin control configuration or NULL */ struct pinctrl_dev_config *const pcfg; @@ -42,6 +44,9 @@ struct udc_dwc2_config { void (*make_thread)(const struct device *dev); void (*irq_enable_func)(const struct device *dev); void (*irq_disable_func)(const struct device *dev); + uint32_t ghwcfg1; + uint32_t ghwcfg2; + uint32_t ghwcfg4; }; #define DWC2_QUIRK_FUNC_DEFINE(fname) \ @@ -63,5 +68,6 @@ DWC2_QUIRK_FUNC_DEFINE(post_enable) DWC2_QUIRK_FUNC_DEFINE(disable) DWC2_QUIRK_FUNC_DEFINE(shutdown) DWC2_QUIRK_FUNC_DEFINE(irq_clear) +DWC2_QUIRK_FUNC_DEFINE(caps) #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_H */ diff --git a/dts/arm/intel_socfpga_std/socfpga.dtsi b/dts/arm/intel_socfpga_std/socfpga.dtsi index 7e1f37267d5cec..ad36609bfa1b28 100644 --- a/dts/arm/intel_socfpga_std/socfpga.dtsi +++ b/dts/arm/intel_socfpga_std/socfpga.dtsi @@ -227,6 +227,11 @@ reg = <0xffb30000 0xffff>; interrupts = <0 127 4 IRQ_DEFAULT_PRIORITY>; interrupt-parent = <&intc>; + num-out-eps = <16>; + num-in-eps = <16>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x208ffc90>; + ghwcfg4 = <0xfe0f0020>; status = "disabled"; }; @@ -235,6 +240,11 @@ reg = <0xffb40000 0xffff>; interrupts = <0 128 4 IRQ_DEFAULT_PRIORITY>; interrupt-parent = <&intc>; + num-out-eps = <16>; + num-in-eps = <16>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x208ffc90>; + ghwcfg4 = <0xfe0f0020>; status = "okay"; }; diff --git a/dts/bindings/usb/snps,dwc2.yaml b/dts/bindings/usb/snps,dwc2.yaml index 8af55448780f8c..d5b0167f26b326 100644 --- a/dts/bindings/usb/snps,dwc2.yaml +++ b/dts/bindings/usb/snps,dwc2.yaml @@ -18,3 +18,36 @@ properties: phys: type: phandle + + num-in-eps: + type: int + required: true + description: | + Number of configured OUT endpoints including control endpoint. + + num-out-eps: + type: int + required: true + description: | + Number of configured IN endpoints including control endpoint. + + ghwcfg1: + type: int + required: true + description: | + Value of the GHWCFG1 register. It is used to determine available endpoint + types during driver pre-initialization. + + ghwcfg2: + type: int + required: true + description: | + Value of the GHWCFG2 register. It is used to determine available endpoint + types during driver pre-initialization. + + ghwcfg4: + type: int + required: true + description: | + Value of the GHWCFG4 register. It is used to determine available endpoint + types during driver pre-initialization. diff --git a/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay b/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay index 8cd2525699c391..d1e6b29edbd3c6 100644 --- a/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay +++ b/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay @@ -15,6 +15,11 @@ interrupt-names = "fsotg"; clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>, <&rcc STM32_SRC_PLL_Q NO_SEL>; + num-out-eps = <6>; + num-in-eps = <6>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x229ed520>; + ghwcfg4 = <0x17f08030>; status = "disabled"; }; }; diff --git a/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay b/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay index ff51b08078efcf..2e954626ded216 100644 --- a/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay +++ b/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay @@ -15,6 +15,11 @@ interrupt-names = "fsotg"; clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>, <&rcc STM32_SRC_PLL_Q NO_SEL>; + num-out-eps = <6>; + num-in-eps = <6>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x229ed520>; + ghwcfg4 = <0x17f08030>; }; }; }; From e0415cbbc8f63a290ab813c110da0a01a46dc213 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0895/1389] drivers: udc_dwc2: add vendor quirks to support Nordic USBHS controller Add vendor quirks to support Nordic USBHS controller. Signed-off-by: Johann Fischer --- drivers/usb/udc/Kconfig.dwc2 | 2 + drivers/usb/udc/udc_dwc2_vendor_quirks.h | 137 +++++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/drivers/usb/udc/Kconfig.dwc2 b/drivers/usb/udc/Kconfig.dwc2 index c05aed352665b8..a1a1c9d22cece7 100644 --- a/drivers/usb/udc/Kconfig.dwc2 +++ b/drivers/usb/udc/Kconfig.dwc2 @@ -5,6 +5,8 @@ config UDC_DWC2 bool "DWC2 USB device controller driver" default y depends on DT_HAS_SNPS_DWC2_ENABLED + select NRFS if NRFS_HAS_VBUS_DETECTOR_SERVICE + select NRFS_VBUS_DETECTOR_SERVICE_ENABLED if NRFS_HAS_VBUS_DETECTOR_SERVICE help DWC2 USB device controller driver. diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index f96ad9312533c9..c06a41572b3bde 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -11,6 +11,7 @@ #include #include +#include #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) @@ -107,6 +108,142 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) #endif /*DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) + +#define DT_DRV_COMPAT snps_dwc2 + +#include +#include + +#define USBHS_DT_WRAPPER_REG_ADDR(n) UINT_TO_POINTER(DT_INST_REG_ADDR_BY_NAME(n, wrapper)) + +static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) +{ + const struct device *dev = context; + + switch (p_evt->type) { + case NRFS_USB_EVT_VBUS_STATUS_CHANGE: + LOG_DBG("USBHS new status, pll_ok = %d vreg_ok = %d vbus_detected = %d", + p_evt->usbhspll_ok, p_evt->vregusb_ok, p_evt->vbus_detected); + + if (p_evt->usbhspll_ok && p_evt->vregusb_ok && p_evt->vbus_detected) { + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + } else { + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + } + + break; + case NRFS_USB_EVT_REJECT: + LOG_ERR("Request rejected"); + break; + default: + LOG_ERR("Unknown event type 0x%x", p_evt->type); + break; + } +} + +static inline int usbhs_enable_nrfs_service(const struct device *dev) +{ + nrfs_err_t nrfs_err; + int err; + + err = nrfs_backend_wait_for_connection(K_MSEC(1000)); + if (err) { + LOG_INF("NRFS backend connection timeout"); + return err; + } + + nrfs_err = nrfs_usb_init(usbhs_vbus_handler); + if (nrfs_err != NRFS_SUCCESS) { + LOG_ERR("Failed to init NRFS VBUS handler: %d", nrfs_err); + return -EIO; + } + + nrfs_err = nrfs_usb_enable_request((void *)dev); + if (nrfs_err != NRFS_SUCCESS) { + LOG_ERR("Failed to enable NRFS VBUS service: %d", nrfs_err); + return -EIO; + } + + return 0; +} + +static inline int usbhs_enable_core(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + wrapper->TASKS_START = 1UL; + + /* Enable interrupts */ + wrapper->INTENSET = 1UL; + + return 0; +} + +static inline int usbhs_disable_core(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + /* Disable interrupts */ + wrapper->INTENCLR = 1UL; + + wrapper->ENABLE = 0UL; + wrapper->TASKS_START = 1UL; + + return 0; +} + +static inline int usbhs_disable_nrfs_service(const struct device *dev) +{ + nrfs_err_t nrfs_err; + + nrfs_err = nrfs_usb_disable_request((void *)dev); + if (nrfs_err != NRFS_SUCCESS) { + LOG_ERR("Failed to disable NRFS VBUS service: %d", nrfs_err); + return -EIO; + } + + nrfs_usb_uninit(); + + return 0; +} + +static inline int usbhs_irq_clear(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + wrapper->EVENTS_CORE = 0UL; + + return 0; +} + +static inline int usbhs_init_caps(const struct device *dev) +{ + struct udc_data *data = dev->data; + + data->caps.can_detect_vbus = true; + data->caps.hs = true; + + return 0; +} + +#define QUIRK_NRF_USBHS_DEFINE(n) \ + struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ + .init = usbhs_enable_nrfs_service, \ + .pre_enable = usbhs_enable_core, \ + .disable = usbhs_disable_core, \ + .shutdown = usbhs_disable_nrfs_service, \ + .irq_clear = usbhs_irq_clear, \ + .caps = usbhs_init_caps, \ + }; + +DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) + +#undef DT_DRV_COMPAT + +#endif /*DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) */ + /* Add next vendor quirks definition above this line */ #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_VENDOR_QUIRKS_H */ From 5836eb4a16d8feebb19580504541ce6f3cdc6fd1 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0896/1389] drivers: udc_dwc2: fix interpretation of NUMDEVEPS and INEPS fields The NUMDEVEPS field provides the number of endpoints in addition to the control endpoint. It is used to iterate over GHWCFG1 register value to get correct number of configured IN/OUT endpoints. To get it correctly, we need to use it internally as number including control endpoint. Interpretation of INEPS misses +1 because value 0 means 1 IN endpoint and so on. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_dwc2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index f533490da259dd..e18aa6b96f6e7a 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -69,7 +69,7 @@ struct udc_dwc2_data { uint32_t max_pktcnt; uint32_t tx_len[16]; unsigned int dynfifosizing : 1; - /* Number of endpoints in addition to control endpoint */ + /* Number of endpoints including control endpoint */ uint8_t numdeveps; /* Number of IN endpoints including control endpoint */ uint8_t ineps; @@ -948,7 +948,7 @@ static void dwc2_unset_unused_fifo(const struct device *dev) struct udc_dwc2_data *const priv = udc_get_private(dev); struct udc_ep_config *tmp; - for (uint8_t i = priv->ineps; i > 0; i--) { + for (uint8_t i = priv->ineps - 1U; i > 0; i--) { tmp = udc_get_ep_cfg(dev, i | USB_EP_DIR_IN); if (tmp->stat.enabled && (priv->txf_set & BIT(i))) { @@ -1396,10 +1396,10 @@ static int udc_dwc2_init_controller(const struct device *dev) } /* Get the number or endpoints and IN endpoints we can use later */ - priv->numdeveps = usb_dwc2_get_ghwcfg2_numdeveps(ghwcfg2); - priv->ineps = usb_dwc2_get_ghwcfg4_ineps(ghwcfg4); - LOG_DBG("Number of endpoints (NUMDEVEPS) %u", priv->numdeveps); - LOG_DBG("Number of IN endpoints (INEPS) %u", priv->ineps); + priv->numdeveps = usb_dwc2_get_ghwcfg2_numdeveps(ghwcfg2) + 1U; + priv->ineps = usb_dwc2_get_ghwcfg4_ineps(ghwcfg4) + 1U; + LOG_DBG("Number of endpoints (NUMDEVEPS + 1) %u", priv->numdeveps); + LOG_DBG("Number of IN endpoints (INEPS + 1) %u", priv->ineps); LOG_DBG("Number of periodic IN endpoints (NUMDEVPERIOEPS) %u", usb_dwc2_get_ghwcfg4_numdevperioeps(ghwcfg4)); From 5d02b94688c4155040387b818ca1a0e3db605a24 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0897/1389] drivers: udc_dwc2: prevent access to registers if USBHS is not ready MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On USBHS, we cannot access the DWC2 register until VBUS is detected and valid. Kernel event API is used to block if a valid VBUS signal is not present when the user tries to force usbd_enable(). Signed-off-by: Tomasz Moń Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_dwc2_vendor_quirks.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index c06a41572b3bde..2311dd803086af 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -117,6 +117,15 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) #define USBHS_DT_WRAPPER_REG_ADDR(n) UINT_TO_POINTER(DT_INST_REG_ADDR_BY_NAME(n, wrapper)) +/* + * On USBHS, we cannot access the DWC2 register until VBUS is detected and + * valid. If the user tries to force usbd_enable() and the corresponding + * udc_enable() without a "VBUS ready" notification, the event wait will block + * until a valid VBUS signal is detected. + */ +static K_EVENT_DEFINE(usbhs_events); +#define USBHS_VBUS_READY BIT(0) + static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) { const struct device *dev = context; @@ -127,8 +136,10 @@ static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) p_evt->usbhspll_ok, p_evt->vregusb_ok, p_evt->vbus_detected); if (p_evt->usbhspll_ok && p_evt->vregusb_ok && p_evt->vbus_detected) { + k_event_post(&usbhs_events, USBHS_VBUS_READY); udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); } else { + k_event_set_masked(&usbhs_events, 0, USBHS_VBUS_READY); udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); } @@ -172,6 +183,11 @@ static inline int usbhs_enable_core(const struct device *dev) { NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { + LOG_WRN("VBUS is not ready, block udc_enable()"); + k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_FOREVER); + } + wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; wrapper->TASKS_START = 1UL; From f7ef465d38252479c9c24b17112c04100c9bad4e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0898/1389] dts: nordic: update USBHS node Add "nordic,nrf-usbhs" vendor compatible and new required properties. Signed-off-by: Johann Fischer --- dts/common/nordic/nrf54h20.dtsi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index a4b70ddcb3c80f..010819d0b6f094 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -333,10 +333,15 @@ ranges = <0x0 0x5f000000 0x1000000>; usbhs: usbhs@86000 { - compatible = "snps,dwc2"; + compatible = "nordic,nrf-usbhs", "snps,dwc2"; reg = <0x86000 0x1000>, <0x2f700000 0x40000>; reg-names = "wrapper", "core"; interrupts = <134 NRF_DEFAULT_IRQ_PRIORITY>; + num-in-eps = <8>; + num-out-eps = <10>; + ghwcfg1 = <0xaa555000>; + ghwcfg2 = <0x22abfc72>; + ghwcfg4 = <0x1e10aa60>; status = "disabled"; }; From 62a7eb145239405b026e3ad17acfd58800ced9c8 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0899/1389] boards: nrf54h20dk: enable USB device controller Enable USB device controller. Signed-off-by: Johann Fischer --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 4 ++++ boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + 2 files changed, 5 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 5cd3d5b78e8256..374a62724529e0 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -237,3 +237,7 @@ ipc0: &cpuapp_cpurad_ipc { &cpuapp_ieee802154 { status = "okay"; }; + +zephyr_udc0: &usbhs { + status = "okay"; +}; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 2f83ef80de6102..713f7c3c273471 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -17,3 +17,4 @@ supported: - pwm - spi - watchdog + - usb_device From 28f0ae6d64cc1fdfaa3dd54ed791a01358ba13ce Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0900/1389] samples: usb: add nrf54h20dk to allowed platforms nRF54H20DK board is first major user of new UDC DWC2 driver. Add nRF54H20DK (Application CPU) to allowed platforms in USB device samples. Signed-off-by: Johann Fischer --- samples/subsys/usb/cdc_acm/sample.yaml | 1 + samples/subsys/usb/hid-keyboard/sample.yaml | 1 + samples/subsys/usb/hid-mouse/sample.yaml | 1 + samples/subsys/usb/mass/sample.yaml | 1 + samples/subsys/usb/shell/sample.yaml | 1 + 5 files changed, 5 insertions(+) diff --git a/samples/subsys/usb/cdc_acm/sample.yaml b/samples/subsys/usb/cdc_acm/sample.yaml index 85dc6b7af27641..82365c1f245980 100644 --- a/samples/subsys/usb/cdc_acm/sample.yaml +++ b/samples/subsys/usb/cdc_acm/sample.yaml @@ -16,6 +16,7 @@ tests: extra_args: CONF_FILE="usbd_next_prj.conf" platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f - 96b_carbon/stm32f401xe harness: console diff --git a/samples/subsys/usb/hid-keyboard/sample.yaml b/samples/subsys/usb/hid-keyboard/sample.yaml index daf6703b81a5dd..726608009bad3c 100644 --- a/samples/subsys/usb/hid-keyboard/sample.yaml +++ b/samples/subsys/usb/hid-keyboard/sample.yaml @@ -8,6 +8,7 @@ common: - gpio platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f tests: sample.usbd.hid-keyboard: diff --git a/samples/subsys/usb/hid-mouse/sample.yaml b/samples/subsys/usb/hid-mouse/sample.yaml index 018c1a04b8021d..d7d79f83ec3bfd 100644 --- a/samples/subsys/usb/hid-mouse/sample.yaml +++ b/samples/subsys/usb/hid-mouse/sample.yaml @@ -12,6 +12,7 @@ tests: sample.usb_device_next.hid-mouse: platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f extra_args: - CONF_FILE="usbd_next_prj.conf" diff --git a/samples/subsys/usb/mass/sample.yaml b/samples/subsys/usb/mass/sample.yaml index d7c2c32bc59334..f2459019ce7fe1 100644 --- a/samples/subsys/usb/mass/sample.yaml +++ b/samples/subsys/usb/mass/sample.yaml @@ -24,6 +24,7 @@ tests: depends_on: usb_device platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f extra_args: - CONF_FILE="usbd_next_prj.conf" diff --git a/samples/subsys/usb/shell/sample.yaml b/samples/subsys/usb/shell/sample.yaml index 834044da3df5f3..246b6133a02a08 100644 --- a/samples/subsys/usb/shell/sample.yaml +++ b/samples/subsys/usb/shell/sample.yaml @@ -4,6 +4,7 @@ tests: sample.usbd.shell: platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f depends_on: usb_device harness: keyboard From 483c92da62d702e6e4ef07cffa14e73024d77910 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0901/1389] samples/posix/env: Change integration platform There is some instability problems with qemu_riscv32 https://github.com/zephyrproject-rtos/zephyr/issues/72858 which cause this sample test to fail in CI at random. Let's change the integration platform to a reliable one, so this test focuses on the sample and does not produce false test failures due to the platform. Signed-off-by: Alberto Escolar Piedras --- samples/posix/env/sample.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/posix/env/sample.yaml b/samples/posix/env/sample.yaml index c276b6b55f1d36..39ad4f088091d5 100644 --- a/samples/posix/env/sample.yaml +++ b/samples/posix/env/sample.yaml @@ -7,7 +7,7 @@ common: - native_posix - native_posix/native/64 integration_platforms: - - qemu_riscv32 + - native_sim harness: console harness_config: type: multi_line From 57e6ac474e852f9fb6915564d8de5121a339186b Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0902/1389] boards: st: nucleo_wba55cg: define all LEDs and buttons This board includes three gpio-connected LEDs and push-buttons. Include all missing defines in board's DTS and while at it, fix existing button definition (missing pull-up enable) and align node names with other boards (e.g. 'nucleo_wb55rg'). Provided changes were tested on real board with 'blinky' and 'button' samples. Additionally, duplicated LED nodes no longer required were removed from overlay file for this board, in 'suspend_to_ram' sample. Signed-off-by: Piotr Dymacz --- boards/st/nucleo_wba55cg/nucleo_wba55cg.dts | 32 ++++++++++++++++--- .../boards/nucleo_wba55cg.overlay | 12 ------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts index f956270a8529a6..0c22bf3796d207 100644 --- a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts +++ b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts @@ -29,24 +29,46 @@ leds: leds { compatible = "gpio-leds"; - blue_led_1: led_1 { + blue_led_1: led_0 { gpios = <&gpiob 4 GPIO_ACTIVE_LOW>; label = "User LD1"; }; + green_led_2: led_1 { + gpios = <&gpioa 9 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + red_led_3: led_2 { + gpios = <&gpiob 8 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; }; gpio_keys { compatible = "gpio-keys"; - user_button: button { - label = "User"; - gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; + user_button_1: button_0 { + label = "User B1"; + gpios = <&gpioc 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; zephyr,code = ; }; + user_button_2: button_1 { + label = "User B2"; + gpios = <&gpiob 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; + user_button_3: button_2 { + label = "User B3"; + gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; }; aliases { led0 = &blue_led_1; - sw0 = &user_button; + led1 = &green_led_2; + led2 = &red_led_3; + sw0 = &user_button_1; + sw1 = &user_button_2; + sw2 = &user_button_3; }; }; diff --git a/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay b/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay index bf8f1747cffc6c..5976dfdbc7600b 100644 --- a/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay +++ b/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay @@ -31,18 +31,6 @@ /* adjust channel number according to pinmux in board.dts */ io-channels = <&adc4 8>; }; - - leds: leds { - compatible = "gpio-leds"; - red_led_3: led_3 { - gpios = <&gpiob 8 GPIO_ACTIVE_LOW>; - label = "User LD2"; - }; - }; - - aliases { - led2 = &red_led_3; - }; }; &lptim1 { From d86ec392efb459017b3e294c0978fe73a971c1ea Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Sun, 26 May 2024 22:39:14 +0200 Subject: [PATCH 0903/1389] boards: st: nucleo_wba55cg: add mcuboot-{led0,button0} aliases This adds DT aliases for LED and button used in recovery mode of the MCUboot bootloader, on the 'nucleo_wba55cg' board. Signed-off-by: Piotr Dymacz --- boards/st/nucleo_wba55cg/nucleo_wba55cg.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts index 0c22bf3796d207..f3ba9c494e29a9 100644 --- a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts +++ b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts @@ -69,6 +69,8 @@ sw0 = &user_button_1; sw1 = &user_button_2; sw2 = &user_button_3; + mcuboot-led0 = &blue_led_1; + mcuboot-button0 = &user_button_1; }; }; From ed45489cf4e6cb398be5533855025cb53482aba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0904/1389] soc: nrf54h: use word accesses to SPI_DW peripheral MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nRF54H20 EXMIF peripheral requires word accesses. Doing accesses of byte or half-word sizes results in bus fault. Signed-off-by: Rafał Kuźnia --- soc/nordic/nrf54h/Kconfig.defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/nordic/nrf54h/Kconfig.defconfig b/soc/nordic/nrf54h/Kconfig.defconfig index ad06920c15ce83..b09b24e5e70408 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig +++ b/soc/nordic/nrf54h/Kconfig.defconfig @@ -36,4 +36,7 @@ endif # RISCV config SPI_DW_HSSI default y if SPI_DW +config SPI_DW_ACCESS_WORD_ONLY + default y if SPI_DW + endif # SOC_SERIES_NRF54HX From c094385d12bb9411a79ed6836ae08026e2e44ddf Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0905/1389] cmake: New target which generates a sort of development kit for llext Loadable extensions need access to Zephyr (and Zephyr application) includes and some CFLAGS to be properly built. This patch adds a new target, `llext-edk`, which generates a tar file with those includes and flags that can be loaded from cmake and make files. A Zephyr application willing to expose some API to extensions it loads only need to add the include directories describing such APIs to the Zephyr ones via zephyr_include_directories() CMake call. A new Kconfig option, CONFIG_LLEXT_EDK_NAME allows one to control some aspects of the generated file, which enables some customization - think of an application called ACME, willing to have a ACME_EXTENSION_KIT or something. All EDK Kconfig options are behind CONFIG_LLEXT_EDK, which doesn't depend on LLEXT directly - so that EDK features can be leveraged by downstream variations of loadable extensions. Also, each arch may need different compiler flags for extensions: those are handled by the `LLEXT_CFLAGS` cmake flag. An example is set for GCC ARM. Finally, EDK throughout this patch means Extension Development Kit, which is a bad name, but at least doesn't conflict with SDK. Signed-off-by: Ederson de Souza --- CMakeLists.txt | 20 +++++ cmake/compiler/gcc/target_arm.cmake | 6 ++ cmake/llext-edk.cmake | 109 ++++++++++++++++++++++++++++ cmake/usage/usage.cmake | 1 + subsys/llext/Kconfig | 13 ++++ 5 files changed, 149 insertions(+) create mode 100644 cmake/llext-edk.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fa2d371c4ab8d..22b60009baca09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2061,6 +2061,26 @@ if((CMAKE_BUILD_TYPE IN_LIST build_types) AND (NOT NO_BUILD_TYPE_WARNING)) endif() endif() +# Extension Development Kit (EDK) generation. +set(llext_edk_file ${PROJECT_BINARY_DIR}/${CONFIG_LLEXT_EDK_NAME}.tar.xz) +add_custom_command( + OUTPUT ${llext_edk_file} + COMMAND ${CMAKE_COMMAND} + -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} + -DAPPLICATION_SOURCE_DIR=${APPLICATION_SOURCE_DIR} + -DINTERFACE_INCLUDE_DIRECTORIES="$,:>" + -Dllext_edk_file=${llext_edk_file} + -DAUTOCONF_H=${AUTOCONF_H} + -DLLEXT_CFLAGS="${LLEXT_CFLAGS}" + -Dllext_edk_name=${CONFIG_LLEXT_EDK_NAME} + -DWEST_TOPDIR=${WEST_TOPDIR} + -DZEPHYR_BASE=${ZEPHYR_BASE} + -P ${ZEPHYR_BASE}/cmake/llext-edk.cmake + DEPENDS ${logical_target_for_zephyr_elf} + COMMAND_EXPAND_LISTS +) +add_custom_target(llext-edk DEPENDS ${llext_edk_file}) + # @Intent: Set compiler specific flags for standard C/C++ includes # Done at the very end, so any other system includes which may # be added by Zephyr components were first in list. diff --git a/cmake/compiler/gcc/target_arm.cmake b/cmake/compiler/gcc/target_arm.cmake index 77a718cc7259f8..7675e7cb6d51c4 100644 --- a/cmake/compiler/gcc/target_arm.cmake +++ b/cmake/compiler/gcc/target_arm.cmake @@ -58,3 +58,9 @@ set(LLEXT_APPEND_FLAGS -mlong-calls -mthumb ) + +set(LLEXT_CFLAGS + -mlong-calls + -mthumb + -nodefaultlibs + -c) diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake new file mode 100644 index 00000000000000..7c8cf4201f546e --- /dev/null +++ b/cmake/llext-edk.cmake @@ -0,0 +1,109 @@ +# Copyright (c) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# This script generates a tarball containing all headers and flags necessary to +# build an llext extension. It does so by copying all headers accessible from +# INTERFACE_INCLUDE_DIRECTORIES and generating a Makefile.cflags file (and a +# cmake.cflags one) with all flags necessary to build the extension. +# +# The tarball can be extracted and used in the extension build system to include +# all necessary headers and flags. File paths are made relative to a few key +# directories (build/zephyr, zephyr base, west top dir and application source +# dir), to avoid leaking any information about the host system. +# +# The following arguments are expected: +# - llext_edk_name: Name of the extension, used to name the tarball and the +# install directory variable for Makefile. +# - INTERFACE_INCLUDE_DIRECTORIES: List of include directories to copy headers +# from. It should simply be the INTERFACE_INCLUDE_DIRECTORIES property of the +# zephyr_interface target. +# - AUTOCONF_H: Name of the autoconf.h file, used to generate the imacros flag. +# - llext_edk_file: Output file name for the tarball. +# - LLEXT_CFLAGS: Additional flags to be added to the generated flags. +# - ZEPHYR_BASE: Path to the zephyr base directory. +# - WEST_TOPDIR: Path to the west top directory. +# - APPLICATION_SOURCE_DIR: Path to the application source directory. +# - PROJECT_BINARY_DIR: Path to the project binary build directory. + +cmake_minimum_required(VERSION 3.20.0) + +set(llext_edk ${PROJECT_BINARY_DIR}/${llext_edk_name}) +set(llext_edk_inc ${llext_edk}/include) + +string(REGEX REPLACE "[^a-zA-Z0-9]" "_" llext_edk_name_sane ${llext_edk_name}) +string(TOUPPER ${llext_edk_name_sane} llext_edk_name_sane) +set(install_dir_var "${llext_edk_name_sane}_INSTALL_DIR") + +cmake_path(CONVERT "${INTERFACE_INCLUDE_DIRECTORIES}" TO_CMAKE_PATH_LIST include_dirs) + +set(autoconf_h_edk ${llext_edk_inc}/${AUTOCONF_H}) +cmake_path(RELATIVE_PATH AUTOCONF_H BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE autoconf_h_rel) + +list(APPEND all_flags_make + "${LLEXT_CFLAGS} -imacros\$(${install_dir_var})/include/zephyr/${autoconf_h_rel}") +list(APPEND all_flags_cmake + "${LLEXT_CFLAGS} -imacros\${CMAKE_CURRENT_LIST_DIR}/include/zephyr/${autoconf_h_rel}") + +file(MAKE_DIRECTORY ${llext_edk_inc}) +foreach(dir ${include_dirs}) + if (NOT EXISTS ${dir}) + continue() + endif() + cmake_path(IS_PREFIX PROJECT_BINARY_DIR ${dir} NORMALIZE to_prj_bindir) + cmake_path(IS_PREFIX ZEPHYR_BASE ${dir} NORMALIZE to_zephyr_base) + if("${WEST_TOPDIR}" STREQUAL "") + set(to_west_topdir FALSE) + else() + cmake_path(IS_PREFIX WEST_TOPDIR ${dir} NORMALIZE to_west_topdir) + endif() + cmake_path(IS_PREFIX APPLICATION_SOURCE_DIR ${dir} NORMALIZE to_app_srcdir) + + # Overall idea is to place included files in the destination dir based on the source: + # files coming from build/zephyr/generated will end up at + # /include/zephyr/include/generated, files coming from zephyr base at + # /include/zephyr/include, files from west top dir (for instance, hal modules), + # at /include and application ones at /include/. + # Finally, everything else (such as external libs not at any of those places) will end up + # at /include/, so we avoid any external lib + # stepping at any other lib toes. + if(to_prj_bindir) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/zephyr/${dir_tmp}) + elseif(to_zephyr_base) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${ZEPHYR_BASE} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/zephyr/${dir_tmp}) + elseif(to_west_topdir) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${WEST_TOPDIR} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/${dir_tmp}) + elseif(to_app_srcdir) + cmake_path(GET APPLICATION_SOURCE_DIR FILENAME app_dir) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${APPLICATION_SOURCE_DIR} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/${app_dir}/${dir_tmp}) + else() + set(dest ${llext_edk_inc}/${dir}) + endif() + + # Use destination parent, as the last part of the source directory is copied as well + cmake_path(GET dest PARENT_PATH dest_p) + + file(MAKE_DIRECTORY ${dest_p}) + file(COPY ${dir} DESTINATION ${dest_p} FILES_MATCHING PATTERN "*.h") + + cmake_path(RELATIVE_PATH dest BASE_DIRECTORY ${llext_edk} OUTPUT_VARIABLE dest_rel) + list(APPEND all_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND all_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") +endforeach() + +list(JOIN all_flags_make " " all_flags_str) +file(WRITE ${llext_edk}/Makefile.cflags "LLEXT_CFLAGS = ${all_flags_str}") + +file(WRITE ${llext_edk}/cmake.cflags "set(LLEXT_CFLAGS ${all_flags_cmake})") + +file(ARCHIVE_CREATE + OUTPUT ${llext_edk_file} + PATHS ${llext_edk} + FORMAT gnutar + COMPRESSION XZ +) + +file(REMOVE_RECURSE ${llext_edk}) diff --git a/cmake/usage/usage.cmake b/cmake/usage/usage.cmake index 2f4b0b76ddd3b2..8ff24025954a12 100644 --- a/cmake/usage/usage.cmake +++ b/cmake/usage/usage.cmake @@ -31,6 +31,7 @@ message(" initlevels - Display the initialization sequence") message(" boards - Display supported boards") message(" shields - Display supported shields") message(" usage - Display this text") +message(" llext-edk - Build the Linkable Loadable Extension (LLEXT) Extension Development Kit (EDK)") message(" help - Display all build system targets") message("") message("Build flags:") diff --git a/subsys/llext/Kconfig b/subsys/llext/Kconfig index 085ef775569591..792ce4b2da5cdb 100644 --- a/subsys/llext/Kconfig +++ b/subsys/llext/Kconfig @@ -71,3 +71,16 @@ module-str = llext source "subsys/logging/Kconfig.template.log_config" endif + +menu "Linkable loadable Extension Development Kit (EDK)" + +config LLEXT_EDK_NAME + string "Name for llext EDK (Extension Development Kit)" + default "llext-edk" + help + Name will be used when generating the EDK file, as .tar.xz. + It will also be used, normalized, as the prefix for the variable + stating EDK location, used on generated Makefile.cflags. For + instance, the default name, "llext-edk", becomes LLEXT_EDK_INSTALL_DIR. + +endmenu From 618048c7c8fdb856eb2c376f6afaafb87a5a128b Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0906/1389] subsys/llext: Generate syscalls stubs for EDK exclusively for userspace A new Kconfig option which generates syscall stubs assuming that extensions will always run on userspace, thus simplifying linking them, as there's no need for z_impl_ stubs (used for direct syscalls), CONFIG_LLEXT_EDK_USERSPACE_ONLY. While defining __ZEPHYR_USER__ could have the same effect for optmised builds, people building extensions on debug environments - thus non-optimised - would suffer, as they'd need to somehow make the stubs available (by either exporting the symbol or implementing dummy stubs). Signed-off-by: Ederson de Souza --- CMakeLists.txt | 15 +++++++++++ cmake/llext-edk.cmake | 9 +++++++ scripts/build/gen_syscalls.py | 49 +++++++++++++++++++++-------------- subsys/llext/Kconfig | 8 ++++++ 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22b60009baca09..e1d88a2fca409b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -623,6 +623,7 @@ get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBR zephyr_link_libraries(${LIBC_LINK_LIBRARIES}) set(syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) +set(edk_syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/edk/include/generated/syscall_list.h) set(syscalls_json ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls.json) set(struct_tags_json ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/struct_tags.json) @@ -2065,6 +2066,19 @@ endif() set(llext_edk_file ${PROJECT_BINARY_DIR}/${CONFIG_LLEXT_EDK_NAME}.tar.xz) add_custom_command( OUTPUT ${llext_edk_file} + # Regenerate syscalls in case CONFIG_LLEXT_EDK_USERSPACE_ONLY + COMMAND ${CMAKE_COMMAND} + -E make_directory edk/include/generated + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py + --json-file ${syscalls_json} # Read this file + --base-output edk/include/generated/syscalls # Write to this dir + --syscall-dispatch edk/include/generated/syscall_dispatch.c # Write this file + --syscall-list ${edk_syscall_list_h} + $<$:--userspace-only> + ${SYSCALL_LONG_REGISTERS_ARG} + ${SYSCALL_SPLIT_TIMEOUT_ARG} COMMAND ${CMAKE_COMMAND} -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} -DAPPLICATION_SOURCE_DIR=${APPLICATION_SOURCE_DIR} @@ -2075,6 +2089,7 @@ add_custom_command( -Dllext_edk_name=${CONFIG_LLEXT_EDK_NAME} -DWEST_TOPDIR=${WEST_TOPDIR} -DZEPHYR_BASE=${ZEPHYR_BASE} + -DCONFIG_LLEXT_EDK_USERSPACE_ONLY=${CONFIG_LLEXT_EDK_USERSPACE_ONLY} -P ${ZEPHYR_BASE}/cmake/llext-edk.cmake DEPENDS ${logical_target_for_zephyr_elf} COMMAND_EXPAND_LISTS diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake index 7c8cf4201f546e..dce42e32090d67 100644 --- a/cmake/llext-edk.cmake +++ b/cmake/llext-edk.cmake @@ -24,6 +24,10 @@ # - WEST_TOPDIR: Path to the west top directory. # - APPLICATION_SOURCE_DIR: Path to the application source directory. # - PROJECT_BINARY_DIR: Path to the project binary build directory. +# - CONFIG_LLEXT_EDK_USERSPACE_ONLY: Whether to copy syscall headers from the +# edk directory. This is necessary when building an extension that only +# supports userspace, as the syscall headers are regenerated in the edk +# directory. cmake_minimum_required(VERSION 3.20.0) @@ -94,6 +98,11 @@ foreach(dir ${include_dirs}) list(APPEND all_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") endforeach() +if(CONFIG_LLEXT_EDK_USERSPACE_ONLY) + # Copy syscall headers from edk directory, as they were regenerated there. + file(COPY ${PROJECT_BINARY_DIR}/edk/include/generated/ DESTINATION ${LLEXT_EDK_INC}/zephyr/include/generated) +endif() + list(JOIN all_flags_make " " all_flags_str) file(WRITE ${llext_edk}/Makefile.cflags "LLEXT_CFLAGS = ${all_flags_str}") diff --git a/scripts/build/gen_syscalls.py b/scripts/build/gen_syscalls.py index 8755f3c649aacc..b6e332d45caef3 100755 --- a/scripts/build/gen_syscalls.py +++ b/scripts/build/gen_syscalls.py @@ -205,21 +205,27 @@ def union_decl(type, split): middle = "struct { uintptr_t lo, hi; } split" if split else "uintptr_t x" return "union { %s; %s val; }" % (middle, type) -def wrapper_defs(func_name, func_type, args, fn): +def wrapper_defs(func_name, func_type, args, fn, userspace_only): ret64 = need_split(func_type) mrsh_args = [] # List of rvalue expressions for the marshalled invocation decl_arglist = ", ".join([" ".join(argrec) for argrec in args]) or "void" syscall_id = "K_SYSCALL_" + func_name.upper() - wrap = "extern %s z_impl_%s(%s);\n" % (func_type, func_name, decl_arglist) - wrap += "\n" + wrap = '' + if not userspace_only: + wrap += "extern %s z_impl_%s(%s);\n" % (func_type, func_name, decl_arglist) + wrap += "\n" + wrap += "__pinned_func\n" wrap += "static inline %s %s(%s)\n" % (func_type, func_name, decl_arglist) wrap += "{\n" - wrap += "#ifdef CONFIG_USERSPACE\n" + if not userspace_only: + wrap += "#ifdef CONFIG_USERSPACE\n" + wrap += ("\t" + "uint64_t ret64;\n") if ret64 else "" - wrap += "\t" + "if (z_syscall_trap()) {\n" + if not userspace_only: + wrap += "\t" + "if (z_syscall_trap()) {\n" valist_args = [] for argnum, (argtype, argname) in enumerate(args): @@ -267,18 +273,19 @@ def wrapper_defs(func_name, func_type, args, fn): for argname in valist_args: wrap += "\t\t" + "va_end(%s);\n" % argname wrap += retcode - wrap += "\t" + "}\n" - wrap += "#endif\n" - - # Otherwise fall through to direct invocation of the impl func. - # Note the compiler barrier: that is required to prevent code from - # the impl call from being hoisted above the check for user - # context. - impl_arglist = ", ".join([argrec[1] for argrec in args]) - impl_call = "z_impl_%s(%s)" % (func_name, impl_arglist) - wrap += "\t" + "compiler_barrier();\n" - wrap += "\t" + "%s%s;\n" % ("return " if func_type != "void" else "", - impl_call) + if not userspace_only: + wrap += "\t" + "}\n" + wrap += "#endif\n" + + # Otherwise fall through to direct invocation of the impl func. + # Note the compiler barrier: that is required to prevent code from + # the impl call from being hoisted above the check for user + # context. + impl_arglist = ", ".join([argrec[1] for argrec in args]) + impl_call = "z_impl_%s(%s)" % (func_name, impl_arglist) + wrap += "\t" + "compiler_barrier();\n" + wrap += "\t" + "%s%s;\n" % ("return " if func_type != "void" else "", + impl_call) wrap += "}\n" @@ -377,7 +384,7 @@ def marshall_defs(func_name, func_type, args): return mrsh, mrsh_name -def analyze_fn(match_group, fn): +def analyze_fn(match_group, fn, userspace_only): func, args = match_group try: @@ -395,7 +402,7 @@ def analyze_fn(match_group, fn): marshaller = None marshaller, handler = marshall_defs(func_name, func_type, args) - invocation = wrapper_defs(func_name, func_type, args, fn) + invocation = wrapper_defs(func_name, func_type, args, fn, userspace_only) # Entry in _k_syscall_table table_entry = "[%s] = %s" % (sys_id, handler) @@ -424,6 +431,8 @@ def parse_args(): help="Generate marshalling files (*_mrsh.c)") parser.add_argument("-e", "--syscall-export-llext", help="output C system call export for extensions") + parser.add_argument("-u", "--userspace-only", action="store_true", + help="Only generate the userpace path of wrappers") args = parser.parse_args() @@ -448,7 +457,7 @@ def main(): exported = [] for match_group, fn, to_emit in syscalls: - handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn) + handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn, args.userspace_only) if fn not in invocations: invocations[fn] = [] diff --git a/subsys/llext/Kconfig b/subsys/llext/Kconfig index 792ce4b2da5cdb..c0dc5e5e881f9c 100644 --- a/subsys/llext/Kconfig +++ b/subsys/llext/Kconfig @@ -83,4 +83,12 @@ config LLEXT_EDK_NAME stating EDK location, used on generated Makefile.cflags. For instance, the default name, "llext-edk", becomes LLEXT_EDK_INSTALL_DIR. +config LLEXT_EDK_USERSPACE_ONLY + bool "Only generate the Userpace codepath on syscall stubs for the EDK" + help + Syscall stubs can contain code that verifies if running code is at user + or kernel space and route the call accordingly. If the EDK is expected + to be used by userspace only extensions, this option will make EDK stubs + not contain the routing code, and only generate the userspace one. + endmenu From 8bc61945d609b5bf94da3cbbf42d19c72fe7ed9e Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0907/1389] cmake/llext-edk: Generate more granular CFLAGS Besides the LLEXT_CFLAGS, which have all that is needed to compile, generate more granular ones, LLEXT_INCLUDE_CFLAGS, LLEXT_ALL_INCLUDE_CFLAGS, LLEXT_GENERATED_INCLUDE_CFLAGS and LLEXT_BASE_CFLAGS. These are done for convenience, as they can help on different setups, such as unit testing. Signed-off-by: Ederson de Souza --- cmake/llext-edk.cmake | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake index dce42e32090d67..2136e7f3fba2cf 100644 --- a/cmake/llext-edk.cmake +++ b/cmake/llext-edk.cmake @@ -43,9 +43,9 @@ cmake_path(CONVERT "${INTERFACE_INCLUDE_DIRECTORIES}" TO_CMAKE_PATH_LIST include set(autoconf_h_edk ${llext_edk_inc}/${AUTOCONF_H}) cmake_path(RELATIVE_PATH AUTOCONF_H BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE autoconf_h_rel) -list(APPEND all_flags_make +list(APPEND base_flags_make "${LLEXT_CFLAGS} -imacros\$(${install_dir_var})/include/zephyr/${autoconf_h_rel}") -list(APPEND all_flags_cmake +list(APPEND base_flags_cmake "${LLEXT_CFLAGS} -imacros\${CMAKE_CURRENT_LIST_DIR}/include/zephyr/${autoconf_h_rel}") file(MAKE_DIRECTORY ${llext_edk_inc}) @@ -94,8 +94,15 @@ foreach(dir ${include_dirs}) file(COPY ${dir} DESTINATION ${dest_p} FILES_MATCHING PATTERN "*.h") cmake_path(RELATIVE_PATH dest BASE_DIRECTORY ${llext_edk} OUTPUT_VARIABLE dest_rel) - list(APPEND all_flags_make "-I\$(${install_dir_var})/${dest_rel}") - list(APPEND all_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") + if(to_prj_bindir) + list(APPEND inc_gen_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND inc_gen_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") + else(to_zephyr_base) + list(APPEND inc_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND inc_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") + endif() + list(APPEND all_inc_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND all_inc_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") endforeach() if(CONFIG_LLEXT_EDK_USERSPACE_ONLY) @@ -103,11 +110,36 @@ if(CONFIG_LLEXT_EDK_USERSPACE_ONLY) file(COPY ${PROJECT_BINARY_DIR}/edk/include/generated/ DESTINATION ${LLEXT_EDK_INC}/zephyr/include/generated) endif() +# Generate flags for Makefile +list(APPEND all_flags_make ${base_flags_make} ${all_inc_flags_make}) list(JOIN all_flags_make " " all_flags_str) file(WRITE ${llext_edk}/Makefile.cflags "LLEXT_CFLAGS = ${all_flags_str}") +list(JOIN all_inc_flags_make " " all_inc_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_ALL_INCLUDE_CFLAGS = ${all_inc_flags_str}") + +list(JOIN inc_flags_make " " inc_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_INCLUDE_CFLAGS = ${inc_flags_str}") + +list(JOIN inc_gen_flags_make " " inc_gen_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_GENERATED_INCLUDE_CFLAGS = ${inc_gen_flags_str}") + +list(JOIN base_flags_make " " base_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_BASE_CFLAGS = ${base_flags_str}") + +# Generate flags for CMake +list(APPEND all_flags_cmake ${base_flags_cmake} ${all_inc_flags_cmake}) file(WRITE ${llext_edk}/cmake.cflags "set(LLEXT_CFLAGS ${all_flags_cmake})") +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_ALL_INCLUDE_CFLAGS ${all_inc_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_INCLUDE_CFLAGS ${inc_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_GENERATED_INCLUDE_CFLAGS ${inc_gen_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_BASE_CFLAGS ${base_flags_cmake})") + +# Generate the tarball file(ARCHIVE_CREATE OUTPUT ${llext_edk_file} PATHS ${llext_edk} From 4f996a7f9e7b7cc9baa97b33f9c31f72e99c00c6 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0908/1389] cmake/modules: Extract flags filtering code to a function This way they can be reused by the LLEXT EDK. Signed-off-by: Ederson de Souza --- cmake/modules/extensions.cmake | 50 ++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 924417286ce3d4..158321bf4a3f7a 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -37,6 +37,7 @@ include(CheckCXXCompilerFlag) # 7 Linkable loadable extensions (llext) # 7.1 llext_* configuration functions # 7.2 add_llext_* build control functions +# 7.3 llext helper functions ######################################################## # 1. Zephyr-aware extensions @@ -5320,24 +5321,11 @@ function(add_llext_target target_name) set(llext_pkg_output ${LLEXT_OUTPUT}) set(source_files ${LLEXT_SOURCES}) - # Convert the LLEXT_REMOVE_FLAGS list to a regular expression, and use it to - # filter out these flags from the Zephyr target settings - list(TRANSFORM LLEXT_REMOVE_FLAGS - REPLACE "(.+)" "^\\1$" - OUTPUT_VARIABLE llext_remove_flags_regexp - ) - list(JOIN llext_remove_flags_regexp "|" llext_remove_flags_regexp) - if ("${llext_remove_flags_regexp}" STREQUAL "") - # an empty regexp would match anything, we actually need the opposite - # so set it to match empty strings - set(llext_remove_flags_regexp "^$") - endif() set(zephyr_flags "$" ) - set(zephyr_filtered_flags - "$" - ) + llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS ${zephyr_flags} + zephyr_filtered_flags) # Compile the source file using current Zephyr settings but a different # set of flags to obtain the desired llext object type. @@ -5557,3 +5545,35 @@ function(add_llext_command) COMMAND_EXPAND_LISTS ) endfunction() + +# 7.3 llext helper functions + +# Usage: +# llext_filter_zephyr_flags( ) +# +# Filter out flags from a list of flags. The filter is a list of regular +# expressions that will be used to exclude flags from the input list. +# +# The resulting generator expression will be stored in the variable . +# +# Example: +# llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS zephyr_flags zephyr_filtered_flags) +# +function(llext_filter_zephyr_flags filter flags outvar) + list(TRANSFORM ${filter} + REPLACE "(.+)" "^\\1$" + OUTPUT_VARIABLE llext_remove_flags_regexp + ) + list(JOIN llext_remove_flags_regexp "|" llext_remove_flags_regexp) + if ("${llext_remove_flags_regexp}" STREQUAL "") + # an empty regexp would match anything, we actually need the opposite + # so set it to match empty strings + set(llext_remove_flags_regexp "^$") + endif() + + set(zephyr_filtered_flags + "$" + ) + + set(${outvar} ${zephyr_filtered_flags} PARENT_SCOPE) +endfunction() From 50566ca115020b3d52fb9ea9eb5f13fb33afec9c Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0909/1389] cmake: Reuse llext flags for EDK Some flags are common between in tree extensions and out of tree supported by the EDK. Instead of duplicating those flags, the EDK reuses the llext ones. However, as the EDK has its own needs, two new lists, `LLEXT_EDK_APPEND_FLAGS` and `LLEXT_EDK_REMOVE_FLAGS` are defined to allow EDK to append or remove flags as needed. Signed-off-by: Ederson de Souza --- CMakeLists.txt | 13 ++++++++++++- cmake/compiler/gcc/target_arm.cmake | 11 +++++++---- cmake/llext-edk.cmake | 6 +++--- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1d88a2fca409b..401060f989cce7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2064,6 +2064,17 @@ endif() # Extension Development Kit (EDK) generation. set(llext_edk_file ${PROJECT_BINARY_DIR}/${CONFIG_LLEXT_EDK_NAME}.tar.xz) + +# TODO maybe generate flags for C CXX ASM +zephyr_get_compile_options_for_lang(C zephyr_flags) + +# Filter out non LLEXT and LLEXT_EDK flags - and add required ones +llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS ${zephyr_flags} llext_edk_cflags) +llext_filter_zephyr_flags(LLEXT_EDK_REMOVE_FLAGS ${llext_edk_cflags} llext_edk_cflags) + +list(APPEND llext_edk_cflags ${LLEXT_APPEND_FLAGS}) +list(APPEND llext_edk_cflags ${LLEXT_EDK_APPEND_FLAGS}) + add_custom_command( OUTPUT ${llext_edk_file} # Regenerate syscalls in case CONFIG_LLEXT_EDK_USERSPACE_ONLY @@ -2085,7 +2096,7 @@ add_custom_command( -DINTERFACE_INCLUDE_DIRECTORIES="$,:>" -Dllext_edk_file=${llext_edk_file} -DAUTOCONF_H=${AUTOCONF_H} - -DLLEXT_CFLAGS="${LLEXT_CFLAGS}" + -Dllext_cflags="${llext_edk_cflags}" -Dllext_edk_name=${CONFIG_LLEXT_EDK_NAME} -DWEST_TOPDIR=${WEST_TOPDIR} -DZEPHYR_BASE=${ZEPHYR_BASE} diff --git a/cmake/compiler/gcc/target_arm.cmake b/cmake/compiler/gcc/target_arm.cmake index 7675e7cb6d51c4..78e5fc94550347 100644 --- a/cmake/compiler/gcc/target_arm.cmake +++ b/cmake/compiler/gcc/target_arm.cmake @@ -59,8 +59,11 @@ set(LLEXT_APPEND_FLAGS -mthumb ) -set(LLEXT_CFLAGS - -mlong-calls - -mthumb +list(APPEND LLEXT_EDK_REMOVE_FLAGS + --sysroot=.* + -fmacro-prefix-map=.* + ) + +list(APPEND LLEXT_EDK_APPEND_FLAGS -nodefaultlibs - -c) + ) diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake index 2136e7f3fba2cf..c62aec4b030051 100644 --- a/cmake/llext-edk.cmake +++ b/cmake/llext-edk.cmake @@ -19,7 +19,7 @@ # zephyr_interface target. # - AUTOCONF_H: Name of the autoconf.h file, used to generate the imacros flag. # - llext_edk_file: Output file name for the tarball. -# - LLEXT_CFLAGS: Additional flags to be added to the generated flags. +# - llext_cflags: Additional flags to be added to the generated flags. # - ZEPHYR_BASE: Path to the zephyr base directory. # - WEST_TOPDIR: Path to the west top directory. # - APPLICATION_SOURCE_DIR: Path to the application source directory. @@ -44,9 +44,9 @@ set(autoconf_h_edk ${llext_edk_inc}/${AUTOCONF_H}) cmake_path(RELATIVE_PATH AUTOCONF_H BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE autoconf_h_rel) list(APPEND base_flags_make - "${LLEXT_CFLAGS} -imacros\$(${install_dir_var})/include/zephyr/${autoconf_h_rel}") + "${llext_cflags} -imacros\$(${install_dir_var})/include/zephyr/${autoconf_h_rel}") list(APPEND base_flags_cmake - "${LLEXT_CFLAGS} -imacros\${CMAKE_CURRENT_LIST_DIR}/include/zephyr/${autoconf_h_rel}") + "${llext_cflags} -imacros\${CMAKE_CURRENT_LIST_DIR}/include/zephyr/${autoconf_h_rel}") file(MAKE_DIRECTORY ${llext_edk_inc}) foreach(dir ${include_dirs}) From 9b8ebebb0239efad0921fee79673700bc06e5039 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0910/1389] cmake: Handle `imacros` from flags Instead of hardcoding `autoconf.h` imacro, get the list of imacros from the llext flags. As those come in the form of absolute paths, they also need to be massaged to point from the EDK directory without revealing host complete paths. Also, the EDK now keeps the imacros on a different flag, `LLEXT_GENERATED_IMACROS_CFLAGS`, to keep it similar to other generated includes. Signed-off-by: Ederson de Souza --- cmake/llext-edk.cmake | 95 ++++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 24 deletions(-) diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake index c62aec4b030051..9501133f3ab382 100644 --- a/cmake/llext-edk.cmake +++ b/cmake/llext-edk.cmake @@ -34,25 +34,15 @@ cmake_minimum_required(VERSION 3.20.0) set(llext_edk ${PROJECT_BINARY_DIR}/${llext_edk_name}) set(llext_edk_inc ${llext_edk}/include) -string(REGEX REPLACE "[^a-zA-Z0-9]" "_" llext_edk_name_sane ${llext_edk_name}) -string(TOUPPER ${llext_edk_name_sane} llext_edk_name_sane) -set(install_dir_var "${llext_edk_name_sane}_INSTALL_DIR") - -cmake_path(CONVERT "${INTERFACE_INCLUDE_DIRECTORIES}" TO_CMAKE_PATH_LIST include_dirs) - -set(autoconf_h_edk ${llext_edk_inc}/${AUTOCONF_H}) -cmake_path(RELATIVE_PATH AUTOCONF_H BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE autoconf_h_rel) - -list(APPEND base_flags_make - "${llext_cflags} -imacros\$(${install_dir_var})/include/zephyr/${autoconf_h_rel}") -list(APPEND base_flags_cmake - "${llext_cflags} -imacros\${CMAKE_CURRENT_LIST_DIR}/include/zephyr/${autoconf_h_rel}") - -file(MAKE_DIRECTORY ${llext_edk_inc}) -foreach(dir ${include_dirs}) - if (NOT EXISTS ${dir}) - continue() - endif() +# Usage: +# relative_dir( ) +# +# Helper function to generate relative paths to a few key directories +# (PROJECT_BINARY_DIR, ZEPHYR_BASE, WEST_TOPDIR and APPLICATION_SOURCE_DIR). +# The generated path is relative to the key directory, and the bindir_out +# output variable is set to TRUE if the path is relative to PROJECT_BINARY_DIR. +# +function(relative_dir dir relative_out bindir_out) cmake_path(IS_PREFIX PROJECT_BINARY_DIR ${dir} NORMALIZE to_prj_bindir) cmake_path(IS_PREFIX ZEPHYR_BASE ${dir} NORMALIZE to_zephyr_base) if("${WEST_TOPDIR}" STREQUAL "") @@ -87,6 +77,58 @@ foreach(dir ${include_dirs}) set(dest ${llext_edk_inc}/${dir}) endif() + set(${relative_out} ${dest} PARENT_SCOPE) + if(to_prj_bindir) + set(${bindir_out} TRUE PARENT_SCOPE) + else() + set(${bindir_out} FALSE PARENT_SCOPE) + endif() +endfunction() + +string(REGEX REPLACE "[^a-zA-Z0-9]" "_" llext_edk_name_sane ${llext_edk_name}) +string(TOUPPER ${llext_edk_name_sane} llext_edk_name_sane) +set(install_dir_var "${llext_edk_name_sane}_INSTALL_DIR") + +separate_arguments(LLEXT_CFLAGS NATIVE_COMMAND ${llext_cflags}) + +set(make_relative FALSE) +foreach(flag ${llext_cflags}) + if (flag STREQUAL "-imacros") + set(make_relative TRUE) + elseif (make_relative) + set(make_relative FALSE) + cmake_path(GET flag PARENT_PATH parent) + cmake_path(GET flag FILENAME name) + relative_dir(${parent} dest bindir) + cmake_path(RELATIVE_PATH dest BASE_DIRECTORY ${llext_edk} OUTPUT_VARIABLE dest_rel) + if(bindir) + list(APPEND imacros_gen_make "-imacros\$(${install_dir_var})/${dest_rel}/${name}") + list(APPEND imacros_gen_cmake "-imacros\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}/${name}") + else() + list(APPEND imacros_make "-imacros\$(${install_dir_var})/${dest_rel}/${name}") + list(APPEND imacros_cmake "-imacros\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}/${name}") + endif() + else() + list(APPEND new_cflags ${flag}) + endif() +endforeach() +set(LLEXT_CFLAGS ${new_cflags}) + +cmake_path(CONVERT "${INTERFACE_INCLUDE_DIRECTORIES}" TO_CMAKE_PATH_LIST include_dirs) + +set(autoconf_h_edk ${llext_edk_inc}/${AUTOCONF_H}) +cmake_path(RELATIVE_PATH AUTOCONF_H BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE autoconf_h_rel) + +list(APPEND base_flags_make ${llext_cflags} ${imacros_make}) +list(APPEND base_flags_cmake ${llext_cflags} ${imacros_cmake}) + +file(MAKE_DIRECTORY ${llext_edk_inc}) +foreach(dir ${include_dirs}) + if (NOT EXISTS ${dir}) + continue() + endif() + + relative_dir(${dir} dest bindir) # Use destination parent, as the last part of the source directory is copied as well cmake_path(GET dest PARENT_PATH dest_p) @@ -94,10 +136,10 @@ foreach(dir ${include_dirs}) file(COPY ${dir} DESTINATION ${dest_p} FILES_MATCHING PATTERN "*.h") cmake_path(RELATIVE_PATH dest BASE_DIRECTORY ${llext_edk} OUTPUT_VARIABLE dest_rel) - if(to_prj_bindir) + if(bindir) list(APPEND inc_gen_flags_make "-I\$(${install_dir_var})/${dest_rel}") list(APPEND inc_gen_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") - else(to_zephyr_base) + else() list(APPEND inc_flags_make "-I\$(${install_dir_var})/${dest_rel}") list(APPEND inc_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") endif() @@ -107,11 +149,11 @@ endforeach() if(CONFIG_LLEXT_EDK_USERSPACE_ONLY) # Copy syscall headers from edk directory, as they were regenerated there. - file(COPY ${PROJECT_BINARY_DIR}/edk/include/generated/ DESTINATION ${LLEXT_EDK_INC}/zephyr/include/generated) + file(COPY ${PROJECT_BINARY_DIR}/edk/include/generated/ DESTINATION ${llext_edk_inc}/zephyr/include/generated) endif() # Generate flags for Makefile -list(APPEND all_flags_make ${base_flags_make} ${all_inc_flags_make}) +list(APPEND all_flags_make ${base_flags_make} ${imacros_gen_make} ${all_inc_flags_make}) list(JOIN all_flags_make " " all_flags_str) file(WRITE ${llext_edk}/Makefile.cflags "LLEXT_CFLAGS = ${all_flags_str}") @@ -127,8 +169,11 @@ file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_GENERATED_INCLUDE_CFLAGS = $ list(JOIN base_flags_make " " base_flags_str) file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_BASE_CFLAGS = ${base_flags_str}") +list(JOIN imacros_gen_make " " imacros_gen_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_GENERATED_IMACROS_CFLAGS = ${imacros_gen_str}") + # Generate flags for CMake -list(APPEND all_flags_cmake ${base_flags_cmake} ${all_inc_flags_cmake}) +list(APPEND all_flags_cmake ${base_flags_cmake} ${imacros_gen_make} ${all_inc_flags_cmake}) file(WRITE ${llext_edk}/cmake.cflags "set(LLEXT_CFLAGS ${all_flags_cmake})") file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_ALL_INCLUDE_CFLAGS ${all_inc_flags_cmake})") @@ -139,6 +184,8 @@ file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_GENERATED_INCLUDE_CFLAGS ${ file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_BASE_CFLAGS ${base_flags_cmake})") +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_GENERATED_IMACROS_CFLAGS ${imacros_gen_cmake})") + # Generate the tarball file(ARCHIVE_CREATE OUTPUT ${llext_edk_file} From d8173679ceaf2c3fcc2e582d5f6b1d9842f38351 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0911/1389] tests/misc: Add llext EDK test This test uses pytest to generate an EDK from a simple Zephyr application, and uses this EDK to build a simple extension, to ensure that EDK generation is sane. Signed-off-by: Ederson de Souza --- cmake/compiler/host-gcc/target.cmake | 9 +++ tests/misc/llext-edk/CMakeLists.txt | 9 +++ tests/misc/llext-edk/extension/CMakeLists.txt | 23 +++++++ tests/misc/llext-edk/extension/src/main.c | 17 +++++ tests/misc/llext-edk/include/app_api.h | 22 +++++++ tests/misc/llext-edk/prj.conf | 3 + tests/misc/llext-edk/pytest/test_edk.py | 66 +++++++++++++++++++ tests/misc/llext-edk/src/foo.c | 23 +++++++ tests/misc/llext-edk/src/main.c | 14 ++++ tests/misc/llext-edk/testcase.yaml | 9 +++ 10 files changed, 195 insertions(+) create mode 100644 tests/misc/llext-edk/CMakeLists.txt create mode 100644 tests/misc/llext-edk/extension/CMakeLists.txt create mode 100644 tests/misc/llext-edk/extension/src/main.c create mode 100644 tests/misc/llext-edk/include/app_api.h create mode 100644 tests/misc/llext-edk/prj.conf create mode 100644 tests/misc/llext-edk/pytest/test_edk.py create mode 100644 tests/misc/llext-edk/src/foo.c create mode 100644 tests/misc/llext-edk/src/main.c create mode 100644 tests/misc/llext-edk/testcase.yaml diff --git a/cmake/compiler/host-gcc/target.cmake b/cmake/compiler/host-gcc/target.cmake index 41e36b99a27ab3..9bc1d46505749a 100644 --- a/cmake/compiler/host-gcc/target.cmake +++ b/cmake/compiler/host-gcc/target.cmake @@ -36,3 +36,12 @@ foreach(file_name include/stddef.h) list(APPEND NOSTDINC ${_OUTPUT}) endforeach() + +list(APPEND LLEXT_EDK_REMOVE_FLAGS + --sysroot=.* + -fmacro-prefix-map=.* + ) + +list(APPEND LLEXT_EDK_APPEND_FLAGS + -nodefaultlibs + ) diff --git a/tests/misc/llext-edk/CMakeLists.txt b/tests/misc/llext-edk/CMakeLists.txt new file mode 100644 index 00000000000000..4fee915a57fcf0 --- /dev/null +++ b/tests/misc/llext-edk/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(llext_edk_test LANGUAGES C) + +target_sources(app PRIVATE src/main.c) +zephyr_include_directories(include) +zephyr_include_directories($ENV{ZEPHYR_BASE}/boards/native/common) diff --git a/tests/misc/llext-edk/extension/CMakeLists.txt b/tests/misc/llext-edk/extension/CMakeLists.txt new file mode 100644 index 00000000000000..1b1a9142ee48ae --- /dev/null +++ b/tests/misc/llext-edk/extension/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.20.0) + +project(extension) + +include($ENV{LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-Werror") +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c +) + +add_custom_target(extension ALL DEPENDS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext) diff --git a/tests/misc/llext-edk/extension/src/main.c b/tests/misc/llext-edk/extension/src/main.c new file mode 100644 index 00000000000000..c4843bee333fb5 --- /dev/null +++ b/tests/misc/llext-edk/extension/src/main.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +int start(void) +{ + int bar = 42; + + printk("foo(%d) is %d\n", bar, foo(bar)); + return 0; +} diff --git a/tests/misc/llext-edk/include/app_api.h b/tests/misc/llext-edk/include/app_api.h new file mode 100644 index 00000000000000..5270bca6873593 --- /dev/null +++ b/tests/misc/llext-edk/include/app_api.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _TEST_EDK_H_ +#define _TEST_EDK_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +__syscall int foo(int bar); + +#ifdef __cplusplus +} +#endif + +#include +#endif /* _TEST_EDK_H_ */ diff --git a/tests/misc/llext-edk/prj.conf b/tests/misc/llext-edk/prj.conf new file mode 100644 index 00000000000000..a479f3a569cd6e --- /dev/null +++ b/tests/misc/llext-edk/prj.conf @@ -0,0 +1,3 @@ +CONFIG_APPLICATION_DEFINED_SYSCALL=y +#CONFIG_USERSPACE=y +CONFIG_LLEXT=y diff --git a/tests/misc/llext-edk/pytest/test_edk.py b/tests/misc/llext-edk/pytest/test_edk.py new file mode 100644 index 00000000000000..d85a138d48b177 --- /dev/null +++ b/tests/misc/llext-edk/pytest/test_edk.py @@ -0,0 +1,66 @@ +# Copyright (c) 2024 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +import logging +import os +import shutil +import tempfile + +from pathlib import Path +from subprocess import check_output +from twister_harness import DeviceAdapter + +logger = logging.getLogger(__name__) + +def test_edk(dut: DeviceAdapter): + # Can we build the edk? + command = [ + "west", + "build", + "-t", + "llext-edk", + "--build-dir", + dut.device_config.build_dir, + ] + output = check_output(command, text=True) + logger.info(output) + + # Install the edk to a temporary location + with tempfile.TemporaryDirectory() as tempdir: + # Copy the edk to the temporary directory using python methods + logger.debug(f"Copying llext-edk.tar.xz to {tempdir}") + edk_path = Path(dut.device_config.build_dir) / "zephyr/llext-edk.tar.xz" + shutil.copy(edk_path, tempdir) + + # Extract the edk using tar + logger.debug(f"Extracting llext-edk.tar.xz to {tempdir}") + command = ["tar", "-xf", "llext-edk.tar.xz"] + output = check_output(command, text=True, cwd=tempdir) + logger.info(output) + + # Copy the extension to another temporary directory to test out of tree builds + with tempfile.TemporaryDirectory() as tempdir_extension: + logger.debug(f"Copying extension to {tempdir_extension}") + ext_dir = Path(os.environ["ZEPHYR_BASE"]) / "tests/misc/llext-edk/extension" + shutil.copytree(ext_dir, tempdir_extension, dirs_exist_ok=True) + + # Set the LLEXT_EDK_INSTALL_DIR environment variable so that the extension + # knows where the EDK is installed + edk_dir = Path(tempdir) / "llext-edk" + env = os.environ.copy() + env.update({"LLEXT_EDK_INSTALL_DIR": edk_dir}) + + # Build the extension using the edk + logger.debug(f"Building extension in {tempdir_extension} - cmake") + command = ["cmake", "-B", "build"] + output = check_output(command, text=True, cwd=tempdir_extension, env=env) + logger.info(output) + + logger.debug(f"Building extension in {tempdir_extension} - make") + command = ["make", "-C", "build"] + output = check_output(command, text=True, cwd=tempdir_extension, env=env) + logger.info(output) + + # Check if the extension was built + assert os.path.exists(Path(tempdir_extension) / "build/extension.llext") diff --git a/tests/misc/llext-edk/src/foo.c b/tests/misc/llext-edk/src/foo.c new file mode 100644 index 00000000000000..190dac2bea692a --- /dev/null +++ b/tests/misc/llext-edk/src/foo.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +int z_impl_foo(int bar) +{ + return bar * bar; +} +EXPORT_SYMBOL(z_impl_foo); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_foo(int bar) +{ + /* Nothing to verify */ + return z_impl_foo(bar); +} +#include +#endif diff --git a/tests/misc/llext-edk/src/main.c b/tests/misc/llext-edk/src/main.c new file mode 100644 index 00000000000000..a5e7ab2e1980f8 --- /dev/null +++ b/tests/misc/llext-edk/src/main.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +int main(void) +{ + return 0; +} diff --git a/tests/misc/llext-edk/testcase.yaml b/tests/misc/llext-edk/testcase.yaml new file mode 100644 index 00000000000000..81f7ce0bd567ce --- /dev/null +++ b/tests/misc/llext-edk/testcase.yaml @@ -0,0 +1,9 @@ +tests: + misc.edk.pytest: + harness: pytest + tags: + - pytest + - edk + platform_allow: + - native_sim + toolchain_exclude: llvm From 781e3b2204e22308f334a0a285269dfa3af4bca2 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0912/1389] samples/subsys/llext: EDK sample Shows a simple application which loads extensions and some simple extensions. While everything is inside Zephyr tree, everything can actually be build from different directories (even machines), as long as the EDK is generated from the application and used by the extensions. More information is available at sample's README. This sample is build only for twister, as it requires a few steps to be properly run, namely build the EDK, install it somewhere, build the extensions using the EDK and finally build the application with the extensions. Signed-off-by: Ederson de Souza --- samples/subsys/llext/edk/README.rst | 137 +++++++++++ samples/subsys/llext/edk/app/CMakeLists.txt | 17 ++ .../subsys/llext/edk/app/include/app_api.h | 38 +++ samples/subsys/llext/edk/app/prj.conf | 19 ++ samples/subsys/llext/edk/app/sample.yaml | 12 + samples/subsys/llext/edk/app/src/main.c | 187 +++++++++++++++ samples/subsys/llext/edk/app/src/pubsub.c | 222 ++++++++++++++++++ samples/subsys/llext/edk/ext1/CMakeLists.txt | 35 +++ samples/subsys/llext/edk/ext1/src/main.c | 34 +++ samples/subsys/llext/edk/ext1/toolchain.cmake | 4 + samples/subsys/llext/edk/ext2/CMakeLists.txt | 31 +++ samples/subsys/llext/edk/ext2/src/main.c | 26 ++ samples/subsys/llext/edk/ext2/toolchain.cmake | 4 + samples/subsys/llext/edk/ext3/CMakeLists.txt | 35 +++ samples/subsys/llext/edk/ext3/src/main.c | 65 +++++ samples/subsys/llext/edk/ext3/toolchain.cmake | 4 + .../subsys/llext/edk/k-ext1/CMakeLists.txt | 35 +++ samples/subsys/llext/edk/k-ext1/src/main.c | 64 +++++ .../subsys/llext/edk/k-ext1/toolchain.cmake | 4 + 19 files changed, 973 insertions(+) create mode 100644 samples/subsys/llext/edk/README.rst create mode 100644 samples/subsys/llext/edk/app/CMakeLists.txt create mode 100644 samples/subsys/llext/edk/app/include/app_api.h create mode 100644 samples/subsys/llext/edk/app/prj.conf create mode 100644 samples/subsys/llext/edk/app/sample.yaml create mode 100644 samples/subsys/llext/edk/app/src/main.c create mode 100644 samples/subsys/llext/edk/app/src/pubsub.c create mode 100644 samples/subsys/llext/edk/ext1/CMakeLists.txt create mode 100644 samples/subsys/llext/edk/ext1/src/main.c create mode 100644 samples/subsys/llext/edk/ext1/toolchain.cmake create mode 100644 samples/subsys/llext/edk/ext2/CMakeLists.txt create mode 100644 samples/subsys/llext/edk/ext2/src/main.c create mode 100644 samples/subsys/llext/edk/ext2/toolchain.cmake create mode 100644 samples/subsys/llext/edk/ext3/CMakeLists.txt create mode 100644 samples/subsys/llext/edk/ext3/src/main.c create mode 100644 samples/subsys/llext/edk/ext3/toolchain.cmake create mode 100644 samples/subsys/llext/edk/k-ext1/CMakeLists.txt create mode 100644 samples/subsys/llext/edk/k-ext1/src/main.c create mode 100644 samples/subsys/llext/edk/k-ext1/toolchain.cmake diff --git a/samples/subsys/llext/edk/README.rst b/samples/subsys/llext/edk/README.rst new file mode 100644 index 00000000000000..22e678c314d221 --- /dev/null +++ b/samples/subsys/llext/edk/README.rst @@ -0,0 +1,137 @@ +.. zephyr:code-sample:: llext-edk + :name: Linkable loadable extensions EDK + :relevant-api: llext + + Enable linkable loadable extension development outside the Zephyr tree using + LLEXT EDK (Extension Development Kit). + +Overview +******** + +This sample demonstrates how to use the Zephyr LLEXT EDK (Extension Development +Kit). It is composed of one Zephyr application, which provides APIs for the +extensions that it loads. The provided API is a simple publish/subscribe system, +based on :ref:`Zbus `, which extensions use to communicate with each other. + +The application is composed of a subscriber thread, which listens for events +published and republishes them via Zbus to the extensions that are +subscribers. There are four extensions, which are loaded by the application and +run in different contexts. Extensions ``ext1``, ``ext2`` and ``ext3`` run in +userspace, each demonstrating different application and Zephyr API usage, such as +semaphores, spawning threads to listen for events or simply publishing or +subscribing to events. Extension ``kext1`` runs in a kernel thread, albeit similar +to ``ext3``. + +The application also creates different memory domains for each extension, thus +providing some level of isolation - although the kernel one still has access +to all of Zephyr kernel. + +Note that the kernel extension is only available when the EDK is built with +the :kconfig:option:`CONFIG_LLEXT_EDK_USERSPACE_ONLY` option disabled. + + +The application is built using the Zephyr build system. The EDK is built using +the Zephyr build system as well, via ``llext-edk`` target. The EDK is then +extracted and the extensions are built using CMake. + +Finally, the way the application loads the extensions is by including them +during build time, which is not really practical. This sample is about the EDK +providing the ability to build extensions independently from the application. +One could build the extensions in different directories, not related to the +Zephyr application - even on different machines, using only the EDK. At the +limit, one could even imagine a scenario where the extensions are built by +different teams, using the EDK provided by the application developer. + +Building the EDK +**************** + +To build the EDK, use the ``llext-edk`` target. For example: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/edk/app + :board: qemu_cortex_r5 + :goals: build llext-edk + :west-args: -p=always + :compact: + +Copy the EDK to some place and extract it: + +.. code-block:: console + + mkdir /tmp/edk + cp build/zephyr/llext-edk.tar.xz /tmp/edk + cd /tmp/edk + tar -xf llext-edk.tar.xz + +Then set ``LLEXT_EDK_INSTALL_DIR`` to the extracted directory: + +.. code-block:: console + + export LLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk + +This variable is used by the extensions to find the EDK. + +Building the extensions +*********************** + +The :envvar:`ZEPHYR_SDK_INSTALL_DIR` environment variable is used by the +extensions to find the Zephyr SDK, so you need to ensure it's properly set: + +.. code-block:: console + + export ZEPHYR_SDK_INSTALL_DIR= + +To build the extensions, in the ``ext1``, ``ext2``, ``ext3`` and ``kext1`` +directories: + +.. code-block:: console + + cmake -B build + make -C build + +Alternatively, you can set the ``LLEXT_EDK_INSTALL_DIR`` directly in the +CMake invocation: + +.. code-block:: console + + cmake -B build -DLLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk + make -C build + +Building the application +************************ + +Now, build the application, including the extensions, and run it: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/edk/app + :board: qemu_cortex_r5 + :goals: build run + :west-args: -p=always + :compact: + +You should see something like: + +.. code-block:: console + + [app]Subscriber thread [0x20b28] started. + [app]Loading extension [kext1]. + [app]Thread 0x20840 created to run extension [kext1], at privileged mode. + [k-ext1]Waiting sem + [app]Thread [0x222a0] registered event [0x223c0] + [k-ext1]Waiting event + [app]Loading extension [ext1]. + [app]Thread 0x20a30 created to run extension [ext1], at userspace. + [app]Thread [0x20a30] registered event [0x26060] + [ext1]Waiting event + [app]Loading extension [ext2]. + [app]Thread 0x20938 created to run extension [ext2], at userspace. + [ext2]Publishing tick + [app][subscriber_thread]Got channel tick_chan + [ext1]Got event, reading channel + [ext1]Read val: 0 + [ext1]Waiting event + [k-ext1]Got event, giving sem + [k-ext1]Got sem, reading channel + [k-ext1]Read val: 0 + [k-ext1]Waiting sem + (...) diff --git a/samples/subsys/llext/edk/app/CMakeLists.txt b/samples/subsys/llext/edk/app/CMakeLists.txt new file mode 100644 index 00000000000000..1afc133186e91a --- /dev/null +++ b/samples/subsys/llext/edk/app/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +# It seems llext currently doesn't support some Thumb32 relocation +# instructions generated when building the extensions with default +# flags. As a workaround, we remove these *unrelated* flags from the +# default flags. This allows the extensions to be built without the +# unsupported instructions. +# See issue #72832 for more details. +list(APPEND LLEXT_EDK_REMOVE_FLAGS -mcpu=cortex-r5 -mfloat-abi=hard) + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(app LANGUAGES C) + +target_sources(app PRIVATE src/main.c src/pubsub.c) +zephyr_include_directories(include) diff --git a/samples/subsys/llext/edk/app/include/app_api.h b/samples/subsys/llext/edk/app/include/app_api.h new file mode 100644 index 00000000000000..bc6cb49dca85e0 --- /dev/null +++ b/samples/subsys/llext/edk/app/include/app_api.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _TEST_EDK_H_ +#define _TEST_EDK_H_ +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + enum Channels { + CHAN_TICK = 1, + CHAN_LAST + }; + + struct channel_tick_data { + unsigned long l; + }; + + __syscall int publish(enum Channels channel, void *data, + size_t data_len); + __syscall int receive(enum Channels channel, void *data, + size_t data_len); + __syscall int register_subscriber(enum Channels channel, + struct k_event *evt); +#ifdef __cplusplus +} +#endif + +#include +#endif /* _TEST_EDK_H_ */ diff --git a/samples/subsys/llext/edk/app/prj.conf b/samples/subsys/llext/edk/app/prj.conf new file mode 100644 index 00000000000000..c9c758f6767360 --- /dev/null +++ b/samples/subsys/llext/edk/app/prj.conf @@ -0,0 +1,19 @@ +CONFIG_APPLICATION_DEFINED_SYSCALL=y +CONFIG_USERSPACE=y +CONFIG_LLEXT=y + +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_DYNAMIC_OBJECTS=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_ALLOC=y +CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y +CONFIG_ZBUS=y +CONFIG_ZBUS_CHANNEL_NAME=y + +CONFIG_LLEXT_HEAP_SIZE=32 + +# Uncomment to disable kext1. +#CONFIG_LLEXT_EDK_USERSPACE_ONLY=y + +CONFIG_EVENTS=y diff --git a/samples/subsys/llext/edk/app/sample.yaml b/samples/subsys/llext/edk/app/sample.yaml new file mode 100644 index 00000000000000..1bcfe288e4dd0f --- /dev/null +++ b/samples/subsys/llext/edk/app/sample.yaml @@ -0,0 +1,12 @@ +common: + tags: llext edk + arch_allow: + - arm + filter: CONFIG_ARCH_HAS_USERSPACE +sample: + description: EDK sample application + name: EDK sample application +tests: + sample.edk.app: + build_only: true + tags: edk llext diff --git a/samples/subsys/llext/edk/app/src/main.c b/samples/subsys/llext/edk/app/src/main.c new file mode 100644 index 00000000000000..502901d59bdd0e --- /dev/null +++ b/samples/subsys/llext/edk/app/src/main.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +#include + +/** + * Assume that if the extension 1 is not built, we are building the + * EDK. If others are not built, this will just fail. + */ +#if defined __has_include +# if __has_include("../../ext1/build/ext1.inc") +# undef EDK_BUILD +# else +# pragma message "Extension 1 not built, assuming EDK build." +# define EDK_BUILD +# endif +#endif + +#ifndef EDK_BUILD +#include "../../ext1/build/ext1.inc" +#define ext1_inc ext1_llext +#define ext1_len ext1_llext_len +#include "../../ext2/build/ext2.inc" +#define ext2_inc ext2_llext +#define ext2_len ext2_llext_len +#include "../../ext3/build/ext3.inc" +#define ext3_inc ext3_llext +#define ext3_len ext3_llext_len +#ifndef CONFIG_LLEXT_EDK_USERSPACE_ONLY +#include "../../k-ext1/build/kext1.inc" +#define kext1_inc kext1_llext +#define kext1_len kext1_llext_len +#endif +#endif + +#define USER_STACKSIZE 2048 +#define USER_HEAPSIZE 8192 +#define MAX_EXTENSIONS 4 + +extern k_tid_t start_subscriber_thread(void); + +/* Maybe make all this depend on MAX_EXTENSIONS? */ +struct k_thread user_thread1, user_thread2, user_thread3, kernel_thread1; +K_THREAD_STACK_DEFINE(user_stack1, USER_STACKSIZE); +K_THREAD_STACK_DEFINE(user_stack2, USER_STACKSIZE); +K_THREAD_STACK_DEFINE(user_stack3, USER_STACKSIZE); +K_THREAD_STACK_DEFINE(kernel_stack1, USER_STACKSIZE); + +K_HEAP_DEFINE(user_heap1, USER_HEAPSIZE); +K_HEAP_DEFINE(user_heap2, USER_HEAPSIZE); +K_HEAP_DEFINE(user_heap3, USER_HEAPSIZE); +K_HEAP_DEFINE(kernel_heap1, USER_HEAPSIZE); + +struct { + k_tid_t thread; + struct llext *ext; +} extension_threads[MAX_EXTENSIONS]; +int max_extension_thread_idx; + +static const void * const load(const char *name, struct llext **ext, void *buf, + size_t len) +{ +#ifndef EDK_BUILD + struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(buf, len); + struct llext_loader *loader = &buf_loader.loader; + struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + + llext_load(loader, name, ext, &ldr_parm); + + return llext_find_sym(&(*ext)->exp_tab, "start"); +#else + return NULL; +#endif +} + +static void unload(struct llext **ext) +{ + llext_unload(ext); +} + +static void user_function(void *p1, void *p2, void *p3) +{ + int (*start_fn)(void) = p1; + + printk("[app]Thread %p created to run extension [%s], at %s\n", + k_current_get(), (char *)p2, + k_is_user_context() ? "userspace." : "privileged mode."); + + start_fn(); + printk("[app]Thread %p done\n", k_current_get()); +} + +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +{ + int i; + + printk("[app]Fatal handler! Thread: %p\n", k_current_get()); + + for (i = 0; i < max_extension_thread_idx; i++) { + if (extension_threads[i].thread == k_current_get()) { + unload(&extension_threads[i].ext); + } + } +} + +void run_extension_on_thread(void *ext_inc, size_t ext_len, + struct k_mem_domain *domain, + struct k_thread *thread, + k_thread_stack_t *stack, + struct k_heap *heap, + const char *name, + k_tid_t subscriber_thread_id, + int flag) +{ + int (*start_fn)(void); + struct llext **ext = &extension_threads[max_extension_thread_idx].ext; + + printk("[app]Loading extension [%s].\n", name); + start_fn = load(name, ext, ext_inc, ext_len); + + llext_add_domain(*ext, domain); + + k_thread_create(thread, stack, USER_STACKSIZE, + user_function, start_fn, (void *)name, NULL, + -1, flag | K_INHERIT_PERMS, K_FOREVER); + k_mem_domain_add_thread(domain, thread); + k_mem_domain_add_thread(domain, subscriber_thread_id); + + k_thread_heap_assign(thread, heap); + + extension_threads[max_extension_thread_idx].thread = thread; + max_extension_thread_idx++; + + k_thread_start(thread); +} + +int main(void) +{ + struct k_mem_domain domain1, domain2, domain3, kdomain1; + +#ifndef EDK_BUILD + k_tid_t subscriber_thread_id = start_subscriber_thread(); +#endif + /* This and all other similar sleeps are here to provide a chance for + * the newly created thread to run. + */ + k_sleep(K_MSEC(1)); + + k_mem_domain_init(&domain1, 0, NULL); + k_mem_domain_init(&domain2, 0, NULL); + k_mem_domain_init(&domain3, 0, NULL); + k_mem_domain_init(&kdomain1, 0, NULL); + +#ifndef EDK_BUILD +#ifndef CONFIG_LLEXT_EDK_USERSPACE_ONLY + run_extension_on_thread(kext1_inc, kext1_len, &kdomain1, + &kernel_thread1, kernel_stack1, &kernel_heap1, + "kext1", subscriber_thread_id, 0); + k_sleep(K_MSEC(1)); +#endif + run_extension_on_thread(ext1_inc, ext1_len, &domain1, &user_thread1, + user_stack1, &user_heap1, "ext1", + subscriber_thread_id, K_USER); + k_sleep(K_MSEC(1)); + run_extension_on_thread(ext2_inc, ext2_len, &domain2, &user_thread2, + user_stack2, &user_heap2, "ext2", + subscriber_thread_id, K_USER); + k_sleep(K_MSEC(1)); + run_extension_on_thread(ext3_inc, ext3_len, &domain3, &user_thread3, + user_stack3, &user_heap3, "ext3", + subscriber_thread_id, K_USER); +#endif + + k_sleep(K_FOREVER); + + return 0; +} diff --git a/samples/subsys/llext/edk/app/src/pubsub.c b/samples/subsys/llext/edk/app/src/pubsub.c new file mode 100644 index 00000000000000..fa7641be4616c0 --- /dev/null +++ b/samples/subsys/llext/edk/app/src/pubsub.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include + +#define MAX_SUBSCRIBERS 64 +#define SUBSCRIBER_THREAD_STACK_SIZE 1024 +#define SUBSCRIBER_THREAD_PRIORITY K_PRIO_PREEMPT(1) + +ZBUS_CHAN_DEFINE(tick_chan, + struct channel_tick_data, + NULL, + NULL, + ZBUS_OBSERVERS(default_sub), + ZBUS_MSG_INIT(.l = 0)); + +ZBUS_SUBSCRIBER_DEFINE(default_sub, 4); + +K_THREAD_STACK_DEFINE(subscriber_thread_stack, SUBSCRIBER_THREAD_STACK_SIZE); +static struct k_thread subscriber_thread; + +static struct subs { + struct { + k_tid_t thread; + struct k_event *evt; + } subscribers[MAX_SUBSCRIBERS]; + struct k_mutex subscribers_mtx; + int subscribers_count; + const struct zbus_channel *chan; +} channel_subscribers[] = { + /* Empty one first, so no channel is zero (first item on enum == 1) */ + {{ }}, + { .chan = &tick_chan }, + {{ }} +}; + +static int remove_subscriber(k_tid_t thread, struct subs *sus) +{ + int i; + + for (i = 0; i < sus->subscribers_count; i++) { + if (sus->subscribers[i].thread == thread) { + sus->subscribers[i].thread = NULL; + sus->subscribers[i].evt = NULL; + break; + } + } + + if (i == sus->subscribers_count) { + return -ENOENT; + } + + /* Move all entries after excluded one, to keep things tidy */ + memmove(&sus->subscribers[i], &sus->subscribers[i + 1], + (sus->subscribers_count - i - 1) * + sizeof(sus->subscribers[0])); + sus->subscribers_count--; + + return 0; +} + +static int add_subscriber(k_tid_t thread, struct subs *sus, + struct k_event *evt) +{ + if (sus->subscribers_count >= MAX_SUBSCRIBERS) { + return -ENOMEM; + } + + sus->subscribers[sus->subscribers_count].thread = thread; + sus->subscribers[sus->subscribers_count].evt = evt; + sus->subscribers_count++; + + printk("[app]Thread [%p] registered event [%p]\n", thread, evt); + return 0; +} + +static void notify_subscribers(enum Channels channel) +{ + int i; + struct subs *subs = &channel_subscribers[channel]; + + for (i = 0; i < subs->subscribers_count; i++) { + k_event_post(subs->subscribers[i].evt, channel); + } +} + +static void subscriber_thread_fn(void *p0, void *p1, void *p2) +{ + const struct zbus_channel *chan; + int i; + + printk("[app]Subscriber thread [%p] started.\n", k_current_get()); + while (zbus_sub_wait(&default_sub, &chan, K_FOREVER) == 0) { + printk("[app][subscriber_thread]Got channel %s\n", + zbus_chan_name(chan)); + + for (i = 0; i < CHAN_LAST; i++) { + if (channel_subscribers[i].chan == chan) { + notify_subscribers((enum Channels)i); + break; + } + } + } +} + +k_tid_t start_subscriber_thread(void) +{ + return k_thread_create(&subscriber_thread, subscriber_thread_stack, + SUBSCRIBER_THREAD_STACK_SIZE, + subscriber_thread_fn, NULL, NULL, NULL, + SUBSCRIBER_THREAD_PRIORITY, 0, K_NO_WAIT); +} + +int z_impl_publish(enum Channels channel, void *data, size_t data_len) +{ + const struct zbus_channel *chan = channel_subscribers[channel].chan; + + if (channel == CHAN_LAST) { + return -EINVAL; + } + + return zbus_chan_pub(chan, data, K_NO_WAIT); +} +EXPORT_SYMBOL(z_impl_publish); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_publish(enum Channels channel, void *data, + size_t data_len) +{ + int ret; + void *copy_data; + + copy_data = k_usermode_alloc_from_copy(data, data_len); + if (copy_data == NULL) { + return -EINVAL; + } + + ret = z_impl_publish(channel, copy_data, data_len); + + k_free(copy_data); + + return ret; +} +#include +#endif + +int z_impl_receive(enum Channels channel, void *data, size_t data_len) +{ + size_t msg_size; + + if (channel == CHAN_LAST || data == NULL) { + return -EINVAL; + } + + msg_size = channel_subscribers[channel].chan->message_size; + if (data_len < msg_size) { + return -EINVAL; + } + + return zbus_chan_read(channel_subscribers[channel].chan, data, + K_NO_WAIT); +} +EXPORT_SYMBOL(z_impl_receive); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_receive(enum Channels channel, void *data, + size_t data_len) +{ + if (K_SYSCALL_MEMORY_WRITE(data, data_len)) { + return -EINVAL; + } + + return z_impl_receive(channel, data, data_len); +} +#include +#endif + +int z_impl_register_subscriber(enum Channels channel, struct k_event *evt) +{ + struct subs *subs = &channel_subscribers[channel]; + int ret; + + if (channel == CHAN_LAST) { + return -EINVAL; + } + + k_mutex_lock(&subs->subscribers_mtx, K_FOREVER); + + if (evt == NULL) { + ret = remove_subscriber(k_current_get(), subs); + } else { + ret = add_subscriber(k_current_get(), subs, evt); + } + + k_mutex_unlock(&subs->subscribers_mtx); + + return ret; +} +EXPORT_SYMBOL(z_impl_register_subscriber); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_register_subscriber(enum Channels channel, + struct k_event *evt) +{ + if (K_SYSCALL_OBJ(evt, K_OBJ_EVENT)) { + return -EINVAL; + } + + return z_impl_register_subscriber(channel, evt); +} +#include +#endif diff --git a/samples/subsys/llext/edk/ext1/CMakeLists.txt b/samples/subsys/llext/edk/ext1/CMakeLists.txt new file mode 100644 index 00000000000000..cfb254797655d8 --- /dev/null +++ b/samples/subsys/llext/edk/ext1/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(ext1) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(ext1 ALL DEPENDS ${PROJECT_BINARY_DIR}/ext1.llext) diff --git a/samples/subsys/llext/edk/ext1/src/main.c b/samples/subsys/llext/edk/ext1/src/main.c new file mode 100644 index 00000000000000..d7f9c6aa71b3f5 --- /dev/null +++ b/samples/subsys/llext/edk/ext1/src/main.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +int start(void) +{ + /* Inside extensions, all kobjects need to be dynamically allocated */ + struct k_event *tick_evt = k_object_alloc(K_OBJ_EVENT); + + k_event_init(tick_evt); + + register_subscriber(CHAN_TICK, tick_evt); + + while (true) { + long l; + + printk("[ext1]Waiting event\n"); + k_event_wait(tick_evt, CHAN_TICK, true, K_FOREVER); + + printk("[ext1]Got event, reading channel\n"); + receive(CHAN_TICK, &l, sizeof(l)); + printk("[ext1]Read val: %ld\n", l); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext1/toolchain.cmake b/samples/subsys/llext/edk/ext1/toolchain.cmake new file mode 100644 index 00000000000000..c511cc4a6a067c --- /dev/null +++ b/samples/subsys/llext/edk/ext1/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/edk/ext2/CMakeLists.txt b/samples/subsys/llext/edk/ext2/CMakeLists.txt new file mode 100644 index 00000000000000..70ea00f0b6120b --- /dev/null +++ b/samples/subsys/llext/edk/ext2/CMakeLists.txt @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(ext2) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +set(CMAKE_C_FLAGS ${LLEXT_CFLAGS} "-c") + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(ext2 ALL DEPENDS ${PROJECT_BINARY_DIR}/ext2.llext) diff --git a/samples/subsys/llext/edk/ext2/src/main.c b/samples/subsys/llext/edk/ext2/src/main.c new file mode 100644 index 00000000000000..38a054a5ccb19c --- /dev/null +++ b/samples/subsys/llext/edk/ext2/src/main.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +int start(void) +{ + int i; + + for (i = 0; i < 5; i++) { + struct channel_tick_data ctd = { .l = i }; + + printk("[ext2]Publishing tick\n"); + publish(CHAN_TICK, &ctd, sizeof(ctd)); + k_sleep(K_SECONDS(1)); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext2/toolchain.cmake b/samples/subsys/llext/edk/ext2/toolchain.cmake new file mode 100644 index 00000000000000..c511cc4a6a067c --- /dev/null +++ b/samples/subsys/llext/edk/ext2/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/edk/ext3/CMakeLists.txt b/samples/subsys/llext/edk/ext3/CMakeLists.txt new file mode 100644 index 00000000000000..8f95956a255776 --- /dev/null +++ b/samples/subsys/llext/edk/ext3/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(ext3) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(ext3 ALL DEPENDS ${PROJECT_BINARY_DIR}/ext3.llext) diff --git a/samples/subsys/llext/edk/ext3/src/main.c b/samples/subsys/llext/edk/ext3/src/main.c new file mode 100644 index 00000000000000..19aff8352d967b --- /dev/null +++ b/samples/subsys/llext/edk/ext3/src/main.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define STACKSIZE 512 +#define PRIORITY 2 + +static struct k_sem *my_sem; + +static void tick_sub(void *p1, void *p2, void *p3) +{ + struct k_event *tick_evt = k_object_alloc(K_OBJ_EVENT); + + k_event_init(tick_evt); + + register_subscriber(CHAN_TICK, tick_evt); + + while (true) { + printk("[ext3]Waiting event\n"); + k_event_wait(tick_evt, CHAN_TICK, true, K_FOREVER); + printk("[ext3]Got event, giving sem\n"); + + k_sem_give(my_sem); + } +} + +int start(void) +{ + k_thread_stack_t *sub_stack; + struct k_thread *sub_thread; + + /* Currently, any kobjects need to be dynamic on extensions, + * so the semaphore, thread stack and thread objects are created + * dynamically. + */ + my_sem = k_object_alloc(K_OBJ_SEM); + k_sem_init(my_sem, 0, 1); + + sub_stack = k_thread_stack_alloc(STACKSIZE, K_USER); + sub_thread = k_object_alloc(K_OBJ_THREAD); + printk("[ext3]%p - %p\n", sub_stack, sub_thread); + k_thread_create(sub_thread, sub_stack, STACKSIZE, tick_sub, NULL, NULL, + NULL, PRIORITY, K_INHERIT_PERMS | K_USER, K_NO_WAIT); + + while (true) { + long l; + + printk("[ext3]Waiting sem\n"); + k_sem_take(my_sem, K_FOREVER); + + printk("[ext3]Got sem, reading channel\n"); + receive(CHAN_TICK, &l, sizeof(l)); + printk("[ext3]Read val: %ld\n", l); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext3/toolchain.cmake b/samples/subsys/llext/edk/ext3/toolchain.cmake new file mode 100644 index 00000000000000..c511cc4a6a067c --- /dev/null +++ b/samples/subsys/llext/edk/ext3/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/edk/k-ext1/CMakeLists.txt b/samples/subsys/llext/edk/k-ext1/CMakeLists.txt new file mode 100644 index 00000000000000..b1f4aae47e84d2 --- /dev/null +++ b/samples/subsys/llext/edk/k-ext1/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(kext1) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(kext1 ALL DEPENDS ${PROJECT_BINARY_DIR}/kext1.llext) diff --git a/samples/subsys/llext/edk/k-ext1/src/main.c b/samples/subsys/llext/edk/k-ext1/src/main.c new file mode 100644 index 00000000000000..34dedc63728207 --- /dev/null +++ b/samples/subsys/llext/edk/k-ext1/src/main.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define STACKSIZE 512 +#define PRIORITY 2 + +static struct k_sem *my_sem; + +static void tick_sub(void *p1, void *p2, void *p3) +{ + struct k_event *tick_evt = k_object_alloc(K_OBJ_EVENT); + + k_event_init(tick_evt); + + register_subscriber(CHAN_TICK, tick_evt); + + while (true) { + printk("[k-ext1]Waiting event\n"); + k_event_wait(tick_evt, CHAN_TICK, true, K_FOREVER); + printk("[k-ext1]Got event, giving sem\n"); + + k_sem_give(my_sem); + } +} + +int start(void) +{ + k_thread_stack_t *sub_stack; + struct k_thread *sub_thread; + + /* Currently, any kobjects need to be dynamic on extensions, + * so the semaphore, thread stack and thread objects are created + * dynamically. + */ + my_sem = k_object_alloc(K_OBJ_SEM); + k_sem_init(my_sem, 0, 1); + + sub_stack = k_thread_stack_alloc(STACKSIZE, 0); + sub_thread = k_object_alloc(K_OBJ_THREAD); + k_thread_create(sub_thread, sub_stack, STACKSIZE, tick_sub, NULL, NULL, + NULL, PRIORITY, K_INHERIT_PERMS, K_NO_WAIT); + + while (true) { + long l; + + printk("[k-ext1]Waiting sem\n"); + k_sem_take(my_sem, K_FOREVER); + + printk("[k-ext1]Got sem, reading channel\n"); + receive(CHAN_TICK, &l, sizeof(l)); + printk("[k-ext1]Read val: %ld\n", l); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/k-ext1/toolchain.cmake b/samples/subsys/llext/edk/k-ext1/toolchain.cmake new file mode 100644 index 00000000000000..c511cc4a6a067c --- /dev/null +++ b/samples/subsys/llext/edk/k-ext1/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) From bcba125d63a94bb7e588204d07f7810ce09a24eb Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0913/1389] ARC: hsdk_2cores: fix broken defconfig After recent HWv2 model changes there is defconfig file broken, so we got incorrect platform configuration. Fix that. Signed-off-by: Eugeniy Paltsev Signed-off-by: Evgeniy Paltsev --- boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig b/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig index 711d759a8fd78d..bc0a91f60beca8 100644 --- a/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig +++ b/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig @@ -9,7 +9,6 @@ CONFIG_ARCV2_TIMER=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_ARC_MPU_ENABLE=y CONFIG_GPIO=y +CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 From 86a441f83c0600a5b12314c005fe3e3326927b4f Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0914/1389] manifest: Update hal_microchip for new MEC5 HAL Microchip external HAL repository has been updated with the MEC5 HAL for new chips. MEC5 is a full HAL with chip headers, C peripheral code, and PINCTRL DTSI files. MEC5 is meant for MEC174x, MEC175x, and also include support for the older MEC172x named as MECH172x. NOTE: legacy MEC172x in the currest zephyr tree is not affected. Signed-off-by: Scott Worley --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 091f6ac35a47b0..11cc8064bb0b74 100644 --- a/west.yml +++ b/west.yml @@ -178,7 +178,7 @@ manifest: groups: - hal - name: hal_microchip - revision: 68575aa28cd33c68b3b8d66f510d15746c57fdb5 + revision: 1279561ea9b71c5f572d3d52708b7b445a383662 path: modules/hal/microchip groups: - hal From bb786b2db109c1cac43c0b29cf093d83fb5acbfa Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0915/1389] usb: device_next: add few more string descriptor helpers Add function to get string descriptor index and function to remove linked descriptor from a device. This abstracts it a bit so that the user does not need to know how it is handled internally. Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 18 ++++++++++++++++++ subsys/usb/device_next/class/usbd_cdc_ecm.c | 2 +- subsys/usb/device_next/usbd_desc.c | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 1797b54f6dc2fa..340cdf9f82be07 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -552,6 +552,24 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c int usbd_add_descriptor(struct usbd_contex *uds_ctx, struct usbd_desc_node *dn); +/** + * @brief Get USB string descriptor index from descriptor node + * + * @param[in] desc_nd Pointer to USB descriptor node + * + * @return Descriptor index, 0 if descriptor is not part of any device + */ +uint8_t usbd_str_desc_get_idx(const struct usbd_desc_node *const desc_nd); + +/** + * @brief Remove USB string descriptor + * + * Remove linked USB string descriptor from any list. + * + * @param[in] desc_nd Pointer to USB descriptor node + */ +void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd); + /** * @brief Add a USB device configuration * diff --git a/subsys/usb/device_next/class/usbd_cdc_ecm.c b/subsys/usb/device_next/class/usbd_cdc_ecm.c index 7cbbc8d433e578..7b3305bf343851 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ecm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ecm.c @@ -457,7 +457,7 @@ static int usbd_cdc_ecm_init(struct usbd_class_data *const c_data) if (usbd_add_descriptor(uds_ctx, data->mac_desc_data)) { LOG_ERR("Failed to add iMACAddress string descriptor"); } else { - desc->if0_ecm.iMACAddress = data->mac_desc_data->idx; + desc->if0_ecm.iMACAddress = usbd_str_desc_get_idx(data->mac_desc_data); } return 0; diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index b5d086d5424633..1d91c188d42ccc 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -268,3 +268,20 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, usbd_device_unlock(uds_ctx); return ret; } + +uint8_t usbd_str_desc_get_idx(const struct usbd_desc_node *const desc_nd) +{ + if (sys_dnode_is_linked(&desc_nd->node)) { + return desc_nd->idx; + } + + return 0; +} + +void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd) +{ + if (sys_dnode_is_linked(&desc_nd->node)) { + sys_dlist_remove(&desc_nd->node); + desc_nd->idx = 0; + } +} From a177177f78bca135c2f92bd51da2c446551fa0aa Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0916/1389] usb: device_next: convert ASCII7 strings to UTF16LE on the fly This is slower but should have no real effect. In the future we can support more than ASCII7 format and store it in other memory areas. Signed-off-by: Johann Fischer --- subsys/usb/device_next/usbd_ch9.c | 88 ++++++++++++++++++++++-------- subsys/usb/device_next/usbd_desc.c | 58 +------------------- subsys/usb/device_next/usbd_desc.h | 10 ++-- 3 files changed, 74 insertions(+), 82 deletions(-) diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 755950cc6519fd..da80e778533af4 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -523,41 +523,85 @@ static int sreq_get_desc_cfg(struct usbd_contex *const uds_ctx, return 0; } -static int sreq_get_desc(struct usbd_contex *const uds_ctx, - struct net_buf *const buf, - const uint8_t type, const uint8_t idx) +/* Copy and convert ASCII-7 string descriptor to UTF16-LE */ +static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, + struct net_buf *const buf, const uint16_t wLength) +{ + struct usb_string_descriptor *desc = dn->desc; + uint8_t *ascii7_str = (uint8_t *)&desc->bString; + size_t len; + + LOG_DBG("wLength %u, bLength %u, tailroom %u", + wLength, desc->bLength, net_buf_tailroom(buf)); + + len = MIN(net_buf_tailroom(buf), MIN(desc->bLength, wLength)); + + /* Add bLength and bDescriptorType */ + net_buf_add_mem(buf, desc, MIN(len, 2U)); + len -= MIN(len, 2U); + + for (size_t i = 0; i < len; i++) { + __ASSERT(ascii7_str[i] > 0x1F && ascii7_str[i] < 0x7F, + "Only printable ascii-7 characters are allowed in USB " + "string descriptors"); + net_buf_add_le16(buf, ascii7_str[i]); + } +} + +static int sreq_get_desc_dev(struct usbd_contex *const uds_ctx, + struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usb_desc_header *head; size_t len; - if (type == USB_DESC_DEVICE) { - switch (usbd_bus_speed(uds_ctx)) { - case USBD_SPEED_FS: - head = uds_ctx->fs_desc; - break; - case USBD_SPEED_HS: - head = uds_ctx->hs_desc; - break; - default: - errno = -ENOTSUP; - return 0; - } - } else { - head = usbd_get_descriptor(uds_ctx, type, idx); - } + len = MIN(setup->wLength, net_buf_tailroom(buf)); - if (head == NULL) { + switch (usbd_bus_speed(uds_ctx)) { + case USBD_SPEED_FS: + head = uds_ctx->fs_desc; + break; + case USBD_SPEED_HS: + head = uds_ctx->hs_desc; + break; + default: errno = -ENOTSUP; return 0; } - len = MIN(setup->wLength, net_buf_tailroom(buf)); net_buf_add_mem(buf, head, MIN(len, head->bLength)); return 0; } +static int sreq_get_desc_str(struct usbd_contex *const uds_ctx, + struct net_buf *const buf, const uint8_t idx) +{ + struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); + struct usb_desc_header *head; + struct usbd_desc_node *d_nd; + size_t len; + + /* Get string descriptor */ + d_nd = usbd_get_descriptor(uds_ctx, USB_DESC_STRING, idx); + if (d_nd == NULL) { + errno = -ENOTSUP; + return 0; + } + + if (d_nd->idx == 0U) { + /* Language ID string descriptor */ + head = d_nd->desc; + len = MIN(setup->wLength, net_buf_tailroom(buf)); + net_buf_add_mem(buf, head, MIN(len, head->bLength)); + } else { + /* String descriptors in ASCII7 format */ + string_ascii7_to_utf16le(d_nd, buf, setup->wLength); + } + + return 0; +} + static int sreq_get_dev_qualifier(struct usbd_contex *const uds_ctx, struct net_buf *const buf) { @@ -617,13 +661,13 @@ static int sreq_get_descriptor(struct usbd_contex *const uds_ctx, switch (desc_type) { case USB_DESC_DEVICE: - return sreq_get_desc(uds_ctx, buf, USB_DESC_DEVICE, 0); + return sreq_get_desc_dev(uds_ctx, buf); case USB_DESC_CONFIGURATION: return sreq_get_desc_cfg(uds_ctx, buf, desc_idx, false); case USB_DESC_OTHER_SPEED: return sreq_get_desc_cfg(uds_ctx, buf, desc_idx, true); case USB_DESC_STRING: - return sreq_get_desc(uds_ctx, buf, USB_DESC_STRING, desc_idx); + return sreq_get_desc_str(uds_ctx, buf, desc_idx); case USB_DESC_DEVICE_QUALIFIER: return sreq_get_dev_qualifier(uds_ctx, buf); case USB_DESC_INTERFACE: diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index 1d91c188d42ccc..70cfdec24565ad 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -17,54 +17,6 @@ #include LOG_MODULE_REGISTER(usbd_desc, CONFIG_USBD_LOG_LEVEL); -/* - * The last index of the initializer_string without null character is: - * ascii_idx_max = bLength / 2 - 2 - * Use this macro to determine the last index of ASCII7 string. - */ -#define USB_BSTRING_ASCII_IDX_MAX(n) (n / 2 - 2) - -/* - * The last index of the bString is: - * utf16le_idx_max = sizeof(initializer_string) * 2 - 2 - 1 - * utf16le_idx_max = bLength - 2 - 1 - * Use this macro to determine the last index of UTF16LE string. - */ -#define USB_BSTRING_UTF16LE_IDX_MAX(n) (n - 3) - -/** - * @brief Transform ASCII-7 string descriptor to UTF16-LE - * - * This function transforms ASCII-7 string descriptor - * into a UTF16-LE. - * - * @param[in] dn Pointer to descriptor node - */ -static void usbd_ascii7_to_utf16le(struct usbd_desc_node *const dn) -{ - struct usb_string_descriptor *desc = dn->desc; - int idx_max = USB_BSTRING_UTF16LE_IDX_MAX(desc->bLength); - int ascii_idx_max = USB_BSTRING_ASCII_IDX_MAX(desc->bLength); - uint8_t *buf = (uint8_t *)&desc->bString; - - LOG_DBG("idx_max %d, ascii_idx_max %d, buf %p", - idx_max, ascii_idx_max, buf); - - for (int i = idx_max; i >= 0; i -= 2) { - LOG_DBG("char %c : %x, idx %d -> %d", - buf[ascii_idx_max], - buf[ascii_idx_max], - ascii_idx_max, i); - __ASSERT(buf[ascii_idx_max] > 0x1F && buf[ascii_idx_max] < 0x7F, - "Only printable ascii-7 characters are allowed in USB " - "string descriptors"); - buf[i] = 0U; - buf[i - 1] = buf[ascii_idx_max--]; - } - - dn->utf16le = true; -} - /** * @brief Get common USB descriptor * @@ -171,8 +123,8 @@ static int desc_add_and_update_idx(struct usbd_contex *const uds_ctx, return 0; } -void *usbd_get_descriptor(struct usbd_contex *const uds_ctx, - const uint8_t type, const uint8_t idx) +struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, + const uint8_t type, const uint8_t idx) { struct usbd_desc_node *tmp; struct usb_desc_header *dh; @@ -180,7 +132,7 @@ void *usbd_get_descriptor(struct usbd_contex *const uds_ctx, SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, tmp, node) { dh = tmp->desc; if (tmp->idx == idx && dh->bDescriptorType == type) { - return tmp->desc; + return tmp; } } @@ -258,10 +210,6 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, default: break; } - - if (desc_nd->idx && !desc_nd->utf16le) { - usbd_ascii7_to_utf16le(desc_nd); - } } add_descriptor_error: diff --git a/subsys/usb/device_next/usbd_desc.h b/subsys/usb/device_next/usbd_desc.h index 0b3702206d2442..623e92e90c4a32 100644 --- a/subsys/usb/device_next/usbd_desc.h +++ b/subsys/usb/device_next/usbd_desc.h @@ -10,18 +10,18 @@ #include /** - * @brief Get common USB descriptor + * @brief Get USB descriptor node * - * Get descriptor from internal descriptor list. + * Get descriptor node from internal descriptor list. * * @param[in] ctx Pointer to USB device support context * @param[in] type Descriptor type (bDescriptorType) * @param[in] idx Descriptor index * - * @return pointer to descriptor or NULL if not found. + * @return pointer to descriptor node or NULL if not found. */ -void *usbd_get_descriptor(struct usbd_contex *uds_ctx, - const uint8_t type, const uint8_t idx); +struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, + const uint8_t type, const uint8_t idx); /** * @brief Remove all descriptors from an USB device context From 3536ee3cdbaafee87a54b925ded055c081797ad5 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0917/1389] usb: device_next: move string descriptor data to a separate structure Move and rework string descriptor data to a separate structure so we can share memory with another type. Also add description to the USBD_DESC_STRING_DEFINE macro. Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 57 ++++++++++++++++++++++-------- subsys/usb/device_next/usbd_ch9.c | 2 +- subsys/usb/device_next/usbd_desc.c | 49 +++++++++++++------------ 3 files changed, 68 insertions(+), 40 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 340cdf9f82be07..04001ad4276769 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -58,8 +58,10 @@ extern "C" { */ #define USB_STRING_DESCRIPTOR_LENGTH(s) (sizeof(s) * 2) -/* Used internally to keep descriptors in order */ -enum usbd_desc_usage_type { +/** Used internally to keep descriptors in order + * @cond INTERNAL_HIDDEN + */ +enum usbd_str_desc_utype { USBD_DUT_STRING_LANG, USBD_DUT_STRING_MANUFACTURER, USBD_DUT_STRING_PRODUCT, @@ -67,6 +69,22 @@ enum usbd_desc_usage_type { USBD_DUT_STRING_INTERFACE, }; +/** @endcond */ + +/** + * USBD string descriptor data + */ +struct usbd_str_desc_data { + /** Descriptor index, required for string descriptors */ + uint8_t idx; + /** Descriptor usage type (not bDescriptorType) */ + enum usbd_str_desc_utype utype : 8; + /** If not set, device stack obtains SN using the hwinfo API */ + unsigned int custom_sn : 1; + /** The string descriptor is in ASCII7 format */ + unsigned int ascii7 : 1; +}; + /** * Descriptor node * @@ -76,16 +94,11 @@ enum usbd_desc_usage_type { struct usbd_desc_node { /** slist node struct */ sys_dnode_t node; - /** Descriptor index, required for string descriptors */ - unsigned int idx : 8; - /** Descriptor usage type (not bDescriptorType) */ - unsigned int utype : 8; - /** If not set, string descriptor must be converted to UTF16LE */ - unsigned int utf16le : 1; - /** If not set, device stack obtains SN using the hwinfo API */ - unsigned int custom_sn : 1; + union { + struct usbd_str_desc_data str; + }; /** Pointer to a descriptor */ - void *desc; + void *const desc; }; /** @@ -438,11 +451,24 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c .bString = sys_cpu_to_le16(0x0409), \ }; \ static struct usbd_desc_node name = { \ - .idx = 0, \ - .utype = USBD_DUT_STRING_LANG, \ + .str = { \ + .idx = 0, \ + .utype = USBD_DUT_STRING_LANG, \ + }, \ .desc = &string_desc_##name, \ } +/** + * @brief Create a string descriptor + * + * This macro defines a descriptor node and a string descriptor. + * The string literal passed to the macro should be in the ASCII7 format. It + * is converted to UTF16LE format on the host request. + * + * @param d_name Internal string descriptor node identifier name + * @param d_string ASCII7 encoded string literal + * @param d_utype String descriptor usage type + */ #define USBD_DESC_STRING_DEFINE(d_name, d_string, d_utype) \ struct usb_string_descriptor_##d_name { \ uint8_t bLength; \ @@ -456,7 +482,10 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c .bString = d_string, \ }; \ static struct usbd_desc_node d_name = { \ - .utype = d_utype, \ + .str = { \ + .utype = d_utype, \ + .ascii7 = true, \ + }, \ .desc = &string_desc_##d_name, \ } diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index da80e778533af4..1092cf9ac23126 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -589,7 +589,7 @@ static int sreq_get_desc_str(struct usbd_contex *const uds_ctx, return 0; } - if (d_nd->idx == 0U) { + if (usbd_str_desc_get_idx(d_nd) == 0U) { /* Language ID string descriptor */ head = d_nd->desc; len = MIN(setup->wLength, net_buf_tailroom(buf)); diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index 70cfdec24565ad..4d4114bda9d585 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -89,36 +89,36 @@ static int desc_add_and_update_idx(struct usbd_contex *const uds_ctx, if (next_nd == NULL) { /* Last node of the same bDescriptorType or tail */ - new_nd->idx = tmp_nd->idx + 1; + new_nd->str.idx = tmp_nd->str.idx + 1; sys_dlist_append(&uds_ctx->descriptors, &new_nd->node); - LOG_DBG("Add %u behind %u", new_nd->idx, tmp_nd->idx); + LOG_DBG("Add %u behind %u", new_nd->str.idx, tmp_nd->str.idx); return 0; } if (!desc_type_equal(next_nd, new_nd)) { /* Last node of the same bDescriptorType */ - new_nd->idx = tmp_nd->idx + 1; + new_nd->str.idx = tmp_nd->str.idx + 1; sys_dlist_insert(&next_nd->node, &new_nd->node); - LOG_DBG("Add %u before %u", new_nd->idx, next_nd->idx); + LOG_DBG("Add %u before %u", new_nd->str.idx, next_nd->str.idx); return 0; } - if (tmp_nd->idx != (next_nd->idx - 1)) { + if (tmp_nd->str.idx != (next_nd->str.idx - 1)) { /* Add between nodes of the same bDescriptorType */ - new_nd->idx = tmp_nd->idx + 1; + new_nd->str.idx = tmp_nd->str.idx + 1; sys_dlist_insert(&next_nd->node, &new_nd->node); LOG_DBG("Add %u between %u and %u", - tmp_nd->idx, next_nd->idx, new_nd->idx); + tmp_nd->str.idx, next_nd->str.idx, new_nd->str.idx); return 0; } } /* If there are none of same bDescriptorType, node idx is set to 0. */ - new_nd->idx = 0; + new_nd->str.idx = 0; sys_dlist_append(&uds_ctx->descriptors, &new_nd->node); - LOG_DBG("Added first descriptor node (usage type %u)", new_nd->utype); + LOG_DBG("Added first descriptor node (usage type %u)", new_nd->str.utype); return 0; } @@ -126,13 +126,13 @@ static int desc_add_and_update_idx(struct usbd_contex *const uds_ctx, struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, const uint8_t type, const uint8_t idx) { - struct usbd_desc_node *tmp; + struct usbd_desc_node *desc_nd; struct usb_desc_header *dh; - SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, tmp, node) { - dh = tmp->desc; - if (tmp->idx == idx && dh->bDescriptorType == type) { - return tmp; + SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) { + dh = desc_nd->desc; + if (desc_nd->str.idx == idx && dh->bDescriptorType == type) { + return desc_nd; } } @@ -187,25 +187,24 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, } if (head->bDescriptorType == USB_DESC_STRING) { - switch (desc_nd->utype) { + switch (desc_nd->str.utype) { case USBD_DUT_STRING_LANG: break; case USBD_DUT_STRING_MANUFACTURER: - hs_desc->iManufacturer = desc_nd->idx; - fs_desc->iManufacturer = desc_nd->idx; + hs_desc->iManufacturer = desc_nd->str.idx; + fs_desc->iManufacturer = desc_nd->str.idx; break; case USBD_DUT_STRING_PRODUCT: - hs_desc->iProduct = desc_nd->idx; - fs_desc->iProduct = desc_nd->idx; + hs_desc->iProduct = desc_nd->str.idx; + fs_desc->iProduct = desc_nd->str.idx; break; case USBD_DUT_STRING_SERIAL_NUMBER: - if (!desc_nd->custom_sn) { + if (!desc_nd->str.custom_sn) { ret = usbd_get_sn_from_hwid(desc_nd); - desc_nd->utf16le = false; } - hs_desc->iSerialNumber = desc_nd->idx; - fs_desc->iSerialNumber = desc_nd->idx; + hs_desc->iSerialNumber = desc_nd->str.idx; + fs_desc->iSerialNumber = desc_nd->str.idx; break; default: break; @@ -220,7 +219,7 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, uint8_t usbd_str_desc_get_idx(const struct usbd_desc_node *const desc_nd) { if (sys_dnode_is_linked(&desc_nd->node)) { - return desc_nd->idx; + return desc_nd->str.idx; } return 0; @@ -230,6 +229,6 @@ void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd) { if (sys_dnode_is_linked(&desc_nd->node)) { sys_dlist_remove(&desc_nd->node); - desc_nd->idx = 0; + desc_nd->str.idx = 0; } } From 410d7846f3dbd449ca21c2d2699f3584ac3b91e1 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0918/1389] usb: device_next: rework SerialNumber generation from HWINFO Do not use application-provided placeholder buffers. Generate SerialNumber just before ASCII string is converted to UTF16LE. Make dependency on HWINFO optional, but enabled by default. Signed-off-by: Johann Fischer --- subsys/usb/device_next/Kconfig | 2 +- subsys/usb/device_next/usbd_ch9.c | 43 ++++++++++++++++++++++++++++- subsys/usb/device_next/usbd_desc.c | 44 ------------------------------ 3 files changed, 43 insertions(+), 46 deletions(-) diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index 72d3a84e5b46d5..a38823db71adda 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -6,7 +6,7 @@ menuconfig USB_DEVICE_STACK_NEXT bool "New USB device stack [EXPERIMENTAL]" select EXPERIMENTAL select UDC_DRIVER - select HWINFO + imply HWINFO help New experimental USB device stack. diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 1092cf9ac23126..57a946e7b7729a 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "usbd_device.h" #include "usbd_desc.h" @@ -523,17 +524,57 @@ static int sreq_get_desc_cfg(struct usbd_contex *const uds_ctx, return 0; } +#define USBD_HWID_SN_MAX 32U + +static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX]) +{ + static const char hex[] = "0123456789ABCDEF"; + uint8_t hwid[USBD_HWID_SN_MAX / 2U]; + ssize_t hwid_len = -ENOSYS; + + if (IS_ENABLED(CONFIG_HWINFO)) { + hwid_len = hwinfo_get_device_id(hwid, sizeof(hwid)); + } + + if (hwid_len < 0) { + if (hwid_len == -ENOSYS) { + LOG_ERR("HWINFO not implemented or enabled"); + } + + return hwid_len; + } + + for (ssize_t i = 0; i < hwid_len; i++) { + sn[i * 2] = hex[hwid[i] >> 4]; + sn[i * 2 + 1] = hex[hwid[i] & 0xF]; + } + + return hwid_len * 2; +} + /* Copy and convert ASCII-7 string descriptor to UTF16-LE */ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, struct net_buf *const buf, const uint16_t wLength) { struct usb_string_descriptor *desc = dn->desc; - uint8_t *ascii7_str = (uint8_t *)&desc->bString; + uint8_t hwid_sn[USBD_HWID_SN_MAX]; + uint8_t *ascii7_str; size_t len; LOG_DBG("wLength %u, bLength %u, tailroom %u", wLength, desc->bLength, net_buf_tailroom(buf)); + if (dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && !dn->str.custom_sn) { + if (get_sn_from_hwid(hwid_sn) < 0) { + errno = -ENOTSUP; + return; + } + + ascii7_str = hwid_sn; + } else { + ascii7_str = (uint8_t *)&desc->bString; + } + len = MIN(net_buf_tailroom(buf), MIN(desc->bLength, wLength)); /* Add bLength and bDescriptorType */ diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index 4d4114bda9d585..acf3cc3c1f82c9 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -9,7 +9,6 @@ #include #include #include -#include #include "usbd_desc.h" #include "usbd_device.h" @@ -17,45 +16,6 @@ #include LOG_MODULE_REGISTER(usbd_desc, CONFIG_USBD_LOG_LEVEL); -/** - * @brief Get common USB descriptor - * - * Get descriptor from internal descriptor list. - * - * @param[in] dn Pointer to descriptor node - * - * @return 0 on success, other values on fail. - */ -static int usbd_get_sn_from_hwid(struct usbd_desc_node *const dn) -{ - static const char hex[] = "0123456789ABCDEF"; - struct usb_string_descriptor *desc = dn->desc; - uint8_t *desc_data = (uint8_t *)&desc->bString; - uint8_t hwid[16]; - ssize_t hwid_len; - ssize_t min_len; - - hwid_len = hwinfo_get_device_id(hwid, sizeof(hwid)); - if (hwid_len < 0) { - if (hwid_len == -ENOSYS) { - LOG_WRN("hwinfo not implemented"); - return 0; - } - - return hwid_len; - } - - min_len = MIN(hwid_len, desc->bLength / 2); - for (size_t i = 0; i < min_len; i++) { - desc_data[i * 2] = hex[hwid[i] >> 4]; - desc_data[i * 2 + 1] = hex[hwid[i] & 0xF]; - } - - LOG_HEXDUMP_DBG(&desc->bString, desc->bLength, "SerialNumber"); - - return 0; -} - static inline bool desc_type_equal(const struct usbd_desc_node *const a, const struct usbd_desc_node *const b) { @@ -199,10 +159,6 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, fs_desc->iProduct = desc_nd->str.idx; break; case USBD_DUT_STRING_SERIAL_NUMBER: - if (!desc_nd->str.custom_sn) { - ret = usbd_get_sn_from_hwid(desc_nd); - } - hs_desc->iSerialNumber = desc_nd->str.idx; fs_desc->iSerialNumber = desc_nd->str.idx; break; From f2fb5f52d8966a6845594c87025f667ebaad5851 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0919/1389] usb: device_next: store bDescriptorType and bLength in descriptor node It simplifies the macros to create the string descriptors. We also no longer need placeholders for the SerialNumber descriptor when it is generated from hwid. In the future, we can store other descriptor types in the same list. Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 70 ++++++++++---------- samples/subsys/usb/common/sample_usbd_init.c | 2 +- subsys/usb/device_next/usbd_ch9.c | 35 ++++++---- subsys/usb/device_next/usbd_desc.c | 13 +--- subsys/usb/device_next/usbd_shell.c | 2 +- 5 files changed, 62 insertions(+), 60 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 04001ad4276769..9c272cdeaddfbf 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -79,10 +79,10 @@ struct usbd_str_desc_data { uint8_t idx; /** Descriptor usage type (not bDescriptorType) */ enum usbd_str_desc_utype utype : 8; - /** If not set, device stack obtains SN using the hwinfo API */ - unsigned int custom_sn : 1; /** The string descriptor is in ASCII7 format */ unsigned int ascii7 : 1; + /** Device stack obtains SerialNumber using the HWINFO API */ + unsigned int use_hwinfo : 1; }; /** @@ -97,8 +97,12 @@ struct usbd_desc_node { union { struct usbd_str_desc_data str; }; - /** Pointer to a descriptor */ - void *const desc; + /** Opaque pointer to a descriptor payload */ + const void *const ptr; + /** Descriptor size in bytes */ + uint8_t bLength; + /** Descriptor type */ + uint8_t bDescriptorType; }; /** @@ -444,18 +448,15 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * @param name Language string descriptor node identifier. */ #define USBD_DESC_LANG_DEFINE(name) \ - static struct usb_string_descriptor \ - string_desc_##name = { \ + static uint16_t langid_##name = sys_cpu_to_le16(0x0409); \ + static struct usbd_desc_node name = { \ .bLength = sizeof(struct usb_string_descriptor), \ .bDescriptorType = USB_DESC_STRING, \ - .bString = sys_cpu_to_le16(0x0409), \ - }; \ - static struct usbd_desc_node name = { \ .str = { \ .idx = 0, \ .utype = USBD_DUT_STRING_LANG, \ }, \ - .desc = &string_desc_##name, \ + .ptr = &langid_##name, \ } /** @@ -469,24 +470,16 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * @param d_string ASCII7 encoded string literal * @param d_utype String descriptor usage type */ -#define USBD_DESC_STRING_DEFINE(d_name, d_string, d_utype) \ - struct usb_string_descriptor_##d_name { \ - uint8_t bLength; \ - uint8_t bDescriptorType; \ - uint8_t bString[USB_BSTRING_LENGTH(d_string)]; \ - } __packed; \ - static struct usb_string_descriptor_##d_name \ - string_desc_##d_name = { \ - .bLength = USB_STRING_DESCRIPTOR_LENGTH(d_string), \ - .bDescriptorType = USB_DESC_STRING, \ - .bString = d_string, \ - }; \ - static struct usbd_desc_node d_name = { \ - .str = { \ - .utype = d_utype, \ - .ascii7 = true, \ - }, \ - .desc = &string_desc_##d_name, \ +#define USBD_DESC_STRING_DEFINE(d_name, d_string, d_utype) \ + static uint8_t ascii_##d_name[USB_BSTRING_LENGTH(d_string)] = d_string; \ + static struct usbd_desc_node d_name = { \ + .str = { \ + .utype = d_utype, \ + .ascii7 = true, \ + }, \ + .bLength = USB_STRING_DESCRIPTOR_LENGTH(d_string), \ + .bDescriptorType = USB_DESC_STRING, \ + .ptr = &ascii_##d_name, \ } /** @@ -520,17 +513,22 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c /** * @brief Create a string descriptor node and serial number string descriptor * - * This macro defines a descriptor node and a string descriptor that, - * when added to the device context, is automatically used as the serial number - * string descriptor. The string literal parameter is used as a placeholder, - * the unique number is obtained from hwinfo. Both descriptor node and descriptor - * are defined with static-storage-class specifier. + * This macro defines a descriptor node that, when added to the device context, + * is automatically used as the serial number string descriptor. A valid serial + * number is generated from HWID (HWINFO= whenever this string descriptor is + * requested. * * @param d_name String descriptor node identifier. - * @param d_string ASCII7 encoded serial number string literal placeholder */ -#define USBD_DESC_SERIAL_NUMBER_DEFINE(d_name, d_string) \ - USBD_DESC_STRING_DEFINE(d_name, d_string, USBD_DUT_STRING_SERIAL_NUMBER) +#define USBD_DESC_SERIAL_NUMBER_DEFINE(d_name) \ + static struct usbd_desc_node d_name = { \ + .str = { \ + .utype = USBD_DUT_STRING_SERIAL_NUMBER, \ + .ascii7 = true, \ + .use_hwinfo = true, \ + }, \ + .bDescriptorType = USB_DESC_STRING, \ + } #define USBD_DEFINE_CLASS(class_name, class_api, class_priv, class_v_reqs) \ static struct usbd_class_data class_name = { \ diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 19023e3212fdf3..585e3cfdcf03e7 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -22,7 +22,7 @@ USBD_DEVICE_DEFINE(sample_usbd, USBD_DESC_LANG_DEFINE(sample_lang); USBD_DESC_MANUFACTURER_DEFINE(sample_mfr, CONFIG_SAMPLE_USBD_MANUFACTURER); USBD_DESC_PRODUCT_DEFINE(sample_product, CONFIG_SAMPLE_USBD_PRODUCT); -USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn, "0123456789ABCDEF"); +USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn); static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ? USB_SCD_SELF_POWERED : 0) | diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 57a946e7b7729a..aa6e3851312e2b 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -526,6 +526,7 @@ static int sreq_get_desc_cfg(struct usbd_contex *const uds_ctx, #define USBD_HWID_SN_MAX 32U +/* Generate valid USB device serial number from hwid */ static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX]) { static const char hex[] = "0123456789ABCDEF"; @@ -556,30 +557,36 @@ static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX]) static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, struct net_buf *const buf, const uint16_t wLength) { - struct usb_string_descriptor *desc = dn->desc; uint8_t hwid_sn[USBD_HWID_SN_MAX]; + struct usb_desc_header head = { + .bDescriptorType = dn->bDescriptorType, + }; uint8_t *ascii7_str; size_t len; - LOG_DBG("wLength %u, bLength %u, tailroom %u", - wLength, desc->bLength, net_buf_tailroom(buf)); + if (dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && dn->str.use_hwinfo) { + ssize_t hwid_len = get_sn_from_hwid(hwid_sn); - if (dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && !dn->str.custom_sn) { - if (get_sn_from_hwid(hwid_sn) < 0) { + if (hwid_len < 0) { errno = -ENOTSUP; return; } + head.bLength = sizeof(head) + hwid_len * 2; ascii7_str = hwid_sn; } else { - ascii7_str = (uint8_t *)&desc->bString; + head.bLength = dn->bLength, + ascii7_str = (uint8_t *)dn->ptr; } - len = MIN(net_buf_tailroom(buf), MIN(desc->bLength, wLength)); + LOG_DBG("wLength %u, bLength %u, tailroom %u", + wLength, head.bLength, net_buf_tailroom(buf)); + + len = MIN(net_buf_tailroom(buf), MIN(head.bLength, wLength)); /* Add bLength and bDescriptorType */ - net_buf_add_mem(buf, desc, MIN(len, 2U)); - len -= MIN(len, 2U); + net_buf_add_mem(buf, &head, MIN(len, sizeof(head))); + len -= MIN(len, sizeof(head)); for (size_t i = 0; i < len; i++) { __ASSERT(ascii7_str[i] > 0x1F && ascii7_str[i] < 0x7F, @@ -619,7 +626,6 @@ static int sreq_get_desc_str(struct usbd_contex *const uds_ctx, struct net_buf *const buf, const uint8_t idx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); - struct usb_desc_header *head; struct usbd_desc_node *d_nd; size_t len; @@ -632,9 +638,14 @@ static int sreq_get_desc_str(struct usbd_contex *const uds_ctx, if (usbd_str_desc_get_idx(d_nd) == 0U) { /* Language ID string descriptor */ - head = d_nd->desc; + struct usb_string_descriptor langid = { + .bLength = d_nd->bLength, + .bDescriptorType = d_nd->bDescriptorType, + .bString = *(uint16_t *)d_nd->ptr, + }; + len = MIN(setup->wLength, net_buf_tailroom(buf)); - net_buf_add_mem(buf, head, MIN(len, head->bLength)); + net_buf_add_mem(buf, &langid, MIN(len, langid.bLength)); } else { /* String descriptors in ASCII7 format */ string_ascii7_to_utf16le(d_nd, buf, setup->wLength); diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index acf3cc3c1f82c9..efc9c217dbe80b 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -19,10 +19,7 @@ LOG_MODULE_REGISTER(usbd_desc, CONFIG_USBD_LOG_LEVEL); static inline bool desc_type_equal(const struct usbd_desc_node *const a, const struct usbd_desc_node *const b) { - const struct usb_desc_header *const head_a = a->desc; - const struct usb_desc_header *const head_b = b->desc; - - return head_a->bDescriptorType == head_b->bDescriptorType; + return a->bDescriptorType == b->bDescriptorType; } /* @@ -87,11 +84,9 @@ struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, const uint8_t type, const uint8_t idx) { struct usbd_desc_node *desc_nd; - struct usb_desc_header *dh; SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) { - dh = desc_nd->desc; - if (desc_nd->str.idx == idx && dh->bDescriptorType == type) { + if (desc_nd->str.idx == idx && desc_nd->bDescriptorType == type) { return desc_nd; } } @@ -116,7 +111,6 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, struct usbd_desc_node *const desc_nd) { struct usb_device_descriptor *hs_desc, *fs_desc; - struct usb_desc_header *head; int ret = 0; usbd_device_lock(uds_ctx); @@ -134,7 +128,6 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, sys_dlist_init(&uds_ctx->descriptors); } - head = desc_nd->desc; if (sys_dnode_is_linked(&desc_nd->node)) { ret = -EALREADY; goto add_descriptor_error; @@ -146,7 +139,7 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, goto add_descriptor_error; } - if (head->bDescriptorType == USB_DESC_STRING) { + if (desc_nd->bDescriptorType == USB_DESC_STRING) { switch (desc_nd->str.utype) { case USBD_DUT_STRING_LANG: break; diff --git a/subsys/usb/device_next/usbd_shell.c b/subsys/usb/device_next/usbd_shell.c index 9f0a3e6721894a..86e571177d7f5a 100644 --- a/subsys/usb/device_next/usbd_shell.c +++ b/subsys/usb/device_next/usbd_shell.c @@ -43,7 +43,7 @@ static struct usbd_shell_speed { USBD_DESC_LANG_DEFINE(lang); USBD_DESC_MANUFACTURER_DEFINE(mfr, "ZEPHYR"); USBD_DESC_PRODUCT_DEFINE(product, "Zephyr USBD foobaz"); -USBD_DESC_SERIAL_NUMBER_DEFINE(sn, "0123456789ABCDEF"); +USBD_DESC_SERIAL_NUMBER_DEFINE(sn); /* Default device descriptors and context used in the shell. */ USBD_DEVICE_DEFINE(sh_uds_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), From 78e7ca3a7c558048db14cabef17f49205efe58a8 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:15 +0200 Subject: [PATCH 0920/1389] usb: bos: cleanup Binary Device Object Store header We could reuse the BOS header, but there are parts that are only needed in the legacy device support or used internally and the tests. Move this parts to the appropriate places. Signed-off-by: Johann Fischer --- include/zephyr/usb/bos.h | 52 ++++------------------------- include/zephyr/usb/usb_device.h | 17 ++++++++++ subsys/usb/device/bos.c | 11 ++++-- subsys/usb/device/bos_desc.h | 25 ++++++++++++++ subsys/usb/device/usb_device.c | 1 + tests/subsys/usb/bos/src/test_bos.c | 2 ++ 6 files changed, 60 insertions(+), 48 deletions(-) create mode 100644 subsys/usb/device/bos_desc.h diff --git a/include/zephyr/usb/bos.h b/include/zephyr/usb/bos.h index b7a0ef08339fe3..f73e7c06678ea3 100644 --- a/include/zephyr/usb/bos.h +++ b/include/zephyr/usb/bos.h @@ -17,12 +17,13 @@ * @{ */ -/** - * @brief Helper macro to place the BOS compatibility descriptor - * in the right memory section. - */ -#define USB_DEVICE_BOS_DESC_DEFINE_CAP \ - static __in_section(usb, bos_desc_area, 1) __aligned(1) __used +/** Root BOS Descriptor */ +struct usb_bos_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; +} __packed; /** Device capability type codes */ enum usb_bos_capability_types { @@ -62,45 +63,6 @@ struct usb_bos_capability_msos { uint8_t bAltEnumCode; } __packed; -/** - * @brief Register BOS capability descriptor - * - * This function should be used by the application to register BOS capability - * descriptors before the USB device stack is enabled. - * - * @param[in] hdr Pointer to BOS capability descriptor - */ -void usb_bos_register_cap(struct usb_bos_platform_descriptor *hdr); - -/** - * @cond INTERNAL_HIDDEN - * Internally used functions - */ - -/* BOS Descriptor (root descriptor) */ -struct usb_bos_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumDeviceCaps; -} __packed; - -#define USB_DEVICE_BOS_DESC_DEFINE_HDR \ - static __in_section(usb, bos_desc_area, 0) __aligned(1) __used - -size_t usb_bos_get_length(void); - -void usb_bos_fix_total_length(void); - -const void *usb_bos_get_header(void); - -#if defined(CONFIG_USB_DEVICE_BOS) -int usb_handle_bos(struct usb_setup_packet *setup, int32_t *len, uint8_t **data); -#else -#define usb_handle_bos(x, y, z) -ENOTSUP -#endif -/** @endcond */ - /** * @} */ diff --git a/include/zephyr/usb/usb_device.h b/include/zephyr/usb/usb_device.h index 0de535365ee17d..59c3db1cb59057 100644 --- a/include/zephyr/usb/usb_device.h +++ b/include/zephyr/usb/usb_device.h @@ -446,6 +446,23 @@ int usb_wakeup_request(void); */ bool usb_get_remote_wakeup_status(void); +/** + * @brief Helper macro to place the BOS compatibility descriptor + * in the right memory section. + */ +#define USB_DEVICE_BOS_DESC_DEFINE_CAP \ + static __in_section(usb, bos_desc_area, 1) __aligned(1) __used + +/** + * @brief Register BOS capability descriptor + * + * This function should be used by the application to register BOS capability + * descriptors before the USB device stack is enabled. + * + * @param[in] hdr Pointer to BOS capability descriptor + */ +void usb_bos_register_cap(void *hdr); + /** * @} */ diff --git a/subsys/usb/device/bos.c b/subsys/usb/device/bos.c index 57abfff9cacc92..4b7feb22513308 100644 --- a/subsys/usb/device/bos.c +++ b/subsys/usb/device/bos.c @@ -7,15 +7,18 @@ #include LOG_MODULE_REGISTER(usb_bos, CONFIG_USB_DEVICE_LOG_LEVEL); -#include +#include +#include #include - #include extern const uint8_t __usb_bos_desc_start[]; extern const uint8_t __usb_bos_desc_end[]; +#define USB_DEVICE_BOS_DESC_DEFINE_HDR \ + static __in_section(usb, bos_desc_area, 0) __aligned(1) __used + USB_DEVICE_BOS_DESC_DEFINE_HDR struct usb_bos_descriptor bos_hdr = { .bLength = sizeof(struct usb_bos_descriptor), .bDescriptorType = USB_DESC_BOS, @@ -38,8 +41,10 @@ void usb_bos_fix_total_length(void) bos_hdr.wTotalLength = usb_bos_get_length(); } -void usb_bos_register_cap(struct usb_bos_platform_descriptor *desc) +void usb_bos_register_cap(void *desc) { + ARG_UNUSED(desc); + /* Has effect only on first register */ bos_hdr.wTotalLength = usb_bos_get_length(); diff --git a/subsys/usb/device/bos_desc.h b/subsys/usb/device/bos_desc.h new file mode 100644 index 00000000000000..711b1a78ebdafe --- /dev/null +++ b/subsys/usb/device/bos_desc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_USB_DEVICE_BOS_DESC_H_ +#define ZEPHYR_INCLUDE_USB_DEVICE_BOS_DESC_H_ + +#include +#include + +size_t usb_bos_get_length(void); + +void usb_bos_fix_total_length(void); + +const void *usb_bos_get_header(void); + +#if defined(CONFIG_USB_DEVICE_BOS) +int usb_handle_bos(struct usb_setup_packet *setup, int32_t *len, uint8_t **data); +#else +#define usb_handle_bos(x, y, z) -ENOTSUP +#endif + +#endif /* ZEPHYR_INCLUDE_USB_DEVICE_BOS_DESC_H_ */ diff --git a/subsys/usb/device/usb_device.c b/subsys/usb/device/usb_device.c index 41c813a61b46d3..a3670a16804b7b 100644 --- a/subsys/usb/device/usb_device.c +++ b/subsys/usb/device/usb_device.c @@ -59,6 +59,7 @@ #include #include +#include #include #include #include diff --git a/tests/subsys/usb/bos/src/test_bos.c b/tests/subsys/usb/bos/src/test_bos.c index 1bd4d9f46cb952..e9452d86fc3014 100644 --- a/tests/subsys/usb/bos/src/test_bos.c +++ b/tests/subsys/usb/bos/src/test_bos.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include #include From 70e73d79008f74563ae07afa36809045e2c31da4 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0921/1389] usb: device_next: add initial BOS support Use the same scheme as for string descriptors. Descriptors can be added or removed using the existend interface. Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 39 +++++++++++++++++++-- subsys/usb/device_next/usbd_ch9.c | 56 ++++++++++++++++++++++++++++++ subsys/usb/device_next/usbd_desc.c | 29 ++++++++++++---- 3 files changed, 114 insertions(+), 10 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 9c272cdeaddfbf..6d697c88869f98 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -15,6 +15,7 @@ #define ZEPHYR_INCLUDE_USBD_H_ #include +#include #include #include #include @@ -69,6 +70,9 @@ enum usbd_str_desc_utype { USBD_DUT_STRING_INTERFACE, }; +enum usbd_bos_desc_utype { + USBD_DUT_BOS_NONE, +}; /** @endcond */ /** @@ -85,17 +89,26 @@ struct usbd_str_desc_data { unsigned int use_hwinfo : 1; }; +/** + * USBD BOS Device Capability descriptor data + */ +struct usbd_bos_desc_data { + /** Descriptor usage type (not bDescriptorType) */ + enum usbd_bos_desc_utype utype : 8; +}; + /** * Descriptor node * * Descriptor node is used to manage descriptors that are not - * directly part of a structure, such as string or bos descriptors. + * directly part of a structure, such as string or BOS capability descriptors. */ struct usbd_desc_node { /** slist node struct */ sys_dnode_t node; union { struct usbd_str_desc_data str; + struct usbd_bos_desc_data bos; }; /** Opaque pointer to a descriptor payload */ const void *const ptr; @@ -219,7 +232,7 @@ struct usbd_contex { usbd_msg_cb_t msg_cb; /** Middle layer runtime data */ struct usbd_ch9_data ch9_data; - /** slist to manage descriptors like string, bos */ + /** slist to manage descriptors like string, BOS */ sys_dlist_t descriptors; /** slist to manage Full-Speed device configurations */ sys_slist_t fs_configs; @@ -530,6 +543,26 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c .bDescriptorType = USB_DESC_STRING, \ } +/** + * @brief Define BOS Device Capability descriptor node + * + * The application defines a BOS capability descriptor node for descriptors + * such as USB 2.0 Extension Descriptor. + * + * @param name Descriptor node identifier + * @param len Device Capability descriptor length + * @param subset Pointer to a Device Capability descriptor + */ +#define USBD_DESC_BOS_DEFINE(name, len, subset) \ + static struct usbd_desc_node name = { \ + .bos = { \ + .utype = USBD_DUT_BOS_NONE, \ + }, \ + .ptr = subset, \ + .bLength = len, \ + .bDescriptorType = USB_DESC_BOS, \ + } + #define USBD_DEFINE_CLASS(class_name, class_api, class_priv, class_v_reqs) \ static struct usbd_class_data class_name = { \ .name = STRINGIFY(class_name), \ @@ -569,7 +602,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c /** * @brief Add common USB descriptor * - * Add common descriptor like string or bos. + * Add common descriptor like string or BOS Device Capability. * * @param[in] uds_ctx Pointer to USB device support context * @param[in] dn Pointer to USB descriptor node diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index aa6e3851312e2b..8e7db0b756e771 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -691,6 +691,60 @@ static int sreq_get_dev_qualifier(struct usbd_contex *const uds_ctx, return 0; } +static void desc_fill_bos_root(struct usbd_contex *const uds_ctx, + struct usb_bos_descriptor *const root) +{ + struct usbd_desc_node *desc_nd; + + root->bLength = sizeof(struct usb_bos_descriptor); + root->bDescriptorType = USB_DESC_BOS; + root->wTotalLength = root->bLength; + + SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) { + if (desc_nd->bDescriptorType == USB_DESC_BOS) { + root->wTotalLength += desc_nd->bLength; + root->bNumDeviceCaps += desc_nd->bLength; + } + } +} + +static int sreq_get_desc_bos(struct usbd_contex *const uds_ctx, + struct net_buf *const buf) +{ + struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); + struct usb_bos_descriptor bos; + struct usbd_desc_node *desc_nd; + size_t len; + + desc_fill_bos_root(uds_ctx, &bos); + len = MIN(net_buf_tailroom(buf), MIN(setup->wLength, bos.wTotalLength)); + + LOG_DBG("wLength %u, bLength %u, wTotalLength %u, tailroom %u", + setup->wLength, bos.bLength, bos.wTotalLength, net_buf_tailroom(buf)); + + net_buf_add_mem(buf, &bos, MIN(len, bos.bLength)); + + len -= MIN(len, sizeof(bos)); + if (len == 0) { + return 0; + } + + SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) { + if (desc_nd->bDescriptorType == USB_DESC_BOS) { + LOG_DBG("bLength %u, len %u, tailroom %u", + desc_nd->bLength, len, net_buf_tailroom(buf)); + net_buf_add_mem(buf, desc_nd->ptr, MIN(len, desc_nd->bLength)); + + len -= MIN(len, desc_nd->bLength); + if (len == 0) { + break; + } + } + } + + return 0; +} + static int sreq_get_descriptor(struct usbd_contex *const uds_ctx, struct net_buf *const buf) { @@ -722,6 +776,8 @@ static int sreq_get_descriptor(struct usbd_contex *const uds_ctx, return sreq_get_desc_str(uds_ctx, buf, desc_idx); case USB_DESC_DEVICE_QUALIFIER: return sreq_get_dev_qualifier(uds_ctx, buf); + case USB_DESC_BOS: + return sreq_get_desc_bos(uds_ctx, buf); case USB_DESC_INTERFACE: case USB_DESC_ENDPOINT: default: diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index efc9c217dbe80b..ecc8e57259a46a 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -86,8 +86,16 @@ struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, struct usbd_desc_node *desc_nd; SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) { - if (desc_nd->str.idx == idx && desc_nd->bDescriptorType == type) { - return desc_nd; + if (desc_nd->bDescriptorType == type) { + if (desc_nd->bDescriptorType == USB_DESC_STRING) { + if (desc_nd->str.idx == idx) { + return desc_nd; + } + } + + if (desc_nd->bDescriptorType == USB_DESC_BOS) { + return desc_nd; + } } } @@ -133,13 +141,17 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx, goto add_descriptor_error; } - ret = desc_add_and_update_idx(uds_ctx, desc_nd); - if (ret) { - ret = -EINVAL; - goto add_descriptor_error; + if (desc_nd->bDescriptorType == USB_DESC_BOS) { + sys_dlist_append(&uds_ctx->descriptors, &desc_nd->node); } if (desc_nd->bDescriptorType == USB_DESC_STRING) { + ret = desc_add_and_update_idx(uds_ctx, desc_nd); + if (ret) { + ret = -EINVAL; + goto add_descriptor_error; + } + switch (desc_nd->str.utype) { case USBD_DUT_STRING_LANG: break; @@ -178,6 +190,9 @@ void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd) { if (sys_dnode_is_linked(&desc_nd->node)) { sys_dlist_remove(&desc_nd->node); - desc_nd->str.idx = 0; + + if (desc_nd->bDescriptorType == USB_DESC_STRING) { + desc_nd->str.idx = 0U; + } } } From 444702f4776d29cc14690fdb995d46629ba71a48 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0922/1389] samples: usb: add a sample USB 2.0 Extension Descriptor Add a sample USB 2.0 Extension Descriptor. Signed-off-by: Johann Fischer --- samples/subsys/usb/common/Kconfig.sample_usbd | 5 ++++ samples/subsys/usb/common/sample_usbd_init.c | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/samples/subsys/usb/common/Kconfig.sample_usbd b/samples/subsys/usb/common/Kconfig.sample_usbd index 1d330c2ad08746..765fc69bf21721 100644 --- a/samples/subsys/usb/common/Kconfig.sample_usbd +++ b/samples/subsys/usb/common/Kconfig.sample_usbd @@ -45,4 +45,9 @@ config SAMPLE_USBD_MAX_POWER help bMaxPower value in the sample configuration in 2 mA units. +config SAMPLE_USBD_20_EXTENSION_DESC + bool "Use default USB 2.0 Extension Descriptor" + help + Set bcdUSB value to 0201 and use default USB 2.0 Extension Descriptor. + endmenu diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 585e3cfdcf03e7..1a712819c5711a 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -37,6 +38,19 @@ USBD_CONFIGURATION_DEFINE(sample_hs_config, attributes, CONFIG_SAMPLE_USBD_MAX_POWER); +/* + * This does not yet provide valuable information, but rather serves as an + * example, and will be improved in the future. + */ +static const struct usb_bos_capability_lpm bos_cap_lpm = { + .bLength = sizeof(struct usb_bos_capability_lpm), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, + .bmAttributes = 0UL, +}; + +USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); + static int register_fs_classes(struct usbd_contex *uds_ctx) { int err = 0; @@ -169,6 +183,17 @@ struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb) } } + if (IS_ENABLED(CONFIG_SAMPLE_USBD_20_EXTENSION_DESC)) { + (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_FS, 0x0201); + (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_HS, 0x0201); + + err = usbd_add_descriptor(&sample_usbd, &sample_usbext); + if (err) { + LOG_ERR("Failed to add USB 2.0 Extension Descriptor"); + return NULL; + } + } + err = usbd_init(&sample_usbd); if (err) { LOG_ERR("Failed to initialize device support"); From eef9c85342eda31a771bde3f4fb8fe11bc25e5e3 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0923/1389] sample: hid-mouse: exclude frdm_mcxn947 Board does not specify "zephyr,code" and is fails in twister. Signed-off-by: Johann Fischer --- samples/subsys/usb/hid-mouse/sample.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/subsys/usb/hid-mouse/sample.yaml b/samples/subsys/usb/hid-mouse/sample.yaml index d7d79f83ec3bfd..77ede76aeb42d3 100644 --- a/samples/subsys/usb/hid-mouse/sample.yaml +++ b/samples/subsys/usb/hid-mouse/sample.yaml @@ -8,6 +8,8 @@ common: - gpio tests: sample.usb.hid-mouse: + platform_exclude: + - frdm_mcxn947/mcxn947/cpu0 tags: usb sample.usb_device_next.hid-mouse: platform_allow: From 438deb17694b736c49a3e2f0258028f3569d0f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0924/1389] samples: net: http_server: add link to HTTP Server doc page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve navigability in the documentation by adding a link to the main HTTP Server documentation page to the HTTP Server sample. Signed-off-by: Benjamin Cabé --- samples/net/sockets/http_server/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/net/sockets/http_server/README.rst b/samples/net/sockets/http_server/README.rst index 8e6740a6348d7d..4d802ae1a35c42 100644 --- a/samples/net/sockets/http_server/README.rst +++ b/samples/net/sockets/http_server/README.rst @@ -7,7 +7,7 @@ Overview -------- -This sample application demonstrates the use of the ``http_server`` library. +This sample application demonstrates the use of the :ref:`http_server_interface` library. This library provides high-level functions to simplify and abstract server implementation. The server supports the HTTP/1.1 protocol which can also be upgraded to HTTP/2, it also support native HTTP/2 protocol without upgrading. From a91a76807f8652942737d5b71bcf47e355f0fb78 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0925/1389] include: arch: x86: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- include/zephyr/arch/x86/arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/arch/x86/arch.h b/include/zephyr/arch/x86/arch.h index f7e75b3aab6154..d58411bb1b507f 100644 --- a/include/zephyr/arch/x86/arch.h +++ b/include/zephyr/arch/x86/arch.h @@ -219,7 +219,7 @@ static ALWAYS_INLINE int sys_test_and_clear_bit(mem_addr_t addr, extern unsigned char _irq_to_interrupt_vector[]; #define Z_IRQ_TO_INTERRUPT_VECTOR(irq) \ - ((unsigned int) _irq_to_interrupt_vector[irq]) + ((unsigned int) _irq_to_interrupt_vector[(irq)]) #endif /* _ASMLANGUAGE */ From 0cad308dca588045ec25e31ad27b877e67507516 Mon Sep 17 00:00:00 2001 From: Karthikeyan Krishnasamy Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0926/1389] samples: cellular: fix dtsi path in overlay fix dtsi include path for board nrf9160dk_nrf52840 Signed-off-by: Karthikeyan Krishnasamy --- samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay index c639ec8b305379..6fd249e01c4ee7 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay @@ -1,4 +1,4 @@ -#include +#include / { aliases { From 228773951531b763f0649aef13fdbe3276cda807 Mon Sep 17 00:00:00 2001 From: Karthikeyan Krishnasamy Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0927/1389] samples: bluetooth: hci_uart: fix dtsi path in overlay fix dtsi overlay include path for nrf9160dk_nrf52840 Signed-off-by: Karthikeyan Krishnasamy --- samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay | 4 ++-- .../hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay index 4209320fcff3fd..8ec74170f94ebf 100644 --- a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay +++ b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include -#include +#include &uart1 { current-speed = <1000000>; diff --git a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay index 409d3bada63f08..692d2a5749b07b 100644 --- a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay +++ b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay @@ -5,4 +5,4 @@ */ /* Use the reset line that is available starting from v0.14.0 of the DK. */ -#include +#include From b3c4b2bbed8d1ac0bcda3c43f6804b5c0ab8be8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0928/1389] dts: nordic: nrf54h20: Fix exmif node definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the "snps,designware-spi" compatible from the EXMIF node in nRF54H20i, as the spi_dw driver cannot be used for this peripheral without Nordic-specific modifications that are not present upstream. An attempt to do so (just setting CONFIG_SPI=y will cause that, as the driver initialization function will be executed then) results in a bus fault. Signed-off-by: Andrzej Głąbek --- dts/common/nordic/nrf54h20.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 010819d0b6f094..4e71c0be76945e 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -346,7 +346,7 @@ }; exmif: spi@95000 { - compatible = "nordic,nrf-exmif", "snps,designware-spi"; + compatible = "nordic,nrf-exmif"; #address-cells = <1>; #size-cells = <0>; reg = <0x95000 0x500 0x95500 0xb00>; From 9c25dfbc7d5385ae589e3f4a91cae39c73566d86 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0929/1389] doc: introduce SoC porting guide Fixes: #27439 This commit introduces an initial SoC porting guide with a general description of the minimal set of files needed to support a new SoC in Zephyr, along with some examples of the content. Signed-off-by: Torsten Rasmussen --- doc/hardware/porting/index.rst | 1 + doc/hardware/porting/soc_porting.rst | 304 +++++++++++++++++++++++++++ 2 files changed, 305 insertions(+) create mode 100644 doc/hardware/porting/soc_porting.rst diff --git a/doc/hardware/porting/index.rst b/doc/hardware/porting/index.rst index e6453a5ba48ac5..91dc8b6ef38fd8 100644 --- a/doc/hardware/porting/index.rst +++ b/doc/hardware/porting/index.rst @@ -9,5 +9,6 @@ These pages document how to port Zephyr to new hardware. :maxdepth: 1 arch.rst + soc_porting.rst board_porting.rst shields.rst diff --git a/doc/hardware/porting/soc_porting.rst b/doc/hardware/porting/soc_porting.rst new file mode 100644 index 00000000000000..5f97065734b369 --- /dev/null +++ b/doc/hardware/porting/soc_porting.rst @@ -0,0 +1,304 @@ +.. _soc_porting_guide: + +SoC Porting Guide +################### + +To add Zephyr support for a new :term:`SoC`, you need a *SoC directory* with +various files in it, and a SoC :file:`.dtsi` in +:zephyr_file:`dts//` is required. + +SoC Definitions +*************** + +It is expected that you are familiar with the board concept in Zephyr. +A high level overview of the hardware support hierarchy and terms used in the +Zephyr documentation can be seen in :ref:`hw_support_hierarchy`. + +For SoC porting, the most important terms are: + +- SoC: the exact system on a chip the board's CPU is part of. +- SoC series: a group of tightly related SoCs. +- SoC family: a wider group of SoCs with similar characteristics. +- CPU Cluster: a cluster of one or more CPU cores. +- CPU core: a particular CPU instance of a given architecture. +- Architecture: an instruction set architecture. + +Architecture +============ + +See :ref:`architecture_porting_guide`. + + +Create your SoC directory +************************* + +Each SoC must have a unique name. Use the official name given by the SoC vendor +and check that it's not already in use. In some cases someone else may have +contributed a SoC with identical name. If the SoC name is already in use, then +you should probably improve the existing SoC instead of creating a new one. +The script ``list_hardware`` can be used to retrieve a list of all SoCs known +in Zephyr, for example ``./scripts/list_hardware.py --soc-root=. --socs`` from +the Zephyr base directory for a list of names that are already in use. + +Start by creating the directory ``zephyr/soc//soc1``, where +```` is your vendor subdirectory. + +.. note:: + A ```` subdirectory is mandatory if contributing your SoC + to Zephyr, but if your SoC is placed in a local repo, then any folder + structure under ``/soc`` is permitted. + The ```` subdirectory must match a vendor defined in the list in + :zephyr_file:`dts/bindings/vendor-prefixes.txt`. If the SoC vendor does not + have a prefix in that list, then one must be created. + +.. note:: + + The SoC directory name does not need to match the name of the SoC. + Multiple SoCs can even be defined in one directory. In Zephyr, SoCs are often + organized in sub-folders in a common SoC Family or SoC Series tree. + +Your SoC directory should look like this: + +.. code-block:: none + + soc// + ├── soc.yml + ├── soc.h + ├── CMakeLists.txt + ├── Kconfig + ├── Kconfig.soc + └── Kconfig.defconfig + +Replace ```` with your SoC's name. + + +The mandatory files are: + +#. :file:`soc.yml`: a YAML file describing the high-level meta data of the + SoC such as: + - SoC name: the name of the SoC + - CPU clusters: CPU clusters if the SoC contains one or more clusters + - SoC series: the SoC series to which the SoC belong + - SoC family: the SoC family to which the series belong + +#. :file:`soc.h`: a header file which can be used to describe or provide + configuration macros for the SoC. The :file:`soc.h` will often be included in + drivers, sub-systems, boards, and other source code found in Zephyr. + +#. :file:`Kconfig.soc`: the base SoC configuration which defines a Kconfig SoC + symbol in the form of ``config SOC_`` and provides the SoC name to + the Kconfig ``SOC`` setting. + If the ``soc.yml`` describes a SoC family and series, then those must also + be defined in this file. Kconfig settings outside of the SoC tree must not be + selected. To select general Zephyr Kconfig settings the :file:`Kconfig` file + must be used. + +#. :file:`CMakeLists.txt`: CMake file loaded by the Zephyr build system. This + CMake file can define additional include paths and/or source files to be used + when a build targets the SoC. Also the base line linker script to use must be + defined. + +The optional files are: + +- :file:`Kconfig`, :file:`Kconfig.defconfig` software configuration in + :ref:`kconfig` format. These select the architecture and peripherals + available. + +Write your SoC YAML +********************* + +The SoC YAML file describes the SoC family, SoC series, and SoC at a high level. + +Detailed configurations, such as hardware description and configuration are done +in devicetree and Kconfig. + +The skeleton of a simple SoC YAML file containing just one SoC is: + +.. code-block:: yaml + + socs: + - name: + +It is possible to have multiple SoC located in the SoC folder. +For example if they belong to a common family or series it is recommended to +locate such SoC in a common tree. +Multiple SoCs and SoC series in a common folder can be described in the +:file:`soc.yml` file as: + +.. code-block:: yaml + + family: + name: + series: + - name: + socs: + - name: + cpucluster: + - name: + - name: + ... + - name: + - name: + ... + + +Write your SoC devicetree +************************* + +SoC devicetree include files are located in the :file:`/dts` folder +under a corresponding :file:`/`. + +The SoC :file:`dts///.dtsi` describes your SoC hardware in +the Devicetree Source (DTS) format and must be included by any boards which use +the SoC. + +If a highlevel :file:`.dtsi` file exists, then a good starting point is to +include this file in your :file:`.dtsi`. + +In general, :file:`.dtsi` should look like this: + +.. code-block:: devicetree + + #include /.dtsi + + / { + chosen { + /* common chosen settings for your SoC */ + }; + + cpus { + #address-cells = ; + #size-cells = ; + + cpu@0 { + device_type = "cpu"; + compatible = ""; + /* ... your CPU definitions ... */ + }; + + soc { + /* Your SoC definitions and peripherals */ + /* such as ram, clock, buses, peripherals. */ + }; + }; + +.. hint:: + It is possible to structure multiple :file:`/.dtsi` files in + sub-directories for a cleaner file system structure. For example organized + pre SoC series, like this: :file:`//.dtsi`. + + +Multiple CPU clusters +===================== + +Devicetree reflects the hardware. The memory space and peripherals available to +one CPU cluster can be very different from another CPU cluster, therefore each +CPU cluster will often have its own :file:`.dtsi` file. + +CPU cluster :file:`.dtsi` files should follow the naming scheme +:file:`_.dtsi`. A :file:`_.dtsi` file will look +similar to a SoC :file:`.dtsi` without CPU clusters. + +Write Kconfig files +******************* + +Zephyr uses the Kconfig language to configure software features. Your SoC +needs to provide some Kconfig settings before you can compile a Zephyr +application for it. + +Setting Kconfig configuration values is documented in detail in +:ref:`setting_configuration_values`. + +There is one mandatory Kconfig file in the SoC directory, and two optional +files for a SoC: + +.. code-block:: none + + soc// + ├── Kconfig.soc + ├── Kconfig + └── Kconfig.defconfig + +:file:`Kconfig.soc` + A shared Kconfig file which can be sourced both in Zephyr Kconfig and sysbuild + Kconfig trees. + + This file selects the SoC family and series in the Kconfig tree and potential + other SoC related Kconfig settings. In some cases a SOC_PART_NUMBER. + This file must not select anything outside the re-usable Kconfig SoC tree. + + A :file:`Kconfig.soc` may look like this: + + .. code-block:: kconfig + + config SOC_ + bool + + config SOC_ + bool + select SOC_SERIES_ + + config SOC + default "SoC name" if SOC_ + + Notice that ``SOC_NAME`` is a pure upper case version of the SoC name. + + The Kconfig ``SOC`` setting is globally defined as a string and therefore the + :file:`Kconfig.soc` file shall only define the default string value and not + the type. Notice that the string value must match the SoC name used in the + :file:`soc.yml` file. + +:file:`Kconfig` + Included by :zephyr_file:`soc/Kconfig`. + + This file can add Kconfig settings which are specific to the current SoC. + + The :file:`Kconfig` will often indicate given hardware support using a setting + of the form ``HAS_``. + + .. code-block:: kconfig + + config SOC_ + select ARM + select CPU_HAS_FPU + + If the setting name is identical to an existing Kconfig setting in Zephyr and + only modifies the default value of said setting, then + :file:`Kconfig.defconfig` should be used instead. + +:file:`Kconfig.defconfig` + SoC specific default values for Kconfig options. + + Not all SoCs have a :file:`Kconfig.defconfig` file. + + The entire file should be inside a pair of ``if SOC_`` / ``endif`` + or ``if SOC_SERIES_`` / ``endif``, like this: + + .. code-block:: kconfig + + if SOC_ + + config NUM_IRQS + default 32 + + endif # SOC_ + +Multiple CPU clusters +===================== + +CPU clusters must provide additional Kconfig settings in the :file:`Kconfig.soc` +file. This will usually be in the form of ``SOC__`` so for +a given ``soc1`` with two clusters ``clusterA`` and ``clusterB``, then this +will look like: + +SoC's When a SoC defines CPU cluster + + .. code-block:: kconfig + + config SOC_SOC1_CLUSTERA + bool + select SOC_SOC1 + + config SOC_SOC1_CLUSTERB + bool + select SOC_SOC1 From 823ae66cc5471c87bc798a7f25a99eb9373fb058 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0930/1389] drivers: display: smartbond: Acquire power rail when using PM The power rail of a peripheral block should always be acquired/released before/after its employment even if it's known that it should already be up and running. Signed-off-by: Ioannis Karachalios --- drivers/mipi_dbi/mipi_dbi_smartbond.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/mipi_dbi/mipi_dbi_smartbond.c b/drivers/mipi_dbi/mipi_dbi_smartbond.c index 034831075b2e84..480ee2158b2062 100644 --- a/drivers/mipi_dbi/mipi_dbi_smartbond.c +++ b/drivers/mipi_dbi/mipi_dbi_smartbond.c @@ -497,11 +497,24 @@ static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device /* Sleep is only allowed when there are no active LCDC operations */ if (!data->is_active) { (void)mipi_dbi_smartbond_suspend(dev); + /* + * Once the display block is turned off, its power domain + * can be released as well. + */ + da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); ret = 0; } break; case PM_DEVICE_ACTION_RESUME: __ASSERT_NO_MSG(!data->is_active); + + /* + * Although PD_SYS should already be turned on, make sure LCD controller's + * power domain is up and running before accessing the display block. + * Acquiring PD_SYS is mandatory when in PM runtime mode. + */ + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + /* * The resume error code should not be taken into consideration * by the PM subsystem. @@ -546,6 +559,7 @@ static int mipi_dbi_smartbond_init(const struct device *dev) ret = pm_device_runtime_enable(dev); #else + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); /* Resme if either PM is not used at all or if PM without runtime is used. */ ret = mipi_dbi_smartbond_resume(dev); #endif From dbc9dd8d82a983f452f221b787fec867d7edcab9 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0931/1389] drivers: rtc: smartbond: Update RTC driver This commit should fix the followings: 1. When an alarm event is initialized, the driver should only consume the valid alarm fields, based on the given mask. Otherwise, the driver should use default valid subfield values. 2. Setting an alarm event should not return with error code if the timer and/or calendar counters have yet to be initialized, explicitly. Instead, a log warning should be issued. Signed-off-by: Ioannis Karachalios --- drivers/rtc/rtc_smartbond.c | 40 ++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc_smartbond.c b/drivers/rtc/rtc_smartbond.c index bfac974e874c04..7aa0d461d27338 100644 --- a/drivers/rtc/rtc_smartbond.c +++ b/drivers/rtc/rtc_smartbond.c @@ -16,6 +16,7 @@ #include #include #include +#include "rtc_utils.h" #include LOG_MODULE_REGISTER(rtc_smartbond, CONFIG_RTC_LOG_LEVEL); @@ -266,8 +267,7 @@ static int rtc_smartbond_get_time(const struct device *dev, struct rtc_time *tim } if (!data->is_rtc_configured) { - LOG_ERR("RTC is not initialized yet"); - return -ENODATA; + LOG_WRN("RTC is not initialized yet"); } k_mutex_lock(&data->lock, K_FOREVER); @@ -286,7 +286,10 @@ static int rtc_smartbond_get_time(const struct device *dev, struct rtc_time *tim #if defined(CONFIG_RTC_ALARM) BUILD_ASSERT(RTC_ALARMS_COUNT, "At least one alarm event should be supported"); -/* Define a valid calendar value as a zero sub-field is not valid for the alarm calendar value */ +/* + * Parse only the alarm fields indicated by the mask. Default valid values should be assigned + * to unused fields as it might happen that application has provided with invalid values. + */ static uint32_t alarm_calendar_to_bcd(const struct rtc_time *timeptr, uint16_t mask) { uint32_t rtc_calendar_alarm_reg = 0x0108; @@ -304,14 +307,28 @@ static uint32_t alarm_calendar_to_bcd(const struct rtc_time *timeptr, uint16_t m return rtc_calendar_alarm_reg; } -/* No need to parse the alarm mask as a zero sub-field is valid for the alarm time counter. */ -static inline uint32_t alarm_time_to_bcd(const struct rtc_time *timeptr) +/* + * Parse only the alarm fields indicated by the mask. Default valid values should be assigned + * to unused fields as it might happen that application has provided with invalid values. + */ +static inline uint32_t alarm_time_to_bcd(const struct rtc_time *timeptr, uint16_t mask) { uint32_t rtc_time_alarm_reg = 0; - RTC_TIME_ALARM_REG_SET_FIELD(S, rtc_time_alarm_reg, bin2bcd(timeptr->tm_sec)); /*[0, 59]*/ - RTC_TIME_ALARM_REG_SET_FIELD(M, rtc_time_alarm_reg, bin2bcd(timeptr->tm_min)); /*[0, 59]*/ - RTC_TIME_ALARM_REG_SET_FIELD(HR, rtc_time_alarm_reg, bin2bcd(timeptr->tm_hour)); /*[0, 23]*/ + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + /*[0, 59]*/ + RTC_TIME_ALARM_REG_SET_FIELD(S, rtc_time_alarm_reg, bin2bcd(timeptr->tm_sec)); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + /*[0, 59]*/ + RTC_TIME_ALARM_REG_SET_FIELD(M, rtc_time_alarm_reg, bin2bcd(timeptr->tm_min)); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + /*[0, 23]*/ + RTC_TIME_ALARM_REG_SET_FIELD(HR, rtc_time_alarm_reg, bin2bcd(timeptr->tm_hour)); + } return rtc_time_alarm_reg; } @@ -408,6 +425,11 @@ static int rtc_smartbond_alarm_set_time(const struct device *dev, uint16_t id, u return -EINVAL; } + if (!rtc_utils_validate_rtc_time(timeptr, mask)) { + LOG_ERR("Invalid alarm fields values"); + return -EINVAL; + } + if (!data->is_rtc_configured) { LOG_WRN("RTC is not initialized yet"); } @@ -425,7 +447,7 @@ static int rtc_smartbond_alarm_set_time(const struct device *dev, uint16_t id, u rtc_time_alarm_reg = RTC->RTC_TIME_ALARM_REG; rtc_calendar_alarm_reg = RTC->RTC_CALENDAR_ALARM_REG; - RTC->RTC_TIME_ALARM_REG = alarm_time_to_bcd(timeptr); + RTC->RTC_TIME_ALARM_REG = alarm_time_to_bcd(timeptr, mask); RTC->RTC_CALENDAR_ALARM_REG = alarm_calendar_to_bcd(timeptr, mask); rtc_status_reg = RTC->RTC_STATUS_REG; From 40b91b37164505e895b27c580d90179e3b6e5681 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0932/1389] tests: drivers: rtc: Add support for Smartbond Pro DevKit This commit should add support for the DA1469x Pro DevKit. Signed-off-by: Ioannis Karachalios --- .../rtc/rtc_api/boards/da1469x_dk_pro.conf | 2 ++ .../rtc/rtc_api/boards/da1469x_dk_pro.overlay | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.overlay diff --git a/tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.conf b/tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.conf new file mode 100644 index 00000000000000..c4d616ff25d689 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_ALARM=y +CONFIG_RTC_UPDATE=y diff --git a/tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.overlay b/tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.overlay new file mode 100644 index 00000000000000..4f795b02288add --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/da1469x_dk_pro.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; + +&rtc { + status = "okay"; +}; From aa6150b0b0cbb5ec1dec42e7210586362125760f Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0933/1389] drivers: rtc: stm32: fix error handling re-enable Write Protection when Init Mode errors. Signed-off-by: Abderrahmane Jarmouni --- drivers/rtc/rtc_ll_stm32.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index cdc975c4f1fe19..2cdda0158f3e87 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -392,9 +392,7 @@ static int rtc_stm32_init(const struct device *dev) static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr) { struct rtc_stm32_data *data = dev->data; - uint32_t real_year = timeptr->tm_year + TM_YEAR_REF; - int err = 0; if (real_year < RTC_YEAR_REF) { @@ -423,11 +421,8 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t ErrorStatus status = LL_RTC_EnterInitMode(RTC); if (status != SUCCESS) { -#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION - LL_PWR_DisableBkUpAccess(); -#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ - k_mutex_unlock(&data->lock); - return -EIO; + err = -EIO; + goto protect_unlock_return; } LL_RTC_DATE_SetYear(RTC, bin2bcd(real_year - RTC_YEAR_REF)); @@ -442,13 +437,13 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t LL_RTC_DATE_SetWeekDay(RTC, timeptr->tm_wday); } - LL_RTC_TIME_SetHour(RTC, bin2bcd(timeptr->tm_hour)); LL_RTC_TIME_SetMinute(RTC, bin2bcd(timeptr->tm_min)); LL_RTC_TIME_SetSecond(RTC, bin2bcd(timeptr->tm_sec)); LL_RTC_DisableInitMode(RTC); +protect_unlock_return: LL_RTC_EnableWriteProtection(RTC); #if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION From 1dacbf126e2aa7b8ef0466d922edda6d9da01a32 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0934/1389] mgmt/MCUmgr/img: Fix img_mgmt_get_unused_slot_area_id checks Remove image == -1 check that can not happen anymore. Signed-off-by: Dominik Ermel --- subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c | 5 +---- 1 file changed, 1 insertion(+), 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 a67db362366aab..c899e31a3fb9bd 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 @@ -226,14 +226,11 @@ static int img_mgmt_get_unused_slot_area_id(int slot) #endif } #elif CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER >= 2 -static int img_mgmt_get_unused_slot_area_id(int image) +static int img_mgmt_get_unused_slot_area_id(unsigned int image) { int area_id = -1; int slot = 0; - if (image == -1) { - image = 0; - } slot = img_mgmt_get_opposite_slot(img_mgmt_active_slot(image)); if (!img_mgmt_slot_in_use(slot)) { From bc45168097f8802e29488d28eebde811d30a2b2f Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0935/1389] dts: bindings: Add bindings for ov5640 camera Add bindings for ov5640 camera sensor Signed-off-by: Phi Bang Nguyen --- dts/bindings/video/ovti,ov5640.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 dts/bindings/video/ovti,ov5640.yaml diff --git a/dts/bindings/video/ovti,ov5640.yaml b/dts/bindings/video/ovti,ov5640.yaml new file mode 100644 index 00000000000000..eecb0e3d3192ba --- /dev/null +++ b/dts/bindings/video/ovti,ov5640.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: OV5640 CMOS video sensor + +compatible: "ovti,ov5640" + +include: i2c-device.yaml + +properties: + reset-gpios: + type: phandle-array + description: | + The RESETB pin is asserted to cause a hard reset. The sensor + receives this as an active-low signal. + powerdown-gpios: + type: phandle-array + description: | + The PWDN pin is asserted to disable the sensor. The sensor + receives this as an active-high signal. From 26786966262d83861653c33d758228783781f4dc Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0936/1389] drivers: video: Add ov5640 camera driver Add driver to support ov5640 camera sensor Signed-off-by: Phi Bang Nguyen --- drivers/video/CMakeLists.txt | 1 + drivers/video/Kconfig | 2 + drivers/video/Kconfig.ov5640 | 12 + drivers/video/ov5640.c | 698 +++++++++++++++++++++++++++++++++++ 4 files changed, 713 insertions(+) create mode 100644 drivers/video/Kconfig.ov5640 create mode 100644 drivers/video/ov5640.c diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 0b279de38134fe..b93c5bb2f66c67 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_VIDEO_MT9M114 mt9m114.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7725 ov7725.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV2640 ov2640.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_STM32_DCMI video_stm32_dcmi.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_OV5640 ov5640.c) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8a489cc4be6bd2..9f44944150fc9a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -43,4 +43,6 @@ source "drivers/video/Kconfig.ov2640" source "drivers/video/Kconfig.stm32_dcmi" +source "drivers/video/Kconfig.ov5640" + endif # VIDEO diff --git a/drivers/video/Kconfig.ov5640 b/drivers/video/Kconfig.ov5640 new file mode 100644 index 00000000000000..950079dd35507a --- /dev/null +++ b/drivers/video/Kconfig.ov5640 @@ -0,0 +1,12 @@ +# OV5640 + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_OV5640 + bool "OV5640 CMOS digital image sensor" + select I2C + depends on DT_HAS_OVTI_OV5640_ENABLED + default y + help + Enable driver for OV5640 CMOS digital image sensor device diff --git a/drivers/video/ov5640.c b/drivers/video/ov5640.c new file mode 100644 index 00000000000000..7c76c7b88c93c2 --- /dev/null +++ b/drivers/video/ov5640.c @@ -0,0 +1,698 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ovti_ov5640 + +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(ov5640); + +#include + +#define CHIP_ID_REG 0x300a +#define CHIP_ID_VAL 0x5640 + +#define SYS_CTRL0_REG 0x3008 +#define SYS_CTRL0_SW_PWDN 0x42 +#define SYS_CTRL0_SW_PWUP 0x02 +#define SYS_CTRL0_SW_RST 0x82 + +#define SYS_RESET00_REG 0x3000 +#define SYS_RESET02_REG 0x3002 +#define SYS_CLK_ENABLE00_REG 0x3004 +#define SYS_CLK_ENABLE02_REG 0x3006 +#define IO_MIPI_CTRL00_REG 0x300e +#define SYSTEM_CONTROL1_REG 0x302e +#define SCCB_SYS_CTRL1_REG 0x3103 +#define TIMING_TC_REG20_REG 0x3820 +#define TIMING_TC_REG21_REG 0x3821 +#define HZ5060_CTRL01_REG 0x3c01 +#define ISP_CTRL01_REG 0x5001 + +#define SC_PLL_CTRL0_REG 0x3034 +#define SC_PLL_CTRL1_REG 0x3035 +#define SC_PLL_CTRL2_REG 0x3036 +#define SC_PLL_CTRL3_REG 0x3037 +#define SYS_ROOT_DIV_REG 0x3108 +#define PCLK_PERIOD_REG 0x4837 + +#define AEC_CTRL00_REG 0x3a00 +#define AEC_CTRL0F_REG 0x3a0f +#define AEC_CTRL10_REG 0x3a10 +#define AEC_CTRL11_REG 0x3a11 +#define AEC_CTRL1B_REG 0x3a1b +#define AEC_CTRL1E_REG 0x3a1e +#define AEC_CTRL1F_REG 0x3a1f + +#define BLC_CTRL01_REG 0x4001 +#define BLC_CTRL04_REG 0x4004 +#define BLC_CTRL05_REG 0x4005 + +#define AWB_CTRL00_REG 0x5180 +#define AWB_CTRL01_REG 0x5181 +#define AWB_CTRL02_REG 0x5182 +#define AWB_CTRL03_REG 0x5183 +#define AWB_CTRL04_REG 0x5184 +#define AWB_CTRL05_REG 0x5185 +#define AWB_CTRL17_REG 0x5191 +#define AWB_CTRL18_REG 0x5192 +#define AWB_CTRL19_REG 0x5193 +#define AWB_CTRL20_REG 0x5194 +#define AWB_CTRL21_REG 0x5195 +#define AWB_CTRL22_REG 0x5196 +#define AWB_CTRL23_REG 0x5197 +#define AWB_CTRL30_REG 0x519e + +#define SDE_CTRL0_REG 0x5580 +#define SDE_CTRL3_REG 0x5583 +#define SDE_CTRL4_REG 0x5584 +#define SDE_CTRL9_REG 0x5589 +#define SDE_CTRL10_REG 0x558a +#define SDE_CTRL11_REG 0x558b + +#define DEFAULT_MIPI_CHANNEL 0 + +#define OV5640_RESOLUTION_PARAM_NUM 24 + +struct ov5640_config { + struct i2c_dt_spec i2c; + struct gpio_dt_spec reset_gpio; + struct gpio_dt_spec powerdown_gpio; +}; + +struct ov5640_data { + struct video_format fmt; +}; + +struct ov5640_reg { + uint16_t addr; + uint8_t val; +}; + +struct ov5640_mipi_clock_config { + uint8_t pllCtrl1; + uint8_t pllCtrl2; +}; + +struct ov5640_resolution_config { + uint16_t width; + uint16_t height; + const struct ov5640_reg *res_params; + const struct ov5640_mipi_clock_config mipi_pclk; +}; + +static const struct ov5640_reg ov5640InitParams[] = { + /* Power down */ + {SYS_CTRL0_REG, SYS_CTRL0_SW_PWDN}, + + /* System setting. */ + {SCCB_SYS_CTRL1_REG, 0x13}, + {SCCB_SYS_CTRL1_REG, 0x03}, + {SYS_RESET00_REG, 0x00}, + {SYS_CLK_ENABLE00_REG, 0xff}, + {SYS_RESET02_REG, 0x1c}, + {SYS_CLK_ENABLE02_REG, 0xc3}, + {SYSTEM_CONTROL1_REG, 0x08}, + {0x3618, 0x00}, + {0x3612, 0x29}, + {0x3708, 0x64}, + {0x3709, 0x52}, + {0x370c, 0x03}, + {TIMING_TC_REG20_REG, 0x41}, + {TIMING_TC_REG21_REG, 0x07}, + {0x3630, 0x36}, + {0x3631, 0x0e}, + {0x3632, 0xe2}, + {0x3633, 0x12}, + {0x3621, 0xe0}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3905, 0x02}, + {0x3906, 0x10}, + {0x3901, 0x0a}, + {0x3731, 0x12}, + {0x3600, 0x08}, + {0x3601, 0x33}, + {0x302d, 0x60}, + {0x3620, 0x52}, + {0x371b, 0x20}, + {0x471c, 0x50}, + {0x3a13, 0x43}, + {0x3a18, 0x00}, + {0x3a19, 0x7c}, + {0x3635, 0x13}, + {0x3636, 0x03}, + {0x3634, 0x40}, + {0x3622, 0x01}, + {HZ5060_CTRL01_REG, 0x00}, + {AEC_CTRL00_REG, 0x58}, + {BLC_CTRL01_REG, 0x02}, + {BLC_CTRL04_REG, 0x02}, + {BLC_CTRL05_REG, 0x1a}, + {ISP_CTRL01_REG, 0xa3}, + + /* AEC */ + {AEC_CTRL0F_REG, 0x30}, + {AEC_CTRL10_REG, 0x28}, + {AEC_CTRL1B_REG, 0x30}, + {AEC_CTRL1E_REG, 0x26}, + {AEC_CTRL11_REG, 0x60}, + {AEC_CTRL1F_REG, 0x14}, + + /* AWB */ + {AWB_CTRL00_REG, 0xff}, + {AWB_CTRL01_REG, 0xf2}, + {AWB_CTRL02_REG, 0x00}, + {AWB_CTRL03_REG, 0x14}, + {AWB_CTRL04_REG, 0x25}, + {AWB_CTRL05_REG, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x88}, + {0x518a, 0x54}, + {0x518b, 0xee}, + {0x518c, 0xb2}, + {0x518d, 0x50}, + {0x518e, 0x34}, + {0x518f, 0x6b}, + {0x5190, 0x46}, + {AWB_CTRL17_REG, 0xf8}, + {AWB_CTRL18_REG, 0x04}, + {AWB_CTRL19_REG, 0x70}, + {AWB_CTRL20_REG, 0xf0}, + {AWB_CTRL21_REG, 0xf0}, + {AWB_CTRL22_REG, 0x03}, + {AWB_CTRL23_REG, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x6c}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x09}, + {0x519d, 0x2b}, + {AWB_CTRL30_REG, 0x38}, + + /* Color Matrix */ + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, + + /* Sharp */ + {0x5300, 0x08}, + {0x5301, 0x30}, + {0x5302, 0x10}, + {0x5303, 0x00}, + {0x5304, 0x08}, + {0x5305, 0x30}, + {0x5306, 0x08}, + {0x5307, 0x16}, + {0x5309, 0x08}, + {0x530a, 0x30}, + {0x530b, 0x04}, + {0x530c, 0x06}, + + /* Gamma */ + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d}, + + /* UV adjust. */ + {SDE_CTRL0_REG, 0x02}, + {SDE_CTRL3_REG, 0x40}, + {SDE_CTRL4_REG, 0x10}, + {SDE_CTRL9_REG, 0x10}, + {SDE_CTRL10_REG, 0x00}, + {SDE_CTRL11_REG, 0xf8}, + + /* Lens correction. */ + {0x5800, 0x23}, + {0x5801, 0x14}, + {0x5802, 0x0f}, + {0x5803, 0x0f}, + {0x5804, 0x12}, + {0x5805, 0x26}, + {0x5806, 0x0c}, + {0x5807, 0x08}, + {0x5808, 0x05}, + {0x5809, 0x05}, + {0x580a, 0x08}, + {0x580b, 0x0d}, + {0x580c, 0x08}, + {0x580d, 0x03}, + {0x580e, 0x00}, + {0x580f, 0x00}, + {0x5810, 0x03}, + {0x5811, 0x09}, + {0x5812, 0x07}, + {0x5813, 0x03}, + {0x5814, 0x00}, + {0x5815, 0x01}, + {0x5816, 0x03}, + {0x5817, 0x08}, + {0x5818, 0x0d}, + {0x5819, 0x08}, + {0x581a, 0x05}, + {0x581b, 0x06}, + {0x581c, 0x08}, + {0x581d, 0x0e}, + {0x581e, 0x29}, + {0x581f, 0x17}, + {0x5820, 0x11}, + {0x5821, 0x11}, + {0x5822, 0x15}, + {0x5823, 0x28}, + {0x5824, 0x46}, + {0x5825, 0x26}, + {0x5826, 0x08}, + {0x5827, 0x26}, + {0x5828, 0x64}, + {0x5829, 0x26}, + {0x582a, 0x24}, + {0x582b, 0x22}, + {0x582c, 0x24}, + {0x582d, 0x24}, + {0x582e, 0x06}, + {0x582f, 0x22}, + {0x5830, 0x40}, + {0x5831, 0x42}, + {0x5832, 0x24}, + {0x5833, 0x26}, + {0x5834, 0x24}, + {0x5835, 0x22}, + {0x5836, 0x22}, + {0x5837, 0x26}, + {0x5838, 0x44}, + {0x5839, 0x24}, + {0x583a, 0x26}, + {0x583b, 0x28}, + {0x583c, 0x42}, + {0x583d, 0xce}, + {0x5000, 0xa7}, +}; + +static const struct ov5640_reg ov5640_low_res_params[] = { + {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x04}, {0x3804, 0x0a}, + {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9b}, {0x3808, 0x02}, {0x3809, 0x80}, + {0x380a, 0x01}, {0x380b, 0xe0}, {0x380c, 0x07}, {0x380d, 0x68}, {0x380e, 0x03}, + {0x380f, 0xd8}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x06}, + {0x3814, 0x31}, {0x3815, 0x31}, {0x3824, 0x02}, {0x460c, 0x22}}; + +static const struct ov5640_reg ov5640_720p_res_params[] = { + {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0xfa}, {0x3804, 0x0a}, + {0x3805, 0x3f}, {0x3806, 0x06}, {0x3807, 0xa9}, {0x3808, 0x05}, {0x3809, 0x00}, + {0x380a, 0x02}, {0x380b, 0xd0}, {0x380c, 0x07}, {0x380d, 0x64}, {0x380e, 0x02}, + {0x380f, 0xe4}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, + {0x3814, 0x31}, {0x3815, 0x31}, {0x3824, 0x04}, {0x460c, 0x20}}; + +static const struct ov5640_resolution_config resolutionParams[] = { + {.width = 640, + .height = 480, + .res_params = ov5640_low_res_params, + .mipi_pclk = { + .pllCtrl1 = 0x14, + .pllCtrl2 = 0x38, + }}, + {.width = 1280, + .height = 720, + .res_params = ov5640_720p_res_params, + .mipi_pclk = { + .pllCtrl1 = 0x21, + .pllCtrl2 = 0x54, + }}, +}; + +#define OV5640_VIDEO_FORMAT_CAP(width, height, format) \ + { \ + .pixelformat = (format), .width_min = (width), .width_max = (width), \ + .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \ + } + +static const struct video_format_cap fmts[] = { + OV5640_VIDEO_FORMAT_CAP(1280, 720, VIDEO_PIX_FMT_RGB565), + OV5640_VIDEO_FORMAT_CAP(1280, 720, VIDEO_PIX_FMT_YUYV), + OV5640_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), + OV5640_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), + {0}}; + +static int ov5640_read_reg(const struct i2c_dt_spec *spec, const uint16_t addr, void *val, + const uint8_t val_size) +{ + int ret; + struct i2c_msg msg[2]; + uint8_t addr_buf[2]; + + if (val_size > 4) { + return -ENOTSUP; + } + + addr_buf[1] = addr & 0xFF; + addr_buf[0] = addr >> 8; + msg[0].buf = addr_buf; + msg[0].len = 2U; + msg[0].flags = I2C_MSG_WRITE; + + msg[1].buf = (uint8_t *)val; + msg[1].len = val_size; + msg[1].flags = I2C_MSG_READ | I2C_MSG_STOP | I2C_MSG_RESTART; + + ret = i2c_transfer_dt(spec, msg, 2); + if (ret) { + return ret; + } + + switch (val_size) { + case 4: + *(uint32_t *)val = sys_be32_to_cpu(*(uint32_t *)val); + break; + case 2: + *(uint16_t *)val = sys_be16_to_cpu(*(uint16_t *)val); + break; + case 1: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int ov5640_write_reg(const struct i2c_dt_spec *spec, const uint16_t addr, const uint8_t val) +{ + uint8_t addr_buf[2]; + struct i2c_msg msg[2]; + + addr_buf[1] = addr & 0xFF; + addr_buf[0] = addr >> 8; + msg[0].buf = addr_buf; + msg[0].len = 2U; + msg[0].flags = I2C_MSG_WRITE; + + msg[1].buf = (uint8_t *)&val; + msg[1].len = 1; + msg[1].flags = I2C_MSG_WRITE | I2C_MSG_STOP; + + return i2c_transfer_dt(spec, msg, 2); +} + +static int ov5640_modify_reg(const struct i2c_dt_spec *spec, const uint16_t addr, + const uint8_t mask, const uint8_t val) +{ + uint8_t regVal = 0; + int ret = ov5640_read_reg(spec, addr, ®Val, sizeof(regVal)); + + if (ret) { + return ret; + } + + return ov5640_write_reg(spec, addr, (regVal & ~mask) | (val & mask)); +} + +static int ov5640_write_multi_regs(const struct i2c_dt_spec *spec, const struct ov5640_reg *regs, + const uint32_t num_regs) +{ + int ret; + + for (int i = 0; i < num_regs; i++) { + ret = ov5640_write_reg(spec, regs[i].addr, regs[i].val); + if (ret) { + return ret; + } + } + + return 0; +} + +static int ov5640_set_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct ov5640_data *drv_data = dev->data; + const struct ov5640_config *cfg = dev->config; + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(fmts); ++i) { + if (fmt->pixelformat == fmts[i].pixelformat && fmt->width >= fmts[i].width_min && + fmt->width <= fmts[i].width_max && fmt->height >= fmts[i].height_min && + fmt->height <= fmts[i].height_max) { + break; + } + } + + if (i == ARRAY_SIZE(fmts)) { + LOG_ERR("Unsupported pixel format or resolution"); + return -ENOTSUP; + } + + if (!memcmp(&drv_data->fmt, fmt, sizeof(drv_data->fmt))) { + return 0; + } + + drv_data->fmt = *fmt; + + /* Set resolution parameters */ + for (i = 0; i < ARRAY_SIZE(resolutionParams); i++) { + if (fmt->width == resolutionParams[i].width && + fmt->height == resolutionParams[i].height) { + ret = ov5640_write_multi_regs(&cfg->i2c, resolutionParams[i].res_params, + OV5640_RESOLUTION_PARAM_NUM); + if (ret) { + LOG_ERR("Unable to set resolution parameters"); + return ret; + } + break; + } + } + + /* Set pixel format, default to VIDEO_PIX_FMT_RGB565 */ + struct ov5640_reg fmt_params[2] = { + {0x4300, 0x6f}, + {0x501f, 0x01}, + }; + + if (fmt->pixelformat == VIDEO_PIX_FMT_YUYV) { + fmt_params[0].val = 0x3f; + fmt_params[1].val = 0x00; + } + + ret = ov5640_write_multi_regs(&cfg->i2c, fmt_params, ARRAY_SIZE(fmt_params)); + if (ret) { + LOG_ERR("Unable to set pixel format"); + return ret; + } + + /* Configure MIPI pixel clock */ + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL0_REG, 0x0f, 0x08); + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL1_REG, 0xff, + resolutionParams[i].mipi_pclk.pllCtrl1); + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL2_REG, 0xff, + resolutionParams[i].mipi_pclk.pllCtrl2); + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL3_REG, 0x1f, 0x13); + ret |= ov5640_modify_reg(&cfg->i2c, SYS_ROOT_DIV_REG, 0x3f, 0x01); + ret |= ov5640_write_reg(&cfg->i2c, PCLK_PERIOD_REG, 0x0a); + if (ret) { + LOG_ERR("Unable to configure MIPI pixel clock"); + return ret; + } + + return 0; +} + +static int ov5640_get_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct ov5640_data *drv_data = dev->data; + + *fmt = drv_data->fmt; + + return 0; +} + +static int ov5640_get_caps(const struct device *dev, enum video_endpoint_id ep, + struct video_caps *caps) +{ + caps->format_caps = fmts; + return 0; +} + +static int ov5640_stream_start(const struct device *dev) +{ + const struct ov5640_config *cfg = dev->config; + /* Power up MIPI PHY HS Tx & LP Rx in 2 data lanes mode */ + int ret = ov5640_write_reg(&cfg->i2c, IO_MIPI_CTRL00_REG, 0x45); + + if (ret) { + LOG_ERR("Unable to power up MIPI PHY"); + return ret; + } + return ov5640_write_reg(&cfg->i2c, SYS_CTRL0_REG, SYS_CTRL0_SW_PWUP); +} + +static int ov5640_stream_stop(const struct device *dev) +{ + const struct ov5640_config *cfg = dev->config; + /* Power down MIPI PHY HS Tx & LP Rx */ + int ret = ov5640_write_reg(&cfg->i2c, IO_MIPI_CTRL00_REG, 0x40); + + if (ret) { + LOG_ERR("Unable to power down MIPI PHY"); + return ret; + } + return ov5640_write_reg(&cfg->i2c, SYS_CTRL0_REG, SYS_CTRL0_SW_PWDN); +} + +static const struct video_driver_api ov5640_driver_api = { + .set_format = ov5640_set_fmt, + .get_format = ov5640_get_fmt, + .get_caps = ov5640_get_caps, + .stream_start = ov5640_stream_start, + .stream_stop = ov5640_stream_stop, +}; + +static int ov5640_init(const struct device *dev) +{ + const struct ov5640_config *cfg = dev->config; + struct video_format fmt; + uint16_t chip_id; + int ret; + + if (!device_is_ready(cfg->i2c.bus)) { + LOG_ERR("Bus device is not ready"); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&cfg->reset_gpio)) { + LOG_ERR("%s: device %s is not ready", dev->name, cfg->reset_gpio.port->name); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&cfg->powerdown_gpio)) { + LOG_ERR("%s: device %s is not ready", dev->name, cfg->powerdown_gpio.port->name); + return -ENODEV; + } + + /* Power up sequence */ + if (cfg->powerdown_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&cfg->powerdown_gpio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + if (cfg->reset_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + k_sleep(K_MSEC(5)); + + if (cfg->powerdown_gpio.port != NULL) { + gpio_pin_set_dt(&cfg->powerdown_gpio, 0); + } + + k_sleep(K_MSEC(1)); + + if (cfg->reset_gpio.port != NULL) { + gpio_pin_set_dt(&cfg->reset_gpio, 0); + } + + k_sleep(K_MSEC(20)); + + /* Software reset */ + ret = ov5640_write_reg(&cfg->i2c, SYS_CTRL0_REG, SYS_CTRL0_SW_RST); + if (ret) { + LOG_ERR("Unable to perform software reset"); + return -EIO; + } + + k_sleep(K_MSEC(5)); + + /* Initialize register values */ + ret = ov5640_write_multi_regs(&cfg->i2c, ov5640InitParams, ARRAY_SIZE(ov5640InitParams)); + if (ret) { + LOG_ERR("Unable to initialize the sensor"); + return -EIO; + } + + /* Set virtual channel */ + ret = ov5640_modify_reg(&cfg->i2c, 0x4814, 3U << 6, (uint8_t)(DEFAULT_MIPI_CHANNEL) << 6); + if (ret) { + LOG_ERR("Unable to set virtual channel"); + return -EIO; + } + + /* Check sensor chip id */ + ret = ov5640_read_reg(&cfg->i2c, CHIP_ID_REG, &chip_id, sizeof(chip_id)); + if (ret) { + LOG_ERR("Unable to read sensor chip ID, ret = %d", ret); + return -ENODEV; + } + + if (chip_id != CHIP_ID_VAL) { + LOG_ERR("Wrong chip ID: %04x (expected %04x)", chip_id, CHIP_ID_VAL); + return -ENODEV; + } + + /* Set default format to 720p RGB565 */ + fmt.pixelformat = VIDEO_PIX_FMT_RGB565; + fmt.width = 1280; + fmt.height = 720; + fmt.pitch = fmt.width * 2; + ret = ov5640_set_fmt(dev, VIDEO_EP_OUT, &fmt); + if (ret) { + LOG_ERR("Unable to configure default format"); + return -EIO; + } + + return 0; +} + +#define OV5640_INIT(n) \ + static struct ov5640_data ov5640_data_##n; \ + \ + static const struct ov5640_config ov5640_cfg_##n = { \ + .i2c = I2C_DT_SPEC_INST_GET(n), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \ + .powerdown_gpio = GPIO_DT_SPEC_INST_GET_OR(n, powerdown_gpios, {0}), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &ov5640_init, NULL, &ov5640_data_##n, &ov5640_cfg_##n, \ + POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov5640_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(OV5640_INIT) From 28758f9199c4bc5946cd04248e6442ce343a105d Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0937/1389] tests: drivers: build_all: video: Add entry for ov5640 Add entry for ov5640 and add mimxrt1170_evk to the test platforms Signed-off-by: Phi Bang Nguyen --- tests/drivers/build_all/video/app.overlay | 7 +++++++ tests/drivers/build_all/video/testcase.yaml | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/drivers/build_all/video/app.overlay b/tests/drivers/build_all/video/app.overlay index a38cfdd0e133c6..e06d2940817a9c 100644 --- a/tests/drivers/build_all/video/app.overlay +++ b/tests/drivers/build_all/video/app.overlay @@ -47,6 +47,13 @@ reg = <0x2>; reset-gpios = <&test_gpio 0 0>; }; + + test_i2c_ov5640: ov5640@3 { + compatible = "ovti,ov5640"; + reg = <0x3>; + reset-gpios = <&test_gpio 0 0>; + powerdown-gpios = <&test_gpio 1 0>; + }; }; }; }; diff --git a/tests/drivers/build_all/video/testcase.yaml b/tests/drivers/build_all/video/testcase.yaml index 08dd430da73145..2acb801b9c6438 100644 --- a/tests/drivers/build_all/video/testcase.yaml +++ b/tests/drivers/build_all/video/testcase.yaml @@ -13,4 +13,6 @@ tests: - gpio - i2c drivers.video.mcux_csi.build: - platform_allow: mimxrt1064_evk + platform_allow: + - mimxrt1064_evk + - mimxrt1170_evk/mimxrt1176/cm7 From 17fb23bd44c8d0234513a088cfa153e960c3fb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0938/1389] drivers: udc_dwc2: Add missing register bit defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing GINTSTS, GRXSTSR and DEPCTL bit defines based on nRF54H20 register map. Signed-off-by: Tomasz Moń --- drivers/usb/common/usb_dwc2_hw.h | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/usb/common/usb_dwc2_hw.h b/drivers/usb/common/usb_dwc2_hw.h index f216a423968d57..b137a526ede0f1 100644 --- a/drivers/usb/common/usb_dwc2_hw.h +++ b/drivers/usb/common/usb_dwc2_hw.h @@ -190,32 +190,81 @@ USB_DWC2_SET_FIELD_DEFINE(grstctl_txfnum, GRSTCTL_TXFNUM) #define USB_DWC2_GINTMSK 0x0018UL #define USB_DWC2_GINTSTS_WKUPINT_POS 31UL #define USB_DWC2_GINTSTS_WKUPINT BIT(USB_DWC2_GINTSTS_WKUPINT_POS) +#define USB_DWC2_GINTSTS_SESSREQINT_POS 30UL +#define USB_DWC2_GINTSTS_SESSREQINT BIT(USB_DWC2_GINTSTS_SESSREQINT_POS) +#define USB_DWC2_GINTSTS_DISCONNINT_POS 29UL +#define USB_DWC2_GINTSTS_DISCONNINT BIT(USB_DWC2_GINTSTS_DISCONNINT_POS) +#define USB_DWC2_GINTSTS_CONIDSTSCHNG_POS 28UL +#define USB_DWC2_GINTSTS_CONIDSTSCHNG BIT(USB_DWC2_GINTSTS_CONIDSTSCHNG_POS) +#define USB_DWC2_GINTSTS_LPM_INT_POS 27UL +#define USB_DWC2_GINTSTS_LPM_INT BIT(USB_DWC2_GINTSTS_LPM_INT_POS) +#define USB_DWC2_GINTSTS_HCHINT_POS 25UL +#define USB_DWC2_GINTSTS_HCHINT BIT(USB_DWC2_GINTSTS_HCHINT_POS) +#define USB_DWC2_GINTSTS_PRTINT_POS 24UL +#define USB_DWC2_GINTSTS_PRTINT BIT(USB_DWC2_GINTSTS_PRTINT_POS) +#define USB_DWC2_GINTSTS_RESETDET_POS 23UL +#define USB_DWC2_GINTSTS_RESETDET BIT(USB_DWC2_GINTSTS_RESETDET_POS) +#define USB_DWC2_GINTSTS_FETSUSP_POS 22UL +#define USB_DWC2_GINTSTS_FETSUSP BIT(USB_DWC2_GINTSTS_FETSUSP_POS) +#define USB_DWC2_GINTSTS_INCOMPIP_POS 21UL +#define USB_DWC2_GINTSTS_INCOMPIP BIT(USB_DWC2_GINTSTS_INCOMPIP_POS) +#define USB_DWC2_GINTSTS_INCOMPISOIN_POS 20UL +#define USB_DWC2_GINTSTS_INCOMPISOIN BIT(USB_DWC2_GINTSTS_INCOMPISOIN_POS) #define USB_DWC2_GINTSTS_OEPINT_POS 19UL #define USB_DWC2_GINTSTS_OEPINT BIT(USB_DWC2_GINTSTS_OEPINT_POS) #define USB_DWC2_GINTSTS_IEPINT_POS 18UL #define USB_DWC2_GINTSTS_IEPINT BIT(USB_DWC2_GINTSTS_IEPINT_POS) +#define USB_DWC2_GINTSTS_EPMIS_POS 17UL +#define USB_DWC2_GINTSTS_EPMIS BIT(USB_DWC2_GINTSTS_EPMIS_POS) +#define USB_DWC2_GINTSTS_RSTRDONEINT_POS 16UL +#define USB_DWC2_GINTSTS_RSTRDONEINT BIT(USB_DWC2_GINTSTS_RSTRDONEINT_POS) +#define USB_DWC2_GINTSTS_EOPF_POS 15UL +#define USB_DWC2_GINTSTS_EOPF BIT(USB_DWC2_GINTSTS_EOPF_POS) +#define USB_DWC2_GINTSTS_ISOOUTDROP_POS 14UL +#define USB_DWC2_GINTSTS_ISOOUTDROP BIT(USB_DWC2_GINTSTS_ISOOUTDROP_POS) #define USB_DWC2_GINTSTS_ENUMDONE_POS 13UL #define USB_DWC2_GINTSTS_ENUMDONE BIT(USB_DWC2_GINTSTS_ENUMDONE_POS) #define USB_DWC2_GINTSTS_USBRST_POS 12UL #define USB_DWC2_GINTSTS_USBRST BIT(USB_DWC2_GINTSTS_USBRST_POS) #define USB_DWC2_GINTSTS_USBSUSP_POS 11UL #define USB_DWC2_GINTSTS_USBSUSP BIT(USB_DWC2_GINTSTS_USBSUSP_POS) +#define USB_DWC2_GINTSTS_ERLYSUSP_POS 10UL +#define USB_DWC2_GINTSTS_ERLYSUSP BIT(USB_DWC2_GINTSTS_ERLYSUSP_POS) +#define USB_DWC2_GINTSTS_GOUTNAKEFF_POS 7UL +#define USB_DWC2_GINTSTS_GOUTNAKEFF BIT(USB_DWC2_GINTSTS_GOUTNAKEFF_POS) +#define USB_DWC2_GINTSTS_GINNAKEFF_POS 6UL +#define USB_DWC2_GINTSTS_GINNAKEFF BIT(USB_DWC2_GINTSTS_GINNAKEFF_POS) +#define USB_DWC2_GINTSTS_NPTXFEMP_POS 5UL +#define USB_DWC2_GINTSTS_NPTXFEMP BIT(USB_DWC2_GINTSTS_NPTXFEMP_POS) #define USB_DWC2_GINTSTS_RXFLVL_POS 4UL #define USB_DWC2_GINTSTS_RXFLVL BIT(USB_DWC2_GINTSTS_RXFLVL_POS) #define USB_DWC2_GINTSTS_SOF_POS 3UL #define USB_DWC2_GINTSTS_SOF BIT(USB_DWC2_GINTSTS_SOF_POS) #define USB_DWC2_GINTSTS_OTGINT_POS 2UL #define USB_DWC2_GINTSTS_OTGINT BIT(USB_DWC2_GINTSTS_OTGINT_POS) +#define USB_DWC2_GINTSTS_MODEMIS_POS 1UL +#define USB_DWC2_GINTSTS_MODEMIS BIT(USB_DWC2_GINTSTS_MODEMIS_POS) +#define USB_DWC2_GINTSTS_CURMOD_POS 0UL +#define USB_DWC2_GINTSTS_CURMOD BIT(USB_DWC2_GINTSTS_CURMOD_POS) /* Status read and pop registers */ #define USB_DWC2_GRXSTSR 0x001CUL #define USB_DWC2_GRXSTSP 0x0020UL +#define USB_DWC2_GRXSTSR_FN_POS 21UL +#define USB_DWC2_GRXSTSR_FN_MASK (0xFUL << USB_DWC2_GRXSTSR_FN_POS) #define USB_DWC2_GRXSTSR_PKTSTS_POS 17UL #define USB_DWC2_GRXSTSR_PKTSTS_MASK (0xFUL << USB_DWC2_GRXSTSR_PKTSTS_POS) +#define USB_DWC2_GRXSTSR_PKTSTS_GLOBAL_OUT_NAK 1 #define USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA 2 #define USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA_DONE 3 #define USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE 4 #define USB_DWC2_GRXSTSR_PKTSTS_SETUP 6 +#define USB_DWC2_GRXSTSR_DPID_POS 15UL +#define USB_DWC2_GRXSTSR_DPID_MASK (0x3UL << USB_DWC2_GRXSTSR_DPID_POS) +#define USB_DWC2_GRXSTSR_DPID_DATA0 0 +#define USB_DWC2_GRXSTSR_DPID_DATA2 1 +#define USB_DWC2_GRXSTSR_DPID_DATA1 2 +#define USB_DWC2_GRXSTSR_DPID_MDATA 3 #define USB_DWC2_GRXSTSR_BCNT_POS 4UL #define USB_DWC2_GRXSTSR_BCNT_MASK (0x000007FFUL << USB_DWC2_GRXSTSR_BCNT_POS) #define USB_DWC2_GRXSTSR_EPNUM_POS 0UL @@ -223,6 +272,7 @@ USB_DWC2_SET_FIELD_DEFINE(grstctl_txfnum, GRSTCTL_TXFNUM) #define USB_DWC2_GRXSTSR_CHNUM_POS 0UL #define USB_DWC2_GRXSTSR_CHNUM_MASK 0x0000000FUL +USB_DWC2_GET_FIELD_DEFINE(grxstsp_fn, GRXSTSR_FN) USB_DWC2_GET_FIELD_DEFINE(grxstsp_pktsts, GRXSTSR_PKTSTS) USB_DWC2_GET_FIELD_DEFINE(grxstsp_bcnt, GRXSTSR_BCNT) USB_DWC2_GET_FIELD_DEFINE(grxstsp_epnum, GRXSTSR_EPNUM) @@ -456,6 +506,8 @@ USB_DWC2_GET_FIELD_DEFINE(dsts_enumspd, DSTS_ENUMSPD) #define USB_DWC2_DEPCTL_EPENA BIT(USB_DWC2_DEPCTL_EPENA_POS) #define USB_DWC2_DEPCTL_EPDIS_POS 30UL #define USB_DWC2_DEPCTL_EPDIS BIT(USB_DWC2_DEPCTL_EPDIS_POS) +#define USB_DWC2_DEPCTL_SETD1PID_POS 29UL +#define USB_DWC2_DEPCTL_SETD1PID BIT(USB_DWC2_DEPCTL_SETD1PID_POS) #define USB_DWC2_DEPCTL_SETD0PID_POS 28UL #define USB_DWC2_DEPCTL_SETD0PID BIT(USB_DWC2_DEPCTL_SETD0PID_POS) #define USB_DWC2_DEPCTL_SNAK_POS 27UL @@ -472,6 +524,10 @@ USB_DWC2_GET_FIELD_DEFINE(dsts_enumspd, DSTS_ENUMSPD) #define USB_DWC2_DEPCTL_EPTYPE_BULK 2 #define USB_DWC2_DEPCTL_EPTYPE_ISO 1 #define USB_DWC2_DEPCTL_EPTYPE_CONTROL 0 +#define USB_DWC2_DEPCTL_NAKSTS_POS 17UL +#define USB_DWC2_DEPCTL_NAKSTS BIT(USB_DWC2_DEPCTL_NAKSTS_POS) +#define USB_DWC2_DEPCTL_DPID_POS 16UL +#define USB_DWC2_DEPCTL_DPID BIT(USB_DWC2_DEPCTL_DPID_POS) #define USB_DWC2_DEPCTL_USBACTEP_POS 15UL #define USB_DWC2_DEPCTL_USBACTEP BIT(USB_DWC2_DEPCTL_USBACTEP_POS) #define USB_DWC2_DEPCTL0_MPS_POS 0UL From bf9cb357f4b80069d5e2642dc76a34afebaa6c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0939/1389] drivers: udc_dwc2: Process SETUP stage when allowed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DWC2 programming guide mentions that SETUP can only be processed by application after DOEPINTn.SETUP interrupt. Not respecting this requirement makes setting Global OUT NAK hang while waiting for GOUTNAKEFF interrupt until the host starts next control transfer. Global OUT NAK is necessary if the application ever wants to properly cancel any ongoing transfer. Change the processing to comply with the programming guide. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 54 +++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index e18aa6b96f6e7a..b344ff0d7d632d 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -349,7 +349,7 @@ static inline int dwc2_read_fifo(const struct device *dev, const uint8_t ep, struct net_buf *const buf, const size_t size) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); - size_t len = MIN(size, net_buf_tailroom(buf)); + size_t len = buf ? MIN(size, net_buf_tailroom(buf)) : 0; const size_t d = sizeof(uint32_t); /* FIFO access is always in 32-bit words */ @@ -389,7 +389,7 @@ static void dwc2_prep_rx(const struct device *dev, doeptsiz = (1 << USB_DWC2_DOEPTSIZ0_PKTCNT_POS) | cfg->mps; if (cfg->addr == USB_CONTROL_EP_OUT) { - doeptsiz |= (1 << USB_DWC2_DOEPTSIZ0_SUPCNT_POS); + doeptsiz |= (3 << USB_DWC2_DOEPTSIZ0_SUPCNT_POS); } sys_write32(doeptsiz, doeptsiz_reg); @@ -650,7 +650,7 @@ static void dwc2_on_bus_reset(const struct device *dev) } } - sys_write32(0UL, (mem_addr_t)&base->doepmsk); + sys_write32(USB_DWC2_DOEPINT_SETUP, (mem_addr_t)&base->doepmsk); sys_set_bits((mem_addr_t)&base->gintmsk, USB_DWC2_GINTSTS_RXFLVL); sys_set_bits((mem_addr_t)&base->diepmsk, USB_DWC2_DIEPINT_XFERCOMPL); @@ -668,13 +668,19 @@ static void dwc2_handle_enumdone(const struct device *dev) priv->enumspd = usb_dwc2_get_dsts_enumspd(dsts); } -static inline int dwc2_read_fifo_setup(const struct device *dev) +static inline int dwc2_read_fifo_setup(const struct device *dev, uint8_t ep, + const size_t size) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); struct udc_dwc2_data *const priv = udc_get_private(dev); + size_t offset; /* FIFO access is always in 32-bit words */ + if (size != 8) { + LOG_ERR("%d bytes SETUP", size); + } + /* * We store the setup packet temporarily in the driver's private data * because there is always a race risk after the status stage OUT @@ -682,8 +688,16 @@ static inline int dwc2_read_fifo_setup(const struct device *dev) * bottom-half processing because the events arrive in a queue and * there will be a next net_buf for the setup packet. */ - sys_put_le32(sys_read32(UDC_DWC2_EP_FIFO(base, 0)), priv->setup); - sys_put_le32(sys_read32(UDC_DWC2_EP_FIFO(base, 0)), &priv->setup[4]); + for (offset = 0; offset < MIN(size, 8); offset += 4) { + sys_put_le32(sys_read32(UDC_DWC2_EP_FIFO(base, ep)), + &priv->setup[offset]); + } + + /* On protocol error simply discard extra data */ + while (offset < size) { + sys_read32(UDC_DWC2_EP_FIFO(base, ep)); + offset += 4; + } return 0; } @@ -706,26 +720,23 @@ static inline void dwc2_handle_rxflvl(const struct device *dev) switch (pktsts) { case USB_DWC2_GRXSTSR_PKTSTS_SETUP: - evt.type = DWC2_DRV_EVT_SETUP; - - __ASSERT(evt.bcnt == 8, "Incorrect setup packet length"); - dwc2_read_fifo_setup(dev); - - k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + dwc2_read_fifo_setup(dev, evt.ep, evt.bcnt); break; case USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA: evt.type = DWC2_DRV_EVT_DOUT; ep_cfg = udc_get_ep_cfg(dev, evt.ep); buf = udc_buf_peek(dev, ep_cfg->addr); + + /* RxFIFO data must be retrieved even when buf is NULL */ + dwc2_read_fifo(dev, evt.ep, buf, evt.bcnt); + if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", ep_cfg->addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); break; } - dwc2_read_fifo(dev, USB_CONTROL_EP_OUT, buf, evt.bcnt); - if (net_buf_tailroom(buf) && evt.bcnt == ep_cfg->mps) { dwc2_prep_rx(dev, ep_cfg, 0); } else { @@ -734,9 +745,11 @@ static inline void dwc2_handle_rxflvl(const struct device *dev) break; case USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA_DONE: - case USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE: LOG_DBG("RX pktsts DONE"); break; + case USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE: + LOG_DBG("SETUP pktsts DONE"); + break; default: break; } @@ -813,7 +826,6 @@ static inline void dwc2_handle_oepint(const struct device *dev) doepmsk = sys_read32((mem_addr_t)&base->doepmsk); daint = sys_read32((mem_addr_t)&base->daint); - /* No OUT interrupt expected in FIFO mode, just clear interrupt */ for (uint8_t n = 0U; n < n_max; n++) { mem_addr_t doepint_reg = (mem_addr_t)&base->out_ep[n].doepint; uint32_t doepint; @@ -826,6 +838,16 @@ static inline void dwc2_handle_oepint(const struct device *dev) sys_write32(status, doepint_reg); LOG_DBG("ep 0x%02x interrupt status: 0x%x", n, status); + + if (status & USB_DWC2_DOEPINT_SETUP) { + struct dwc2_drv_event evt = { + .type = DWC2_DRV_EVT_SETUP, + .ep = USB_CONTROL_EP_OUT, + .bcnt = 8, + }; + + k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + } } } From 643e6b214590bf512ee15171fbc665584b8a309f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 26 May 2024 22:39:16 +0200 Subject: [PATCH 0940/1389] drivers: udc_dwc2: Properly revive STALLed endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DWC2 documentation unfortunately assigns somewhat confusing semantics to endpoint "enable"/"disable" and "activate"/"deactivate". The Zephyr USB device stack endpoint enable/disable refers to DWC2 activate/deactivate. The DWC2 endpoint enable/disable actions can be loosely referred to Zephyr USB stack enqueue/dequeue. Rename the functions and rework internal working to match DWC2 Programming Guide. This makes endpoint halt work as expected by the stack and therefore fixes all classes that rely on correct STALL handling. Most notable STALL user is the Mass Storage class. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 154 ++++++++++++++++++++++++++++++++++--- 1 file changed, 145 insertions(+), 9 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index b344ff0d7d632d..2f43eb00a506f2 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -259,6 +259,7 @@ static int dwc2_tx_fifo_write(const struct device *dev, mem_addr_t dieptsiz_reg = (mem_addr_t)&base->in_ep[ep_idx].dieptsiz; /* TODO: use dwc2_get_dxepctl_reg() */ mem_addr_t diepctl_reg = (mem_addr_t)&base->in_ep[ep_idx].diepctl; + mem_addr_t diepint_reg = (mem_addr_t)&base->in_ep[ep_idx].diepint; uint32_t max_xfersize, max_pktcnt, pktcnt, spcavail; const size_t d = sizeof(uint32_t); @@ -321,6 +322,8 @@ static int dwc2_tx_fifo_write(const struct device *dev, /* Clear NAK and set endpoint enable */ sys_set_bits(diepctl_reg, USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_CNAK); + /* Clear IN Endpoint NAK Effective interrupt in case it was set */ + sys_write32(USB_DWC2_DIEPINT_INEPNAKEFF, diepint_reg); /* FIFO access is always in 32-bit words */ @@ -749,6 +752,8 @@ static inline void dwc2_handle_rxflvl(const struct device *dev) break; case USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE: LOG_DBG("SETUP pktsts DONE"); + case USB_DWC2_GRXSTSR_PKTSTS_GLOBAL_OUT_NAK: + LOG_DBG("Global OUT NAK"); break; default: break; @@ -960,6 +965,9 @@ static int udc_dwc2_ep_dequeue(const struct device *dev, } irq_unlock(lock_key); + + udc_ep_set_busy(dev, cfg->addr, false); + LOG_DBG("dequeue ep 0x%02x", cfg->addr); return 0; @@ -1108,8 +1116,8 @@ static int dwc2_ep_control_enable(const struct device *dev, return 0; } -static int udc_dwc2_ep_enable(const struct device *dev, - struct udc_ep_config *const cfg) +static int udc_dwc2_ep_activate(const struct device *dev, + struct udc_ep_config *const cfg) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); struct udc_dwc2_data *const priv = udc_get_private(dev); @@ -1213,8 +1221,117 @@ static int dwc2_unset_dedicated_fifo(const struct device *dev, return 0; } -static int udc_dwc2_ep_disable(const struct device *dev, - struct udc_ep_config *const cfg) +static void dwc2_wait_for_bit(mem_addr_t addr, uint32_t bit) +{ + k_timepoint_t timeout = sys_timepoint_calc(K_MSEC(100)); + + /* This could potentially be converted to use proper synchronization + * primitives instead of busy looping, but the number of interrupt bits + * this function can be waiting for is rather high. + * + * Busy looping is most likely fine unless profiling shows otherwise. + */ + while (!(sys_read32(addr) & bit)) { + if (sys_timepoint_expired(timeout)) { + LOG_ERR("Timeout waiting for bit 0x%08X at 0x%08X", + bit, (uint32_t)addr); + return; + } + } +} + +/* Disabled IN endpoint means that device will send NAK (isochronous: ZLP) after + * receiving IN token from host even if there is packet available in TxFIFO. + * Disabled OUT endpoint means that device will NAK (isochronous: discard data) + * incoming OUT data (or HS PING) even if there is space available in RxFIFO. + * + * Set stall parameter to true if caller wants to send STALL instead of NAK. + */ +static void udc_dwc2_ep_disable(const struct device *dev, + struct udc_ep_config *const cfg, bool stall) +{ + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + mem_addr_t dxepctl_reg; + uint32_t dxepctl; + + dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); + dxepctl = sys_read32(dxepctl_reg); + + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + mem_addr_t dctl_reg, gintsts_reg, doepint_reg; + uint32_t dctl; + + dctl_reg = (mem_addr_t)&base->dctl; + gintsts_reg = (mem_addr_t)&base->gintsts; + doepint_reg = (mem_addr_t)&base->out_ep[ep_idx].doepint; + + dctl = sys_read32(dctl_reg); + + if (sys_read32(gintsts_reg) & USB_DWC2_GINTSTS_GOUTNAKEFF) { + LOG_ERR("GOUTNAKEFF already active"); + } else { + dctl |= USB_DWC2_DCTL_SGOUTNAK; + sys_write32(dctl, dctl_reg); + dctl &= ~USB_DWC2_DCTL_SGOUTNAK; + } + + dwc2_wait_for_bit(gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF); + + dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; + if (stall) { + /* For OUT endpoints STALL is set instead of SNAK */ + dxepctl |= USB_DWC2_DEPCTL_STALL; + } else { + dxepctl |= USB_DWC2_DEPCTL_SNAK; + } + sys_write32(dxepctl, dxepctl_reg); + + dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); + + /* Clear Endpoint Disabled interrupt */ + sys_write32(USB_DWC2_DIEPINT_EPDISBLD, doepint_reg); + + dctl |= USB_DWC2_DCTL_CGOUTNAK; + sys_write32(dctl, dctl_reg); + } else { + mem_addr_t diepint_reg; + + diepint_reg = (mem_addr_t)&base->in_ep[ep_idx].diepint; + + dxepctl |= USB_DWC2_DEPCTL_SNAK; + if (stall) { + /* For IN endpoints STALL is set in addition to SNAK */ + dxepctl |= USB_DWC2_DEPCTL_STALL; + } + sys_write32(dxepctl, dxepctl_reg); + + dwc2_wait_for_bit(diepint_reg, USB_DWC2_DIEPINT_INEPNAKEFF); + + dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; + sys_write32(dxepctl, dxepctl_reg); + + dwc2_wait_for_bit(diepint_reg, USB_DWC2_DIEPINT_EPDISBLD); + + /* Clear Endpoint Disabled interrupt */ + sys_write32(USB_DWC2_DIEPINT_EPDISBLD, diepint_reg); + + /* TODO: Read DIEPTSIZn here? Programming Guide suggest it to + * let application know how many bytes of interrupted transfer + * were transferred to the host. + */ + + dwc2_flush_tx_fifo(dev, ep_idx); + } + + udc_ep_set_busy(dev, cfg->addr, false); +} + +/* Deactivated endpoint means that there will be a bus timeout when the host + * tries to access the endpoint. + */ +static int udc_dwc2_ep_deactivate(const struct device *dev, + struct udc_ep_config *const cfg) { uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); mem_addr_t dxepctl_reg; @@ -1226,7 +1343,11 @@ static int udc_dwc2_ep_disable(const struct device *dev, if (dxepctl & USB_DWC2_DEPCTL_USBACTEP) { LOG_DBG("Disable ep 0x%02x DxEPCTL%u %x", cfg->addr, ep_idx, dxepctl); - dxepctl |= USB_DWC2_DEPCTL_EPDIS | USB_DWC2_DEPCTL_SNAK; + + udc_dwc2_ep_disable(dev, cfg, false); + + dxepctl = sys_read32(dxepctl_reg); + dxepctl &= ~USB_DWC2_DEPCTL_USBACTEP; } else { LOG_WRN("ep 0x%02x is not active DxEPCTL%u %x", cfg->addr, ep_idx, dxepctl); @@ -1247,7 +1368,7 @@ static int udc_dwc2_ep_set_halt(const struct device *dev, { uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); - sys_set_bits(dwc2_get_dxepctl_reg(dev, cfg->addr), USB_DWC2_DEPCTL_STALL); + udc_dwc2_ep_disable(dev, cfg, true); LOG_DBG("Set halt ep 0x%02x", cfg->addr); if (ep_idx != 0) { @@ -1260,11 +1381,26 @@ static int udc_dwc2_ep_set_halt(const struct device *dev, static int udc_dwc2_ep_clear_halt(const struct device *dev, struct udc_ep_config *const cfg) { - sys_clear_bits(dwc2_get_dxepctl_reg(dev, cfg->addr), USB_DWC2_DEPCTL_STALL); + mem_addr_t dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); + uint32_t dxepctl; + struct dwc2_drv_event evt = { + .ep = cfg->addr, + .type = DWC2_DRV_EVT_XFER, + }; + + dxepctl = sys_read32(dxepctl_reg); + dxepctl &= ~USB_DWC2_DEPCTL_STALL; + dxepctl |= USB_DWC2_DEPCTL_SETD0PID; + sys_write32(dxepctl, dxepctl_reg); LOG_DBG("Clear halt ep 0x%02x", cfg->addr); cfg->stat.halted = false; + /* Resume queued transfers if any */ + if (udc_buf_peek(dev, cfg->addr)) { + k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + } + return 0; } @@ -1753,8 +1889,8 @@ static const struct udc_api udc_dwc2_api = { .set_address = udc_dwc2_set_address, .test_mode = udc_dwc2_test_mode, .host_wakeup = udc_dwc2_host_wakeup, - .ep_enable = udc_dwc2_ep_enable, - .ep_disable = udc_dwc2_ep_disable, + .ep_enable = udc_dwc2_ep_activate, + .ep_disable = udc_dwc2_ep_deactivate, .ep_set_halt = udc_dwc2_ep_set_halt, .ep_clear_halt = udc_dwc2_ep_clear_halt, .ep_enqueue = udc_dwc2_ep_enqueue, From eb95802867258281f83f48767fb61fad1a84d356 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0941/1389] drivers: lpuart: Fix async configure Fix async configure function not being called when the irq driven api is not used, which both causes a build warning and would not work at runtime. Signed-off-by: Declan Snyder --- drivers/serial/uart_mcux_lpuart.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index a3a46039bfc993..359944f477f8b3 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -714,10 +714,9 @@ static int mcux_lpuart_callback_set(const struct device *dev, uart_callback_t ca data->callback = NULL; data->cb_data = NULL; data->api_type = LPUART_ASYNC; - return mcux_lpuart_configure_async(dev); -#else - return 0; #endif + + return mcux_lpuart_configure_async(dev); } static int mcux_lpuart_tx(const struct device *dev, const uint8_t *buf, size_t len, From 9e812c8ba4bd601c44825605f3a73447369a2534 Mon Sep 17 00:00:00 2001 From: Taras Zaporozhets Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0942/1389] net: if: Fix potential unaligned word access The input address originates from an RX net_buf which may be unaligned. Consequently, word access to this unaligned buffer can trigger an unaligned access exception on certain platforms, such as the ARMv7 Cortex-A9. Signed-off-by: Taras Zaporozhets --- subsys/net/ip/net_if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 1dbc0fb46a6b83..dc115aaf2c3298 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -3549,7 +3549,7 @@ static bool ipv4_is_broadcast_address(struct net_if *iface, bcast.s_addr = ipv4->unicast[i].ipv4.address.in_addr.s_addr | ~ipv4->unicast[i].netmask.s_addr; - if (bcast.s_addr == addr->s_addr) { + if (bcast.s_addr == UNALIGNED_GET(&addr->s_addr)) { ret = true; goto out; } From 8624246e288c028a8666a209203913e7e04d65b7 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0943/1389] soc: nxp: rw: remove DT_NODE_HAS_STATUS_OKAY We do not have `DT_NODE_HAS_STATUS_OKAY`, change that to `DT_NODE_HAS_STATUS(node_id, okay)` instead Signed-off-by: Yong Cong Sin --- soc/nxp/rw/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/nxp/rw/soc.c b/soc/nxp/rw/soc.c index 536d79b67ec6ae..f319328bd37e8a 100644 --- a/soc/nxp/rw/soc.c +++ b/soc/nxp/rw/soc.c @@ -290,7 +290,7 @@ static int nxp_rw600_init(void) #define PMU_RESET_CAUSES \ COND_CODE_0(IS_EMPTY(PMU_RESET_CAUSES_), (PMU_RESET_CAUSES_), (0)) #define WDT_RESET \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(wwdt), (kPOWER_ResetSourceWdt), (0)) + COND_CODE_1(DT_NODE_HAS_STATUS(wwdt, okay), (kPOWER_ResetSourceWdt), (0)) #define RESET_CAUSES \ (PMU_RESET_CAUSES | WDT_RESET) #else From 84f7582cec84a57770f945673ccebeca8f31fc64 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0944/1389] Bluetooth: CAP: Add reference to the set member for CAP discover Since the CSIP API expects a set member struct for nearly all functionality, the reference to the full set member (along with the CAS specific CSIS) should be given to the application. Signed-off-by: Emil Gydesen --- doc/releases/migration-guide-3.7.rst | 5 ++++ include/zephyr/bluetooth/audio/cap.h | 8 ++++-- .../tmap_central/src/cap_initiator.c | 1 + subsys/bluetooth/audio/cap_commander.c | 3 ++- subsys/bluetooth/audio/cap_common.c | 25 +++++++++++-------- subsys/bluetooth/audio/cap_initiator.c | 3 ++- subsys/bluetooth/audio/cap_internal.h | 3 ++- subsys/bluetooth/audio/csip_internal.h | 2 ++ subsys/bluetooth/audio/csip_set_coordinator.c | 16 ++++++++++++ subsys/bluetooth/audio/shell/cap_commander.c | 1 + subsys/bluetooth/audio/shell/cap_initiator.c | 1 + .../audio/mocks/include/cap_commander.h | 1 + .../bluetooth/audio/mocks/src/cap_commander.c | 1 + tests/bluetooth/tester/src/btp_cap.c | 1 + .../bluetooth/audio/src/cap_commander_test.c | 1 + .../audio/src/cap_initiator_unicast_test.c | 1 + .../bsim/bluetooth/audio/src/gmap_ugg_test.c | 1 + 17 files changed, 59 insertions(+), 15 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 0ba7d361c03288..3222d6ad9c04ac 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -312,6 +312,11 @@ Bluetooth Audio :kconfig:option:`CONFIG_BT_ISO_PERIPHERAL` are not longer `select`ed automatically when enabling :kconfig:option:`CONFIG_BT_BAP_UNICAST_SERVER`, and these must now be set explicitly in the project configuration file. (:github:`71993`) +* The discover callback functions :code:`bt_cap_initiator_cb.unicast_discovery_complete`` and + :code:`bt_cap_commander_cb.discovery_complete`` for CAP now contain an additional parameter for + the set member. + This needs to be added to all instances of CAP discovery callback functions defined. + (:github:`72797`) Bluetooth Classic ================= diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index a6cfcb418d6eaf..6bf5e1b018e12b 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -63,14 +63,16 @@ struct bt_cap_initiator_cb { * @param conn The connection pointer supplied to * bt_cap_initiator_unicast_discover(). * @param err 0 if Common Audio Service was found else -ENODATA. + * @param member Pointer to the set member. NULL if err != 0. * @param csis_inst The Coordinated Set Identification Service if * Common Audio Service was found and includes a * Coordinated Set Identification Service. * NULL on error or if remote device does not include - * Coordinated Set Identification Service. + * Coordinated Set Identification Service. NULL if err != 0. */ void (*unicast_discovery_complete)( struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst); /** @@ -676,13 +678,15 @@ struct bt_cap_commander_cb { * @param conn The connection pointer supplied to * bt_cap_initiator_unicast_discover(). * @param err 0 if Common Audio Service was found else -ENODATA. + * @param member Pointer to the set member. NULL if err != 0. * @param csis_inst The Coordinated Set Identification Service if * Common Audio Service was found and includes a * Coordinated Set Identification Service. * NULL on error or if remote device does not include - * Coordinated Set Identification Service. + * Coordinated Set Identification Service. NULL if err != 0. */ void (*discovery_complete)(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst); #if defined(CONFIG_BT_VCP_VOL_CTLR) diff --git a/samples/bluetooth/tmap_central/src/cap_initiator.c b/samples/bluetooth/tmap_central/src/cap_initiator.c index dc7e54c439da4e..fd20fadaa71056 100644 --- a/samples/bluetooth/tmap_central/src/cap_initiator.c +++ b/samples/bluetooth/tmap_central/src/cap_initiator.c @@ -98,6 +98,7 @@ static struct bt_bap_lc3_preset unicast_preset_48_2_1 = BT_AUDIO_CONTEXT_TYPE_MEDIA); static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { diff --git a/subsys/bluetooth/audio/cap_commander.c b/subsys/bluetooth/audio/cap_commander.c index 7a9c1663594d1c..80fd66c103afc4 100644 --- a/subsys/bluetooth/audio/cap_commander.c +++ b/subsys/bluetooth/audio/cap_commander.c @@ -65,10 +65,11 @@ int bt_cap_commander_unregister_cb(const struct bt_cap_commander_cb *cb) static void cap_commander_discover_complete(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (cap_cb && cap_cb->discovery_complete) { - cap_cb->discovery_complete(conn, err, csis_inst); + cap_cb->discovery_complete(conn, err, member, csis_inst); } } diff --git a/subsys/bluetooth/audio/cap_common.c b/subsys/bluetooth/audio/cap_common.c index ea45041159992f..cd4ee8639f0d9e 100644 --- a/subsys/bluetooth/audio/cap_common.c +++ b/subsys/bluetooth/audio/cap_common.c @@ -256,6 +256,7 @@ struct bt_cap_common_client *bt_cap_common_get_client(enum bt_cap_set_type type, } static void cap_common_discover_complete(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { struct bt_cap_common_client *client; @@ -265,7 +266,7 @@ static void cap_common_discover_complete(struct bt_conn *conn, int err, const bt_cap_common_discover_func_t cb_func = client->discover_cb_func; client->discover_cb_func = NULL; - cb_func(conn, err, csis_inst); + cb_func(conn, err, member, csis_inst); } } @@ -278,7 +279,7 @@ static void csis_client_discover_cb(struct bt_conn *conn, if (err != 0) { LOG_DBG("CSIS client discover failed: %d", err); - cap_common_discover_complete(conn, err, NULL); + cap_common_discover_complete(conn, err, NULL, NULL); return; } @@ -290,10 +291,10 @@ static void csis_client_discover_cb(struct bt_conn *conn, if (member == NULL || set_count == 0 || client->csis_inst == NULL) { LOG_ERR("Unable to find CSIS for CAS"); - cap_common_discover_complete(conn, -ENODATA, NULL); + cap_common_discover_complete(conn, -ENODATA, NULL, NULL); } else { LOG_DBG("Found CAS with CSIS"); - cap_common_discover_complete(conn, 0, client->csis_inst); + cap_common_discover_complete(conn, 0, member, client->csis_inst); } } @@ -304,7 +305,7 @@ static uint8_t bt_cap_common_discover_included_cb(struct bt_conn *conn, if (attr == NULL) { LOG_DBG("CAS CSIS include not found"); - cap_common_discover_complete(conn, 0, NULL); + cap_common_discover_complete(conn, 0, NULL, NULL); } else { const struct bt_gatt_include *included_service = attr->user_data; struct bt_cap_common_client *client = @@ -335,11 +336,15 @@ static uint8_t bt_cap_common_discover_included_cb(struct bt_conn *conn, err = bt_csip_set_coordinator_discover(conn); if (err != 0) { LOG_DBG("Discover failed (err %d)", err); - cap_common_discover_complete(conn, err, NULL); + cap_common_discover_complete(conn, err, NULL, NULL); } } else { + const struct bt_csip_set_coordinator_set_member *member = + bt_csip_set_coordinator_csis_member_by_conn(conn); + LOG_DBG("Found CAS with CSIS"); - cap_common_discover_complete(conn, 0, client->csis_inst); + + cap_common_discover_complete(conn, 0, member, client->csis_inst); } } @@ -350,7 +355,7 @@ static uint8_t bt_cap_common_discover_cas_cb(struct bt_conn *conn, const struct struct bt_gatt_discover_params *params) { if (attr == NULL) { - cap_common_discover_complete(conn, -ENODATA, NULL); + cap_common_discover_complete(conn, -ENODATA, NULL, NULL); } else { const struct bt_gatt_service_val *prim_service = attr->user_data; struct bt_cap_common_client *client = @@ -362,7 +367,7 @@ static uint8_t bt_cap_common_discover_cas_cb(struct bt_conn *conn, const struct if (attr->handle == prim_service->end_handle) { LOG_DBG("Found CAS without CSIS"); - cap_common_discover_complete(conn, 0, NULL); + cap_common_discover_complete(conn, 0, NULL, NULL); return BT_GATT_ITER_STOP; } @@ -379,7 +384,7 @@ static uint8_t bt_cap_common_discover_cas_cb(struct bt_conn *conn, const struct if (err != 0) { LOG_DBG("Discover failed (err %d)", err); - cap_common_discover_complete(conn, err, NULL); + cap_common_discover_complete(conn, err, NULL, NULL); } } diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index cd57f97e11ccd3..3f750e9516f368 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -315,10 +315,11 @@ int bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source *broadcas static void bt_cap_initiator_discover_complete(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (cap_cb && cap_cb->unicast_discovery_complete) { - cap_cb->unicast_discovery_complete(conn, err, csis_inst); + cap_cb->unicast_discovery_complete(conn, err, member, csis_inst); } } diff --git a/subsys/bluetooth/audio/cap_internal.h b/subsys/bluetooth/audio/cap_internal.h index a2605e4b0c77ca..ad94a97a965733 100644 --- a/subsys/bluetooth/audio/cap_internal.h +++ b/subsys/bluetooth/audio/cap_internal.h @@ -118,7 +118,8 @@ struct bt_cap_commander_proc_param { }; typedef void (*bt_cap_common_discover_func_t)( - struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_csis_inst *csis_inst); + struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_set_member *member, + const struct bt_csip_set_coordinator_csis_inst *csis_inst); struct bt_cap_common_proc_param { union { diff --git a/subsys/bluetooth/audio/csip_internal.h b/subsys/bluetooth/audio/csip_internal.h index 082a96d2f1b5f2..86dcdcc0161654 100644 --- a/subsys/bluetooth/audio/csip_internal.h +++ b/subsys/bluetooth/audio/csip_internal.h @@ -48,3 +48,5 @@ struct bt_csip_set_coordinator_svc_inst { struct bt_csip_set_coordinator_csis_inst *bt_csip_set_coordinator_csis_inst_by_handle( struct bt_conn *conn, uint16_t start_handle); +struct bt_csip_set_coordinator_set_member * +bt_csip_set_coordinator_csis_member_by_conn(struct bt_conn *conn); diff --git a/subsys/bluetooth/audio/csip_set_coordinator.c b/subsys/bluetooth/audio/csip_set_coordinator.c index b59587ebdfc7ff..fb68aa2ee9ed73 100644 --- a/subsys/bluetooth/audio/csip_set_coordinator.c +++ b/subsys/bluetooth/audio/csip_set_coordinator.c @@ -1418,6 +1418,22 @@ struct bt_csip_set_coordinator_csis_inst *bt_csip_set_coordinator_csis_inst_by_h return NULL; } +struct bt_csip_set_coordinator_set_member * +bt_csip_set_coordinator_csis_member_by_conn(struct bt_conn *conn) +{ + struct bt_csip_set_coordinator_inst *client; + + CHECKIF(conn == NULL) { + LOG_DBG("conn is NULL"); + + return NULL; + } + + client = &client_insts[bt_conn_index(conn)]; + + return &client->set_member; +} + /*************************** PUBLIC FUNCTIONS ***************************/ int bt_csip_set_coordinator_register_cb(struct bt_csip_set_coordinator_cb *cb) { diff --git a/subsys/bluetooth/audio/shell/cap_commander.c b/subsys/bluetooth/audio/shell/cap_commander.c index 1042f3530a2368..16a6d5ce7f84c4 100644 --- a/subsys/bluetooth/audio/shell/cap_commander.c +++ b/subsys/bluetooth/audio/shell/cap_commander.c @@ -19,6 +19,7 @@ #include "audio.h" static void cap_discover_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { diff --git a/subsys/bluetooth/audio/shell/cap_initiator.c b/subsys/bluetooth/audio/shell/cap_initiator.c index 54d2e7caf53a2c..d5b7496eb19d0a 100644 --- a/subsys/bluetooth/audio/shell/cap_initiator.c +++ b/subsys/bluetooth/audio/shell/cap_initiator.c @@ -25,6 +25,7 @@ #define CAP_UNICAST_CLIENT_STREAM_COUNT ARRAY_SIZE(unicast_streams) static void cap_discover_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { diff --git a/tests/bluetooth/audio/mocks/include/cap_commander.h b/tests/bluetooth/audio/mocks/include/cap_commander.h index 1e56aca6930733..6133ce2ae64165 100644 --- a/tests/bluetooth/audio/mocks/include/cap_commander.h +++ b/tests/bluetooth/audio/mocks/include/cap_commander.h @@ -16,6 +16,7 @@ void mock_cap_commander_init(void); void mock_cap_commander_cleanup(void); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn *, int, + const struct bt_csip_set_coordinator_set_member *, const struct bt_csip_set_coordinator_csis_inst *); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_changed_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn *, int); diff --git a/tests/bluetooth/audio/mocks/src/cap_commander.c b/tests/bluetooth/audio/mocks/src/cap_commander.c index 4305f8e1b8ee23..c652de7946cef1 100644 --- a/tests/bluetooth/audio/mocks/src/cap_commander.c +++ b/tests/bluetooth/audio/mocks/src/cap_commander.c @@ -18,6 +18,7 @@ FAKE(mock_cap_commander_microphone_gain_changed_cb) DEFINE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn *, int, + const struct bt_csip_set_coordinator_set_member *, const struct bt_csip_set_coordinator_csis_inst *); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_changed_cb, struct bt_conn *, int); diff --git a/tests/bluetooth/tester/src/btp_cap.c b/tests/bluetooth/tester/src/btp_cap.c index c8ddf116b0eacd..58d34bd06511af 100644 --- a/tests/bluetooth/tester/src/btp_cap.c +++ b/tests/bluetooth/tester/src/btp_cap.c @@ -50,6 +50,7 @@ static void btp_send_discovery_completed_ev(struct bt_conn *conn, uint8_t status } static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { LOG_DBG(""); diff --git a/tests/bsim/bluetooth/audio/src/cap_commander_test.c b/tests/bsim/bluetooth/audio/src/cap_commander_test.c index 9271a6a12dee54..8d100ebb826670 100644 --- a/tests/bsim/bluetooth/audio/src/cap_commander_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_commander_test.c @@ -36,6 +36,7 @@ CREATE_FLAG(flag_microphone_mute_changed); CREATE_FLAG(flag_microphone_gain_changed); static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c index 3ae18ced886b86..0a4daa04ca11e7 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c @@ -185,6 +185,7 @@ static struct bt_bap_stream_ops unicast_stream_ops = { }; static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { diff --git a/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c b/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c index 3048dfa89995fc..1d686a31016e5d 100644 --- a/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c +++ b/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c @@ -263,6 +263,7 @@ static struct bt_bap_stream_ops stream_ops = { }; static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { From 6cccb7e81a314e6ebdae1a1b46ee8fcbd67d85cc Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0945/1389] kernel: userspace: manipulate _thread_idx_map on per-byte basis The sys_bitfield_(clear/set)_bit() work on pointer size element. However, _thread_idx_map[] is a byte array. On little endian systems, the bitops should work fine. However, on big endian systems, changing the lower bits may actually be manipulating memory outside the array when CONFIG_MAX_THREAD_BYTES is not multiple of 4. So modify the code to perform bit ops on a per-byte basis. Fixes #72430 Signed-off-by: Daniel Leung --- kernel/userspace.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/userspace.c b/kernel/userspace.c index 6a77532f8aebc0..664971e2727e26 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -277,8 +277,10 @@ static bool thread_idx_alloc(uintptr_t *tidx) if (idx != 0) { *tidx = base + (idx - 1); - sys_bitfield_clear_bit((mem_addr_t)_thread_idx_map, - *tidx); + /* Clear the bit. We already know the array index, + * and the bit to be cleared. + */ + _thread_idx_map[i] &= ~(BIT(idx - 1)); /* Clear permission from all objects */ k_object_wordlist_foreach(clear_perms_cb, @@ -308,7 +310,11 @@ static void thread_idx_free(uintptr_t tidx) /* To prevent leaked permission when index is recycled */ k_object_wordlist_foreach(clear_perms_cb, (void *)tidx); - sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx); + /* Figure out which bits to set in _thread_idx_map[] and set it. */ + int base = tidx / NUM_BITS(_thread_idx_map[0]); + int offset = tidx % NUM_BITS(_thread_idx_map[0]); + + _thread_idx_map[base] |= BIT(offset); } static struct k_object *dynamic_object_create(enum k_objects otype, size_t align, From 769ea1e51b06276d4773da970211f4ae51bd31d4 Mon Sep 17 00:00:00 2001 From: Nikolay Agishev Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0946/1389] ARCMWDT: Turn off picolibc support MetaWare toolchain doesn't support building Zephyr with Picolibc module. This PR fixes biuld process by turning off picolibc support on compiler side. Signed-off-by: Nikolay Agishev --- cmake/toolchain/arcmwdt/Kconfig.defconfig | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cmake/toolchain/arcmwdt/Kconfig.defconfig diff --git a/cmake/toolchain/arcmwdt/Kconfig.defconfig b/cmake/toolchain/arcmwdt/Kconfig.defconfig new file mode 100644 index 00000000000000..78164376629e6e --- /dev/null +++ b/cmake/toolchain/arcmwdt/Kconfig.defconfig @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Synopsys +# SPDX-License-Identifier: Apache-2.0 + +config PICOLIBC_SUPPORTED + default n From baee9bcf54ac714ae0ae6ee48dcfccc75e0d0134 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0947/1389] Bluetooth: ISO: Support bt_disable Add support for bt_disable in the ISO implementation. This involves clearing all information related to states in the controller, such as the BIGs and CIGs. Signed-off-by: Emil Gydesen --- subsys/bluetooth/host/conn_internal.h | 2 + subsys/bluetooth/host/hci_core.c | 4 + subsys/bluetooth/host/iso.c | 44 ++++++++-- tests/bsim/bluetooth/host/iso/cis/prj.conf | 1 + .../bluetooth/host/iso/cis/src/cis_central.c | 84 +++++++++++++++++-- .../host/iso/cis/tests_scripts/cis_disable.sh | 21 +++++ 6 files changed, 144 insertions(+), 12 deletions(-) create mode 100755 tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_disable.sh diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 1466d468148108..5bdbc947b64fca 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -323,6 +323,8 @@ int bt_conn_iso_init(void); /* Cleanup ISO references */ void bt_iso_cleanup_acl(struct bt_conn *iso_conn); +void bt_iso_reset(void); + /* Add a new BR/EDR connection */ struct bt_conn *bt_conn_add_br(const bt_addr_t *peer); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index f02acf526513f5..1c4a5ca67e1465 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -4264,6 +4264,10 @@ int bt_disable(void) k_thread_abort(&bt_workq.thread); #endif + if (IS_ENABLED(CONFIG_BT_ISO)) { + bt_iso_reset(); + } + bt_monitor_send(BT_MONITOR_CLOSE_INDEX, NULL, 0); /* Clear BT_DEV_ENABLE here to prevent early bt_enable() calls, before disable is diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index ec0a5e8ceabbbc..6df42691a288fb 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -764,25 +764,26 @@ static int validate_send(const struct bt_iso_chan *chan, const struct net_buf *b BT_ISO_DATA_DBG("chan %p len %zu", chan, net_buf_frags_len(buf)); if (chan->state != BT_ISO_STATE_CONNECTED) { - LOG_DBG("Not connected"); + LOG_DBG("Channel %p not connected", chan); return -ENOTCONN; } iso_conn = chan->iso; if (!iso_conn->iso.info.can_send) { - LOG_DBG("Channel not able to send"); + LOG_DBG("Channel %p not able to send", chan); return -EINVAL; } if (buf->size < hdr_size) { - LOG_DBG("Cannot send ISO packet with buffer size %u", buf->size); + LOG_DBG("Channel %p cannot send ISO packet with buffer size %u", chan, buf->size); return -EMSGSIZE; } max_data_len = iso_chan_max_data_len(chan); if (buf->len > max_data_len) { - LOG_DBG("Cannot send %u octets, maximum %u", buf->len, max_data_len); + LOG_DBG("Channel %p cannot send %u octets, maximum %u", chan, buf->len, + max_data_len); return -EMSGSIZE; } @@ -2194,6 +2195,11 @@ void bt_iso_security_changed(struct bt_conn *acl, uint8_t hci_status) continue; } + /* Set state to disconnected to indicate that we are no longer waiting for + * encryption. + * TODO: Remove the BT_ISO_STATE_ENCRYPT_PENDING state and replace with a flag to + * avoid these unnecessary state changes + */ bt_iso_chan_set_state(iso_chan, BT_ISO_STATE_DISCONNECTED); if (hci_status == BT_HCI_ERR_SUCCESS) { @@ -2528,7 +2534,7 @@ static void big_disconnect(struct bt_iso_big *big, uint8_t reason) SYS_SLIST_FOR_EACH_CONTAINER(&big->bis_channels, bis, node) { bis->iso->err = reason; - bt_iso_disconnected(bis->iso); + bt_iso_chan_disconnected(bis, reason); } } @@ -3278,3 +3284,31 @@ int bt_iso_big_sync(struct bt_le_per_adv_sync *sync, struct bt_iso_big_sync_para } #endif /* CONFIG_BT_ISO_SYNC_RECEIVER */ #endif /* CONFIG_BT_ISO_BROADCAST */ + +void bt_iso_reset(void) +{ +#if defined(CONFIG_BT_ISO_CENTRAL) + for (size_t i = 0U; i < ARRAY_SIZE(cigs); i++) { + struct bt_iso_cig *cig = &cigs[i]; + struct bt_iso_chan *cis, *tmp; + + /* Call the disconnected callback for each CIS that is no idle */ + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cig->cis_channels, cis, tmp, node) { + if (cis->state != BT_ISO_STATE_DISCONNECTED) { + bt_iso_chan_disconnected(cis, BT_HCI_ERR_UNSPECIFIED); + } + } + + cleanup_cig(cig); + } +#endif /* CONFIG_BT_ISO_CENTRAL */ + +#if defined(CONFIG_BT_ISO_BROADCAST) + for (size_t i = 0U; i < ARRAY_SIZE(bigs); i++) { + struct bt_iso_big *big = &bigs[i]; + + big_disconnect(big, BT_HCI_ERR_UNSPECIFIED); + cleanup_big(big); + } +#endif /* CONFIG_BT_ISO_BROADCAST */ +} diff --git a/tests/bsim/bluetooth/host/iso/cis/prj.conf b/tests/bsim/bluetooth/host/iso/cis/prj.conf index 78ef925ce07c47..134cd4beed5c0d 100644 --- a/tests/bsim/bluetooth/host/iso/cis/prj.conf +++ b/tests/bsim/bluetooth/host/iso/cis/prj.conf @@ -21,3 +21,4 @@ CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=208 CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 CONFIG_BT_CTLR_ISOAL_SOURCES=2 CONFIG_BT_CTLR_ISOAL_SINKS=2 +CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP=4 diff --git a/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c b/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c index 2cae15e78621f5..9c85946c1a2188 100644 --- a/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c +++ b/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c @@ -107,19 +107,23 @@ static void iso_connected(struct bt_iso_chan *chan) seq_num = 0U; enqueue_cnt = ENQUEUE_COUNT; - /* Start send timer */ - k_work_schedule(&iso_send_work, K_MSEC(0)); + if (chan == default_chan) { + /* Start send timer */ + k_work_schedule(&iso_send_work, K_MSEC(0)); - SET_FLAG(flag_iso_connected); + SET_FLAG(flag_iso_connected); + } } static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) { printk("ISO Channel %p disconnected (reason 0x%02x)\n", chan, reason); - k_work_cancel_delayable(&iso_send_work); + if (chan == default_chan) { + k_work_cancel_delayable(&iso_send_work); - UNSET_FLAG(flag_iso_connected); + UNSET_FLAG(flag_iso_connected); + } } static void sdu_sent_cb(struct bt_iso_chan *chan) @@ -188,12 +192,19 @@ static void set_cig_defaults(struct bt_iso_cig_param *param) } -static void create_cig(void) +static void create_cig(size_t iso_channels) { + struct bt_iso_chan *channels[ARRAY_SIZE(iso_chans)]; struct bt_iso_cig_param param; int err; + for (size_t i = 0U; i < iso_channels; i++) { + channels[i] = &iso_chans[i]; + } + set_cig_defaults(¶m); + param.num_cis = iso_channels; + param.cis_channels = channels; err = bt_iso_cig_create(¶m, &cig); if (err != 0) { @@ -385,10 +396,34 @@ static void terminate_cig(void) cig = NULL; } +static void reset_bluetooth(void) +{ + int err; + + printk("Resetting Bluetooth\n"); + + err = bt_disable(); + if (err != 0) { + FAIL("Failed to disable (%d)\n", err); + + return; + } + + /* After a disable, all CIGs and BIGs are removed */ + cig = NULL; + + err = bt_enable(NULL); + if (err != 0) { + FAIL("Failed to re-enable (%d)\n", err); + + return; + } +} + static void test_main(void) { init(); - create_cig(); + create_cig(1); reconfigure_cig(); connect_acl(); connect_cis(); @@ -404,6 +439,34 @@ static void test_main(void) PASS("Test passed\n"); } +static void test_main_disable(void) +{ + init(); + + /* Setup and connect before disabling */ + create_cig(ARRAY_SIZE(iso_chans)); + connect_acl(); + connect_cis(); + + /* Reset BT to see if we can set it up again */ + reset_bluetooth(); + + /* Set everything up again to see if everything still works as expected */ + create_cig(ARRAY_SIZE(iso_chans)); + connect_acl(); + connect_cis(); + + while (seq_num < 100U) { + k_sleep(K_USEC(interval_us)); + } + + disconnect_cis(); + disconnect_acl(); + terminate_cig(); + + PASS("Disable test passed\n"); +} + static const struct bst_test_instance test_def[] = { { .test_id = "central", @@ -412,6 +475,13 @@ static const struct bst_test_instance test_def[] = { .test_tick_f = test_tick, .test_main_f = test_main, }, + { + .test_id = "central_disable", + .test_descr = "CIS central that tests bt_disable for ISO", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main_disable, + }, BSTEST_END_MARKER, }; diff --git a/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_disable.sh b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_disable.sh new file mode 100755 index 00000000000000..dfd2d8d11e2240 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_disable.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="iso_cis_disable" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_cis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central_disable + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_cis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs From 7eaa569dc779918b481a40a3855251289f8fdce5 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0948/1389] Bluetooth: ISO: Guard sec_level for iso_chan with unicast The required_sec_level is only valid for unicast iso channels. Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/iso.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zephyr/bluetooth/iso.h b/include/zephyr/bluetooth/iso.h index f7bb3900e76490..c7ff859472f60f 100644 --- a/include/zephyr/bluetooth/iso.h +++ b/include/zephyr/bluetooth/iso.h @@ -156,7 +156,7 @@ struct bt_iso_chan { struct bt_iso_chan_qos *qos; /** Channel state */ enum bt_iso_state state; -#if defined(CONFIG_BT_SMP) || defined(__DOXYGEN__) +#if (defined(CONFIG_BT_SMP) && defined(CONFIG_BT_ISO_UNICAST)) || defined(__DOXYGEN__) /** @brief The required security level of the channel * * This value can be set as the central before connecting a CIS @@ -167,7 +167,7 @@ struct bt_iso_chan { * Only available when @kconfig{CONFIG_BT_SMP} is enabled. */ bt_security_t required_sec_level; -#endif /* CONFIG_BT_SMP */ +#endif /* CONFIG_BT_SMP && CONFIG_BT_ISO_UNICAST */ /** Node used internally by the stack */ sys_snode_t node; }; From 3abd4ca232524ac59cfb9229643dfe9b6ac14e54 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0949/1389] Bluetooth: Host: Guard set state in conn_destroy If bt_conn_set_state(conn, BT_CONN_DISCONNECTED) is called while the connection is already disconnected, this triggers a warning. This is likely to happen when bt_conn_cleanup_all is called as part of bt_disable. Added the state check to avoid unnecessary warnings in the log. Signed-off-by: Emil Gydesen --- subsys/bluetooth/host/conn.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 8caebcc4c3c347..018329969695cf 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -852,7 +852,9 @@ static void conn_destroy(struct bt_conn *conn, void *data) bt_conn_set_state(conn, BT_CONN_DISCONNECT_COMPLETE); } - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + if (conn->state != BT_CONN_DISCONNECTED) { + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + } } void bt_conn_cleanup_all(void) From 30d8389521caae6e465a62937c2292e2f88c3106 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0950/1389] Tests: Bluetooth: Add BSIM test of ISO BIS Adds 2 tests for ISO broadcast. First test is just a minimal test that sets up a BIG, transmits data and verifies that it is being received on the ISO sync receiver. The second test creates a BIG, disables BT, enables BT, and the verifies the above. Signed-off-by: Emil Gydesen --- tests/bsim/bluetooth/host/compile.sh | 1 + .../bluetooth/host/iso/bis/CMakeLists.txt | 22 ++ tests/bsim/bluetooth/host/iso/bis/prj.conf | 27 ++ .../host/iso/bis/src/bis_broadcaster.c | 328 ++++++++++++++++++ .../bluetooth/host/iso/bis/src/bis_receiver.c | 280 +++++++++++++++ .../bsim/bluetooth/host/iso/bis/src/common.c | 31 ++ .../bsim/bluetooth/host/iso/bis/src/common.h | 16 + tests/bsim/bluetooth/host/iso/bis/src/main.c | 22 ++ .../host/iso/bis/tests_scripts/_compile.sh | 13 + .../host/iso/bis/tests_scripts/bis.sh | 21 ++ .../host/iso/bis/tests_scripts/bis_disable.sh | 21 ++ 11 files changed, 782 insertions(+) create mode 100644 tests/bsim/bluetooth/host/iso/bis/CMakeLists.txt create mode 100644 tests/bsim/bluetooth/host/iso/bis/prj.conf create mode 100644 tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c create mode 100644 tests/bsim/bluetooth/host/iso/bis/src/bis_receiver.c create mode 100644 tests/bsim/bluetooth/host/iso/bis/src/common.c create mode 100644 tests/bsim/bluetooth/host/iso/bis/src/common.h create mode 100644 tests/bsim/bluetooth/host/iso/bis/src/main.c create mode 100755 tests/bsim/bluetooth/host/iso/bis/tests_scripts/_compile.sh create mode 100755 tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis.sh create mode 100755 tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis_disable.sh diff --git a/tests/bsim/bluetooth/host/compile.sh b/tests/bsim/bluetooth/host/compile.sh index cc0d49ea360fa3..265bb6fae39f4f 100755 --- a/tests/bsim/bluetooth/host/compile.sh +++ b/tests/bsim/bluetooth/host/compile.sh @@ -18,6 +18,7 @@ ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/l2cap/compile.sh ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/security/compile.sh app=tests/bsim/bluetooth/host/iso/cis compile +app=tests/bsim/bluetooth/host/iso/bis compile app=tests/bsim/bluetooth/host/misc/disable compile app=tests/bsim/bluetooth/host/misc/disconnect/dut compile diff --git a/tests/bsim/bluetooth/host/iso/bis/CMakeLists.txt b/tests/bsim/bluetooth/host/iso/bis/CMakeLists.txt new file mode 100644 index 00000000000000..89a3d5cf313d50 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(bsim_test_iso_bis) + +add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit) +target_link_libraries(app PRIVATE babblekit) + +target_sources(app PRIVATE + src/common.c + src/bis_broadcaster.c + src/bis_receiver.c + src/main.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ +) diff --git a/tests/bsim/bluetooth/host/iso/bis/prj.conf b/tests/bsim/bluetooth/host/iso/bis/prj.conf new file mode 100644 index 00000000000000..e1e57deda07dee --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/prj.conf @@ -0,0 +1,27 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_ASSERT=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y + +CONFIG_BT_DEVICE_NAME="BIS test" + +CONFIG_BT_ISO_BROADCASTER=y +CONFIG_BT_ISO_SYNC_RECEIVER=y +CONFIG_BT_ISO_TX_BUF_COUNT=4 +CONFIG_BT_ISO_MAX_CHAN=4 +CONFIG_BT_ISO_TX_MTU=200 +CONFIG_BT_ISO_RX_MTU=200 + +CONFIG_BT_ISO_LOG_LEVEL_DBG=y + +# Controller ISO configs +CONFIG_BT_CTLR_ADV_ISO=y +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=4 +CONFIG_BT_CTLR_SYNC_ISO=y +CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=4 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=208 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 +CONFIG_BT_CTLR_ISOAL_SOURCES=4 +CONFIG_BT_CTLR_ISOAL_SINKS=4 diff --git a/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c b/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c new file mode 100644 index 00000000000000..165b6add6838ce --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +#include +#include +#include + +#include "babblekit/flags.h" +#include "babblekit/sync.h" +#include "babblekit/testcase.h" + +LOG_MODULE_REGISTER(bis_broadcaster, LOG_LEVEL_INF); + +#define LATENCY_MS 10U /* 10ms */ +#define SDU_INTERVAL_US 10U * USEC_PER_MSEC /* 10 ms */ + +extern enum bst_result_t bst_result; +static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN]; +static struct bt_iso_chan *default_chan = &iso_chans[0]; +static uint16_t seq_num; +NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static DEFINE_FLAG(flag_iso_connected); + +static void send_data_cb(struct k_work *work); +K_WORK_DELAYABLE_DEFINE(iso_send_work, send_data_cb); + +static void send_data(struct bt_iso_chan *chan) +{ + static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU]; + static size_t len_to_send = 1U; + static bool data_initialized; + struct net_buf *buf; + int ret; + + if (!IS_FLAG_SET(flag_iso_connected)) { + /* TX has been aborted */ + return; + } + + if (!data_initialized) { + for (int i = 0; i < ARRAY_SIZE(buf_data); i++) { + buf_data[i] = (uint8_t)i; + } + + data_initialized = true; + } + + buf = net_buf_alloc(&tx_pool, K_NO_WAIT); + TEST_ASSERT(buf != NULL, "Failed to allocate buffer"); + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, buf_data, len_to_send); + + ret = bt_iso_chan_send(default_chan, buf, seq_num++); + if (ret < 0) { + LOG_DBG("Failed to send ISO data: %d", ret); + net_buf_unref(buf); + + /* Reschedule for next interval */ + k_work_reschedule(&iso_send_work, K_USEC(SDU_INTERVAL_US)); + + return; + } + + len_to_send++; + if (len_to_send > ARRAY_SIZE(buf_data)) { + len_to_send = 1; + } +} + +static void send_data_cb(struct k_work *work) +{ + const uint16_t tx_pool_cnt = tx_pool.uninit_count; + + /* Send/enqueue as many as we can */ + for (uint16_t i = 0U; i < tx_pool_cnt; i++) { + send_data(default_chan); + } +} + +static void iso_connected_cb(struct bt_iso_chan *chan) +{ + LOG_INF("ISO Channel %p connected", chan); + + if (chan == default_chan) { + seq_num = 0U; + + SET_FLAG(flag_iso_connected); + } +} + +static void iso_disconnected_cb(struct bt_iso_chan *chan, uint8_t reason) +{ + LOG_INF("ISO Channel %p disconnected (reason 0x%02x)", chan, reason); + + if (chan == default_chan) { + k_work_cancel_delayable(&iso_send_work); + + UNSET_FLAG(flag_iso_connected); + } +} + +static void sdu_sent_cb(struct bt_iso_chan *chan) +{ + if (!IS_FLAG_SET(flag_iso_connected)) { + /* TX has been aborted */ + return; + } + + send_data(chan); +} + +static void init(void) +{ + static struct bt_iso_chan_ops iso_ops = { + .disconnected = iso_disconnected_cb, + .connected = iso_connected_cb, + .sent = sdu_sent_cb, + }; + static struct bt_iso_chan_io_qos iso_tx = { + .sdu = CONFIG_BT_ISO_TX_MTU, + .phy = BT_GAP_LE_PHY_2M, + .rtn = 1, + .path = NULL, + }; + static struct bt_iso_chan_qos iso_qos = { + .tx = &iso_tx, + .rx = NULL, + }; + int err; + + err = bt_enable(NULL); + TEST_ASSERT(err == 0, "Bluetooth enable failed: %d", err); + + for (size_t i = 0U; i < ARRAY_SIZE(iso_chans); i++) { + iso_chans[i].ops = &iso_ops; + iso_chans[i].qos = &iso_qos; + } + + bk_sync_init(); +} + +static void create_ext_adv(struct bt_le_ext_adv **adv) +{ + int err; + + LOG_INF("Creating extended advertising set with periodic advertising"); + + /* Create a non-connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); + TEST_ASSERT(err == 0, "Unable to create extended advertising set: %d", err); + + /* Set periodic advertising parameters */ + err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_PARAM(BT_GAP_PER_ADV_FAST_INT_MIN_2, + BT_GAP_PER_ADV_FAST_INT_MAX_2, + BT_LE_PER_ADV_OPT_NONE)); + TEST_ASSERT(err == 0, "Failed to set periodic advertising parameters: %d", err); +} + +static void start_ext_adv(struct bt_le_ext_adv *adv) +{ + int err; + + LOG_INF("Starting extended and periodic advertising"); + + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + TEST_ASSERT(err == 0, "Failed to start extended advertising: %d", err); + + /* FIXME: Temporary workaround to get around an assert in the controller + * Open issue: https://github.com/zephyrproject-rtos/zephyr/issues/72852 + */ + k_sleep(K_MSEC(100)); + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); + TEST_ASSERT(err == 0, "Failed to enable periodic advertising: %d", err); +} + +static void create_big(struct bt_le_ext_adv *adv, size_t cnt, struct bt_iso_big **out_big) +{ + struct bt_iso_chan *channels[ARRAY_SIZE(iso_chans)]; + struct bt_iso_big_create_param param = { + .packing = BT_ISO_PACKING_SEQUENTIAL, + .framing = BT_ISO_FRAMING_UNFRAMED, + .interval = SDU_INTERVAL_US, + .bis_channels = channels, + .latency = LATENCY_MS, + .encryption = false, + .num_bis = cnt, + }; + int err; + + for (size_t i = 0U; i < cnt; i++) { + channels[i] = &iso_chans[i]; + } + + LOG_INF("Creating BIG"); + + err = bt_iso_big_create(adv, ¶m, out_big); + TEST_ASSERT(err == 0, "Failed to create BIG: %d", err); + + WAIT_FOR_FLAG(flag_iso_connected); +} + +static void start_tx(void) +{ + const uint16_t tx_pool_cnt = tx_pool.uninit_count; + + LOG_INF("Starting TX"); + + /* Send/enqueue as many as we can */ + for (uint16_t i = 0U; i < tx_pool_cnt; i++) { + send_data(default_chan); + } +} + +static void terminate_big(struct bt_iso_big *big) +{ + int err; + + LOG_INF("Terminating BIG"); + + err = bt_iso_big_terminate(big); + TEST_ASSERT(err == 0, "Failed to terminate BIG: %d", err); + + big = NULL; +} + +static void reset_bluetooth(void) +{ + int err; + + LOG_INF("Resetting Bluetooth"); + + err = bt_disable(); + TEST_ASSERT(err == 0, "Failed to disable: %d", err); + + err = bt_enable(NULL); + TEST_ASSERT(err == 0, "Failed to re-enable: %d", err); +} + +static void test_main(void) +{ + struct bt_le_ext_adv *adv; + struct bt_iso_big *big; + + init(); + + /* Create advertising set and BIG and start it and starting TXing */ + create_ext_adv(&adv); + create_big(adv, 1U, &big); + start_ext_adv(adv); + start_tx(); + + /* Wait for receiver to tell us to terminate */ + bk_sync_wait(); + + terminate_big(big); + big = NULL; + + TEST_PASS("Test passed"); +} + +static void test_main_disable(void) +{ + struct bt_le_ext_adv *adv; + struct bt_iso_big *big; + + init(); + + /* Create advertising set and BIG */ + create_ext_adv(&adv); + create_big(adv, ARRAY_SIZE(iso_chans), &big); + + /* Reset BT to see if we can set it up again */ + reset_bluetooth(); + + /* After a disable, all advertising sets and BIGs are removed */ + big = NULL; + adv = NULL; + + /* Set everything up again to see if everything still works as expected */ + create_ext_adv(&adv); + create_big(adv, ARRAY_SIZE(iso_chans), &big); + start_ext_adv(adv); + start_tx(); + + /* Wait for receiver to tell us to terminate */ + bk_sync_wait(); + + terminate_big(big); + big = NULL; + + TEST_PASS("Disable test passed"); +} + +static const struct bst_test_instance test_def[] = { + { + .test_id = "broadcaster", + .test_descr = "Minimal BIS broadcaster that broadcast ISO data", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + { + .test_id = "broadcaster_disable", + .test_descr = "BIS broadcaster that tests bt_disable for ISO", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main_disable, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_main_bis_broadcaster_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_def); +} diff --git a/tests/bsim/bluetooth/host/iso/bis/src/bis_receiver.c b/tests/bsim/bluetooth/host/iso/bis/src/bis_receiver.c new file mode 100644 index 00000000000000..6d1ec087b23fdd --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/src/bis_receiver.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +#include +#include +#include + +#include "babblekit/flags.h" +#include "babblekit/sync.h" +#include "babblekit/testcase.h" + +LOG_MODULE_REGISTER(bis_receiver, LOG_LEVEL_INF); + +#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 5U /* Set the timeout relative to interval */ + +extern enum bst_result_t bst_result; + +static DEFINE_FLAG(flag_broadcaster_found); +static DEFINE_FLAG(flag_iso_connected); +static DEFINE_FLAG(flag_data_received); +static DEFINE_FLAG(flag_pa_synced); +static DEFINE_FLAG(flag_biginfo); + +static struct bt_iso_chan iso_chans[CONFIG_BT_ISO_MAX_CHAN]; +static struct bt_le_scan_recv_info broadcaster_info; +static bt_addr_le_t broadcaster_addr; +static uint8_t broadcaster_num_bis; + +/** Log data as d_0 d_1 d_2 ... d_(n-2) d_(n-1) d_(n) to show the 3 first and 3 last octets + * + * Examples: + * 01 + * 0102 + * 010203 + * 01020304 + * 0102030405 + * 010203040506 + * 010203...050607 + * 010203...060708 + * etc. + */ +static void iso_log_data(uint8_t *data, size_t data_len) +{ + /* Maximum number of octets from each end of the data */ + const uint8_t max_octets = 3; + char data_str[35]; + size_t str_len; + + str_len = bin2hex(data, MIN(max_octets, data_len), data_str, sizeof(data_str)); + if (data_len > max_octets) { + if (data_len > (max_octets * 2)) { + static const char dots[] = "..."; + + strcat(&data_str[str_len], dots); + str_len += strlen(dots); + } + + str_len += bin2hex(data + (data_len - MIN(max_octets, data_len - max_octets)), + MIN(max_octets, data_len - max_octets), data_str + str_len, + sizeof(data_str) - str_len); + } + + LOG_DBG("\t %s", data_str); +} + +static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + if (info->flags & BT_ISO_FLAGS_VALID) { + LOG_DBG("Incoming data channel %p len %u", chan, buf->len); + iso_log_data(buf->data, buf->len); + SET_FLAG(flag_data_received); + } +} + +static void iso_connected(struct bt_iso_chan *chan) +{ + LOG_INF("ISO Channel %p connected", chan); + + SET_FLAG(flag_iso_connected); +} + +static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) +{ + LOG_INF("ISO Channel %p disconnected (reason 0x%02x)", chan, reason); + + UNSET_FLAG(flag_iso_connected); +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) +{ + if (IS_FLAG_SET(flag_broadcaster_found)) { + /* no-op*/ + return; + } + + LOG_INF("Broadcaster found"); + + if (info->interval != 0U) { + memcpy(&broadcaster_info, info, sizeof(broadcaster_info)); + bt_addr_le_copy(&broadcaster_addr, info->addr); + SET_FLAG(flag_broadcaster_found); + } +} + +static void pa_synced_cb(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + LOG_INF("PA synced"); + + SET_FLAG(flag_pa_synced); +} + +static void pa_term_cb(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + LOG_INF("PA terminated"); + + UNSET_FLAG(flag_pa_synced); +} + +static void pa_biginfo_cb(struct bt_le_per_adv_sync *sync, const struct bt_iso_biginfo *biginfo) +{ + if (IS_FLAG_SET(flag_biginfo)) { + /* no-op*/ + return; + } + + LOG_INF("BIGInfo received"); + + broadcaster_num_bis = biginfo->num_bis; + SET_FLAG(flag_biginfo); +} + +static void init(void) +{ + static struct bt_le_per_adv_sync_cb pa_sync_cbs = { + .biginfo = pa_biginfo_cb, + .synced = pa_synced_cb, + .term = pa_term_cb, + }; + static struct bt_le_scan_cb bap_scan_cb = { + .recv = broadcast_scan_recv, + }; + static struct bt_iso_chan_io_qos iso_rx = { + .sdu = CONFIG_BT_ISO_TX_MTU, + }; + static struct bt_iso_chan_ops iso_ops = { + .recv = iso_recv, + .connected = iso_connected, + .disconnected = iso_disconnected, + }; + static struct bt_iso_chan_qos iso_qos = { + .rx = &iso_rx, + }; + int err; + + err = bt_enable(NULL); + TEST_ASSERT(err == 0, "Bluetooth enable failed (err %d)", err); + + for (size_t i = 0U; i < ARRAY_SIZE(iso_chans); i++) { + iso_chans[i].ops = &iso_ops; + iso_chans[i].qos = &iso_qos; + } + + bt_le_per_adv_sync_cb_register(&pa_sync_cbs); + bt_le_scan_cb_register(&bap_scan_cb); + + bk_sync_init(); +} + +static uint16_t interval_to_sync_timeout(uint16_t pa_interval) +{ + uint32_t interval_ms; + uint16_t pa_timeout; + uint32_t timeout; + + /* Add retries and convert to unit in 10's of ms */ + interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval); + timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10U; + + /* Enforce restraints */ + pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); + + return pa_timeout; +} + +static void scan_and_sync_pa(struct bt_le_per_adv_sync **out_sync) +{ + struct bt_le_per_adv_sync_param create_params = {0}; + int err; + + LOG_INF("Starting scan"); + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); + TEST_ASSERT(err == 0, "Failed to start scan: %d", err); + + WAIT_FOR_FLAG(flag_broadcaster_found); + + bt_addr_le_copy(&create_params.addr, &broadcaster_addr); + create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE; + create_params.sid = broadcaster_info.sid; + create_params.skip = 0U; + create_params.timeout = interval_to_sync_timeout(broadcaster_info.interval); + + LOG_INF("Creating PA sync"); + err = bt_le_per_adv_sync_create(&create_params, out_sync); + TEST_ASSERT(err == 0, "Failed to sync to PA: %d", err); + + WAIT_FOR_FLAG(flag_pa_synced); + + LOG_INF("Stopping scan"); + err = bt_le_scan_stop(); + TEST_ASSERT(err == 0, "Failed to stop scan: %d", err); +} + +static void sync_big(struct bt_le_per_adv_sync *sync, uint8_t cnt, struct bt_iso_big **out_big) +{ + struct bt_iso_chan *bis_channels[CONFIG_BT_ISO_MAX_CHAN]; + struct bt_iso_big_sync_param param = { + .sync_timeout = interval_to_sync_timeout(broadcaster_info.interval), + .bis_bitfield = BIT_MASK(cnt) << 1U, /* BIS indexes start from 1, thus shift by 1 */ + .bis_channels = bis_channels, + .mse = BT_ISO_SYNC_MSE_MIN, + .encryption = false, + .num_bis = cnt, + }; + int err; + + TEST_ASSERT(cnt <= ARRAY_SIZE(bis_channels)); + for (size_t i = 0U; i < cnt; i++) { + bis_channels[i] = &iso_chans[i]; + } + + LOG_INF("Creating BIG sync"); + err = bt_iso_big_sync(sync, ¶m, out_big); + TEST_ASSERT(err == 0, "Failed to create BIG sync: %d"); + + WAIT_FOR_FLAG(flag_iso_connected); +} + +static void test_main(void) +{ + struct bt_le_per_adv_sync *sync; + struct bt_iso_big *big; + + init(); + scan_and_sync_pa(&sync); + WAIT_FOR_FLAG(flag_biginfo); + sync_big(sync, MIN(broadcaster_num_bis, CONFIG_BT_ISO_MAX_CHAN), &big); + + LOG_INF("Waiting for data"); + WAIT_FOR_FLAG(flag_data_received); + bk_sync_send(); + + LOG_INF("Waiting for sync lost"); + WAIT_FOR_FLAG_UNSET(flag_iso_connected); + + TEST_PASS("Test passed"); +} + +static const struct bst_test_instance test_def[] = { + { + .test_id = "receiver", + .test_descr = "receiver", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_main_bis_receiver_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_def); +} diff --git a/tests/bsim/bluetooth/host/iso/bis/src/common.c b/tests/bsim/bluetooth/host/iso/bis/src/common.c new file mode 100644 index 00000000000000..f644f9181c2b7a --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/src/common.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include +#include +#include + +#include "babblekit/flags.h" +#include "babblekit/testcase.h" + +#include "common.h" + +extern enum bst_result_t bst_result; + +void test_init(void) +{ + bst_result = In_progress; + bst_ticker_set_next_tick_absolute(WAIT_TIME); +} + +void test_tick(bs_time_t HW_device_time) +{ + if (bst_result != Passed) { + TEST_FAIL("Test failed (not passed after %" PRIu64 " us)", WAIT_TIME); + } +} diff --git a/tests/bsim/bluetooth/host/iso/bis/src/common.h b/tests/bsim/bluetooth/host/iso/bis/src/common.h new file mode 100644 index 00000000000000..60a191e3883810 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/src/common.h @@ -0,0 +1,16 @@ +/* + * Common functions and helpers for ISO broadcast tests + * + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bstests.h" + +#define WAIT_TIME (30e6) /* 30 seconds*/ + +void test_init(void); +void test_tick(bs_time_t HW_device_time); diff --git a/tests/bsim/bluetooth/host/iso/bis/src/main.c b/tests/bsim/bluetooth/host/iso/bis/src/main.c new file mode 100644 index 00000000000000..3bfdb37533447d --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_main_bis_broadcaster_install(struct bst_test_list *tests); +extern struct bst_test_list *test_main_bis_receiver_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_main_bis_broadcaster_install, + test_main_bis_receiver_install, + NULL, +}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/iso/bis/tests_scripts/_compile.sh b/tests/bsim/bluetooth/host/iso/bis/tests_scripts/_compile.sh new file mode 100755 index 00000000000000..e717a4b2bbef02 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/tests_scripts/_compile.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +set -eu +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be defined}" + +INCR_BUILD=1 + +source ${ZEPHYR_BASE}/tests/bsim/compile.source + +app="$(guess_test_relpath)" compile + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis.sh b/tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis.sh new file mode 100755 index 00000000000000..18c76e299e37e7 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="iso_bis" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=broadcaster + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=receiver + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis_disable.sh b/tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis_disable.sh new file mode 100755 index 00000000000000..980af68ee6f046 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/bis/tests_scripts/bis_disable.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="iso_bis_disable" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=broadcaster_disable + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_bis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=receiver + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs From 4133728954b374ef36dc46217114699eac544208 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0951/1389] Bluetooth: ISO: Upgrade from experimental to unstable The ISO API and implementation have existed in Zephyr for several years, and while not fully qualified, stable or tested yet, it's not experimental anymore (and have not been for a long time). This commit removes any references to it being experimental and instead defines it as unstable by setting the version to > 0.1.0. 0.8.0 is being used as the initial version, as that is what other unstable modules was defined to have as their initial version if they were not stable (>= 1.0.0). Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/iso.h | 4 ++++ subsys/bluetooth/Kconfig.iso | 12 ++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/zephyr/bluetooth/iso.h b/include/zephyr/bluetooth/iso.h index c7ff859472f60f..a8166a5605132d 100644 --- a/include/zephyr/bluetooth/iso.h +++ b/include/zephyr/bluetooth/iso.h @@ -14,6 +14,10 @@ /** * @brief Isochronous channels (ISO) * @defgroup bt_iso Isochronous channels (ISO) + * + * @since 2.3 + * @version 0.8.0 + * * @ingroup bluetooth * @{ */ diff --git a/subsys/bluetooth/Kconfig.iso b/subsys/bluetooth/Kconfig.iso index cce7208b48cf08..9fdde1da867347 100644 --- a/subsys/bluetooth/Kconfig.iso +++ b/subsys/bluetooth/Kconfig.iso @@ -25,21 +25,19 @@ config BT_ISO_UNICAST Isochronous channels. config BT_ISO_PERIPHERAL - bool "Bluetooth Isochronous Channel Unicast Peripheral Support [EXPERIMENTAL]" + bool "Bluetooth Isochronous Channel Unicast Peripheral Support" depends on !BT_CTLR || BT_CTLR_PERIPHERAL_ISO_SUPPORT select BT_PERIPHERAL select BT_ISO_UNICAST - select EXPERIMENTAL help This option enables support for Bluetooth Unicast Isochronous channels for the peripheral role. config BT_ISO_CENTRAL - bool "Bluetooth Isochronous Channel Unicast Central Support [EXPERIMENTAL]" + bool "Bluetooth Isochronous Channel Unicast Central Support" depends on !BT_CTLR || BT_CTLR_CENTRAL_ISO_SUPPORT select BT_CENTRAL select BT_ISO_UNICAST - select EXPERIMENTAL help This option enables support for Bluetooth Broadcast Isochronous channels for the central role. @@ -50,24 +48,22 @@ config BT_ISO_BROADCAST select BT_EXT_ADV config BT_ISO_BROADCASTER - bool "Bluetooth Isochronous Broadcaster Support [EXPERIMENTAL]" + bool "Bluetooth Isochronous Broadcaster Support" depends on !BT_CTLR || BT_CTLR_ADV_ISO_SUPPORT select BT_ISO_BROADCAST select BT_ISO_TX select BT_BROADCASTER select BT_PER_ADV - select EXPERIMENTAL help This option enables support for the Bluetooth Isochronous Broadcaster. config BT_ISO_SYNC_RECEIVER - bool "Bluetooth Isochronous Synchronized Receiver Support [EXPERIMENTAL]" + bool "Bluetooth Isochronous Synchronized Receiver Support" depends on !BT_CTLR || BT_CTLR_SYNC_ISO_SUPPORT select BT_ISO_BROADCAST select BT_ISO_RX select BT_OBSERVER select BT_PER_ADV_SYNC - select EXPERIMENTAL help This option enables support for the Bluetooth Isochronous Synchronized Receiver. From 096b629929b8497b8825bb0de47a73f18f7202e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Stenberg?= Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0952/1389] voltage_divider: Add support for single-ended 16-bit ADC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unless configured as differential, the raw ADC data is unsigned. Includes workaround for #71119. Signed-off-by: Björn Stenberg --- drivers/sensor/voltage_divider/voltage.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/sensor/voltage_divider/voltage.c b/drivers/sensor/voltage_divider/voltage.c index 47569b005d58db..f10a6596222aa7 100644 --- a/drivers/sensor/voltage_divider/voltage.c +++ b/drivers/sensor/voltage_divider/voltage.c @@ -22,7 +22,7 @@ struct voltage_config { struct voltage_data { struct adc_sequence sequence; - int16_t raw; + uint16_t raw; }; static int fetch(const struct device *dev, enum sensor_channel chan) @@ -47,7 +47,7 @@ static int get(const struct device *dev, enum sensor_channel chan, struct sensor { const struct voltage_config *config = dev->config; struct voltage_data *data = dev->data; - int32_t raw_val = data->raw; + int32_t raw_val; int32_t v_mv; int ret; @@ -57,6 +57,15 @@ static int get(const struct device *dev, enum sensor_channel chan, struct sensor return -ENOTSUP; } + if (config->voltage.port.channel_cfg.differential) { + raw_val = (int16_t)data->raw; + } else if (config->voltage.port.resolution < 16) { + /* Can be removed when issue #71119 is resolved */ + raw_val = (int16_t)data->raw; + } else { + raw_val = data->raw; + } + ret = adc_raw_to_millivolts_dt(&config->voltage.port, &raw_val); if (ret != 0) { LOG_ERR("raw_to_mv: %d", ret); From 0f3bcde2bb9974006732e94bbaf22cab75e2bd64 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0953/1389] dts: bindings: Add vendor prefix festo Add vendor prefix for Festo SE & Co. KG Signed-off-by: Jeppe Odgaard --- dts/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index a6121e34194f6e..4cc0cae7e82f7e 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -232,6 +232,7 @@ fastrax Fastrax Oy fcs Fairchild Semiconductor feixin Shenzhen Feixin Photoelectic Co., Ltd feiyang Shenzhen Fly Young Technology Co.,LTD. +festo Festo SE & Co. KG fii Foxconn Industrial Internet fintek Feature Integration Technology Inc. firefly Firefly From 62647ab782ceb5379e4dc34cedf2bbc11de8a374 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0954/1389] dts: bindings: add festo_veaa_x_3 support Add bindings for the Festo proportional pressure regulator. Signed-off-by: Jeppe Odgaard --- dts/bindings/sensor/festo,veaa-x-3.yaml | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 dts/bindings/sensor/festo,veaa-x-3.yaml diff --git a/dts/bindings/sensor/festo,veaa-x-3.yaml b/dts/bindings/sensor/festo,veaa-x-3.yaml new file mode 100644 index 00000000000000..38529ab240d292 --- /dev/null +++ b/dts/bindings/sensor/festo,veaa-x-3.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024 Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +description: | + Festo VEAA proportional pressure regulator using 3/3-way valve. + Only voltage controlled valve is supported. + +compatible: "festo,veaa-x-3" + +include: sensor-device.yaml + +properties: + io-channels: + type: phandle-array + required: true + description: | + ADC used to get the actual value: + <&adc_node channel> + dac: + type: phandle + required: true + description: | + DAC used to set the setpoint value: + <&dac_node channel resolution buffered> + dac-channel-id: + type: int + required: true + dac-resolution: + type: int + required: true + pressure-range-type: + type: string + enum: ["D2", "D9", "D11"] + required: true + description: | + The device pressure range type. + | Type | Range [kPa] | + | D11 | 5-1000 | + | D9 | 3-600 | + | D2 | 1-200 | From 8bfe8ed5bfd59452fce71c3f110b8b7eaaea252c Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0955/1389] drivers: sensors: add veaa_x_3 proportional pressure regulator sensor Add driver for Festo VEAA-X-3 series proportional pressure regulator. The driver assumes that the maximum ADC value matches the maximum output from the device, and that the maximum DAC value matches the maximum input value for the device. External hardware is probably required between the ADC/DAC and the device. Signed-off-by: Jeppe Odgaard --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 1 + drivers/sensor/veaa_x_3/CMakeLists.txt | 5 + drivers/sensor/veaa_x_3/Kconfig | 18 ++ drivers/sensor/veaa_x_3/veaa_x_3.c | 217 +++++++++++++++++++++++ include/zephyr/drivers/sensor/veaa_x_3.h | 27 +++ 6 files changed, 269 insertions(+) create mode 100644 drivers/sensor/veaa_x_3/CMakeLists.txt create mode 100644 drivers/sensor/veaa_x_3/Kconfig create mode 100644 drivers/sensor/veaa_x_3/veaa_x_3.c create mode 100644 include/zephyr/drivers/sensor/veaa_x_3.h diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 0c1ec766321d41..76a8cff9b96bba 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -62,6 +62,7 @@ add_subdirectory_ifdef(CONFIG_SBS_GAUGE sbs_gauge) add_subdirectory_ifdef(CONFIG_SX9500 sx9500) add_subdirectory_ifdef(CONFIG_TH02 th02) add_subdirectory_ifdef(CONFIG_TSIC_XX6 tsic_xx6) +add_subdirectory_ifdef(CONFIG_VEAA_X_3 veaa_x_3) add_subdirectory_ifdef(CONFIG_VOLTAGE_DIVIDER voltage_divider) add_subdirectory_ifdef(CONFIG_TACH_ENE_KB1200 ene_tach_kb1200) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 5f264cc05c1292..85589a541c959a 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -143,6 +143,7 @@ source "drivers/sensor/sbs_gauge/Kconfig" source "drivers/sensor/sx9500/Kconfig" source "drivers/sensor/th02/Kconfig" source "drivers/sensor/tsic_xx6/Kconfig" +source "drivers/sensor/veaa_x_3/Kconfig" source "drivers/sensor/voltage_divider/Kconfig" source "drivers/sensor/ene_tach_kb1200/Kconfig" diff --git a/drivers/sensor/veaa_x_3/CMakeLists.txt b/drivers/sensor/veaa_x_3/CMakeLists.txt new file mode 100644 index 00000000000000..07db16869425c3 --- /dev/null +++ b/drivers/sensor/veaa_x_3/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(veaa_x_3.c) diff --git a/drivers/sensor/veaa_x_3/Kconfig b/drivers/sensor/veaa_x_3/Kconfig new file mode 100644 index 00000000000000..143618c6838aa7 --- /dev/null +++ b/drivers/sensor/veaa_x_3/Kconfig @@ -0,0 +1,18 @@ +# VEAA-X-3 configuration options + +# Copyright (c) 2024, Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +config VEAA_X_3 + bool "VEAA-X-3 pressure driver" + default y + depends on DT_HAS_FESTO_VEAA_X_3_ENABLED + depends on ADC + depends on DAC + help + Enable driver for Festo VEAA-X-3. + + The driver assumes that the maximum ADC value matches the maximum + output from the device, and that the maximum DAC value matches the + maximum input value for the device. External hardware is probably + required between the ADC/DAC and the device. diff --git a/drivers/sensor/veaa_x_3/veaa_x_3.c b/drivers/sensor/veaa_x_3/veaa_x_3.c new file mode 100644 index 00000000000000..c5935942069e76 --- /dev/null +++ b/drivers/sensor/veaa_x_3/veaa_x_3.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2024, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.festo.com/media/pim/620/D15000100140620.PDF + * + */ + +#define DT_DRV_COMPAT festo_veaa_x_3 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(veaa_x_3_sensor, CONFIG_SENSOR_LOG_LEVEL); + +struct veaa_x_3_data { + uint16_t adc_buf; +}; + +struct veaa_x_3_cfg { + const struct adc_dt_spec adc; + const struct device *dac; + const uint8_t dac_channel; + const uint8_t dac_resolution; + const uint16_t kpa_max; + const uint8_t kpa_min; +}; + +static uint16_t veaa_x_3_kpa_range(const struct veaa_x_3_cfg *cfg) +{ + return cfg->kpa_max - cfg->kpa_min; +} + +static int veaa_x_3_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + const struct veaa_x_3_cfg *cfg = dev->config; + uint32_t tmp; + + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + + switch ((enum sensor_attribute_veaa_x_3)attr) { + case SENSOR_ATTR_VEAA_X_3_SETPOINT: + if (val->val1 > cfg->kpa_max || val->val1 < cfg->kpa_min) { + LOG_ERR("%d kPa outside range", val->val1); + return -EINVAL; + } + + /* Convert from kPa to DAC value */ + tmp = val->val1 - cfg->kpa_min; + if (u32_mul_overflow(tmp, BIT(cfg->dac_resolution) - 1, &tmp)) { + LOG_ERR("kPa to DAC overflow"); + return -ERANGE; + } + tmp /= veaa_x_3_kpa_range(cfg); + + return dac_write_value(cfg->dac, cfg->dac_channel, tmp); + default: + return -ENOTSUP; + } +} + +static int veaa_x_3_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + const struct veaa_x_3_cfg *cfg = dev->config; + + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + + switch ((enum sensor_attribute_veaa_x_3)attr) { + case SENSOR_ATTR_VEAA_X_3_RANGE: + val->val1 = cfg->kpa_min; + val->val2 = cfg->kpa_max; + return 0; + default: + return -ENOTSUP; + } +} + +static int veaa_x_3_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + int rc; + const struct veaa_x_3_cfg *cfg = dev->config; + struct veaa_x_3_data *data = dev->data; + struct adc_sequence sequence = { + .buffer = &data->adc_buf, + .buffer_size = sizeof(data->adc_buf), + }; + + if (chan != SENSOR_CHAN_PRESS && chan != SENSOR_CHAN_ALL) { + return -ENOTSUP; + } + + rc = adc_sequence_init_dt(&cfg->adc, &sequence); + if (rc != 0) { + return rc; + } + sequence.options = NULL; + sequence.buffer = &data->adc_buf; + sequence.buffer_size = sizeof(data->adc_buf); + sequence.calibrate = false; + + rc = adc_read_dt(&cfg->adc, &sequence); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int veaa_x_3_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct veaa_x_3_cfg *cfg = dev->config; + struct veaa_x_3_data *data = dev->data; + const uint32_t max_adc_val = BIT(cfg->adc.resolution) - 1; + + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + + /* Convert from ADC value to kPa */ + if (u32_mul_overflow(data->adc_buf, veaa_x_3_kpa_range(cfg), &val->val1)) { + LOG_ERR("ADC to kPa overflow"); + return -ERANGE; + } + val->val2 = (val->val1 % max_adc_val) * 1000000 / max_adc_val; + val->val1 = (val->val1 / max_adc_val) + cfg->kpa_min; + + return 0; +} + +static const struct sensor_driver_api veaa_x_3_api_funcs = { + .attr_set = veaa_x_3_attr_set, + .attr_get = veaa_x_3_attr_get, + .sample_fetch = veaa_x_3_sample_fetch, + .channel_get = veaa_x_3_channel_get, +}; + +static int veaa_x_3_init(const struct device *dev) +{ + int rc; + const struct veaa_x_3_cfg *cfg = dev->config; + const struct dac_channel_cfg dac_cfg = { + .channel_id = cfg->dac_channel, + .resolution = cfg->dac_resolution, + .buffered = false, + }; + + LOG_DBG("Initializing %s with range %u-%u kPa", dev->name, cfg->kpa_min, cfg->kpa_max); + + if (!adc_is_ready_dt(&cfg->adc)) { + LOG_ERR("ADC not ready"); + return -ENODEV; + } + + rc = adc_channel_setup_dt(&cfg->adc); + if (rc != 0) { + LOG_ERR("%s setup failed: %d", cfg->adc.dev->name, rc); + return -ENODEV; + } + + if (!device_is_ready(cfg->dac)) { + LOG_ERR("DAC not ready"); + return -ENODEV; + } + + rc = dac_channel_setup(cfg->dac, &dac_cfg); + if (rc != 0) { + LOG_ERR("%s setup failed: %d", cfg->dac->name, rc); + return -ENODEV; + } + + return 0; +} + +#define VEAA_X_3_RANGE_KPA_INIT(n) \ + COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d11), ({.max = 1000, min = 5}), \ + (COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d9), \ + ({.max = 600, min = 3}), ({.max = 200, .min = 1})))) + +#define VEAA_X_3_TYPE_INIT(n) \ + COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d11), \ + (.kpa_max = 1000, .kpa_min = 5), \ + (COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d9), \ + (.kpa_max = 600, kpa_min = 3), (.kpa_max = 200, .kpa_min = 1)))) + +#define VEAA_X_3_INIT(n) \ + \ + static struct veaa_x_3_data veaa_x_3_data_##n; \ + \ + static const struct veaa_x_3_cfg veaa_x_3_cfg_##n = { \ + .adc = ADC_DT_SPEC_INST_GET(n), \ + .dac = DEVICE_DT_GET(DT_INST_PHANDLE(n, dac)), \ + .dac_channel = DT_INST_PROP(n, dac_channel_id), \ + .dac_resolution = DT_INST_PROP(n, dac_resolution), \ + VEAA_X_3_TYPE_INIT(n)}; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, veaa_x_3_init, NULL, &veaa_x_3_data_##n, \ + &veaa_x_3_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &veaa_x_3_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(VEAA_X_3_INIT) diff --git a/include/zephyr/drivers/sensor/veaa_x_3.h b/include/zephyr/drivers/sensor/veaa_x_3.h new file mode 100644 index 00000000000000..de08f07aedccdf --- /dev/null +++ b/include/zephyr/drivers/sensor/veaa_x_3.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_VEAA_X_3_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_VEAA_X_3_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_attribute_veaa_x_3 { + /* Set pressure setpoint value in kPa. */ + SENSOR_ATTR_VEAA_X_3_SETPOINT = SENSOR_ATTR_PRIV_START, + /* Supported pressure range in kPa. val1 is minimum and val2 is maximum */ + SENSOR_ATTR_VEAA_X_3_RANGE, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_VEAA_X_3_H_ */ From 92f22d0a1430c56b4f7313e33b50ecec114473f2 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0956/1389] samples: sensors: add veaa_x_3 sample Add sample for VEAA-X-3 sensor. Signed-off-by: Jeppe Odgaard --- samples/sensor/veaa_x_3/CMakeLists.txt | 8 +++ samples/sensor/veaa_x_3/Kconfig | 23 ++++++ samples/sensor/veaa_x_3/README.rst | 38 ++++++++++ .../veaa_x_3/boards/nucleo_h563zi.overlay | 35 +++++++++ samples/sensor/veaa_x_3/prj.conf | 4 ++ samples/sensor/veaa_x_3/sample.yaml | 8 +++ samples/sensor/veaa_x_3/src/main.c | 71 +++++++++++++++++++ 7 files changed, 187 insertions(+) create mode 100644 samples/sensor/veaa_x_3/CMakeLists.txt create mode 100644 samples/sensor/veaa_x_3/Kconfig create mode 100644 samples/sensor/veaa_x_3/README.rst create mode 100644 samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay create mode 100644 samples/sensor/veaa_x_3/prj.conf create mode 100644 samples/sensor/veaa_x_3/sample.yaml create mode 100644 samples/sensor/veaa_x_3/src/main.c diff --git a/samples/sensor/veaa_x_3/CMakeLists.txt b/samples/sensor/veaa_x_3/CMakeLists.txt new file mode 100644 index 00000000000000..e43b188ab7d9cb --- /dev/null +++ b/samples/sensor/veaa_x_3/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(app) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/sensor/veaa_x_3/Kconfig b/samples/sensor/veaa_x_3/Kconfig new file mode 100644 index 00000000000000..7eca02930fd6b6 --- /dev/null +++ b/samples/sensor/veaa_x_3/Kconfig @@ -0,0 +1,23 @@ +# +# Copyright (c) 2024 Vitrolife A/S +# +# SPDX-License-Identifier: Apache-2.0 +# + +mainmenu "VEAA sample application" + +config SAMPLE_USE_SHELL + bool "Use sensor shell and disable loop" + default n + select SHELL + select SENSOR_SHELL + +config SAMPLE_LOOP_INTERVAL + int "Sample loop delay in milliseconds" + default 200 + +config SAMPLE_LOOP_INCREMENT + int "Sample kPa increment per loop" + default 1 + +source "Kconfig.zephyr" diff --git a/samples/sensor/veaa_x_3/README.rst b/samples/sensor/veaa_x_3/README.rst new file mode 100644 index 00000000000000..09d85eacacfab3 --- /dev/null +++ b/samples/sensor/veaa_x_3/README.rst @@ -0,0 +1,38 @@ +.. veaa_x_3: + +VEAA-X-3 sample +########################## + +Overview +******** + +A sensor sample that demonstrates how to use a VEAA-X-3 device. + +Building and Running +******************** + +This sample sets the valve setpoint then reads the actual pressure. +This is done continuously. When the maximum supported pressure is reached the setpoint is reset to +the valve's minimum supported pressure value. + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/veaa_x_3 + :board: + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + Testing test_veaa_x_3 + Valve range: 1 to 200 kPa + Setpoint: 1 kPa, actual: 1 kPa + Setpoint: 2 kPa, actual: 2 kPa + Setpoint: 3 kPa, actual: 3 kPa + ... + Setpoint: 199 kPa, actual: 199 kPa + Setpoint: 200 kPa, actual: 200 kPa + Setpoint: 1 kPa, actual: 1 kPa + diff --git a/samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay b/samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay new file mode 100644 index 00000000000000..10b9676ac80be3 --- /dev/null +++ b/samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024, Vitrolife A/S + */ + +/* spi1 sck conflicts with dac1 channel 3 */ +/delete-node/ &spi1; + +/ { + test_veaa_x_3: test_veaa_x_3 { + status = "okay"; + compatible = "festo,veaa-x-3"; + io-channels = <&adc1 3>; + dac = <&dac1>; + dac-channel-id = <2>; + dac-resolution = <12>; + pressure-range-type = "D2"; + }; + +}; + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + +}; diff --git a/samples/sensor/veaa_x_3/prj.conf b/samples/sensor/veaa_x_3/prj.conf new file mode 100644 index 00000000000000..e0bc48f5dfef20 --- /dev/null +++ b/samples/sensor/veaa_x_3/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ADC=y +CONFIG_DAC=y +CONFIG_SENSOR=y +CONFIG_LOG=y diff --git a/samples/sensor/veaa_x_3/sample.yaml b/samples/sensor/veaa_x_3/sample.yaml new file mode 100644 index 00000000000000..2039dd9e7ed1a1 --- /dev/null +++ b/samples/sensor/veaa_x_3/sample.yaml @@ -0,0 +1,8 @@ +sample: + name: VEAA-X-3 sensor sample +tests: + sample.sensor.veaa_x_3: + harness: sensor + tags: sensors + filter: dt_compat_enabled("festo,veaa-x-3") + depends_on: adc dac diff --git a/samples/sensor/veaa_x_3/src/main.c b/samples/sensor/veaa_x_3/src/main.c new file mode 100644 index 00000000000000..db00cda87159bb --- /dev/null +++ b/samples/sensor/veaa_x_3/src/main.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024 Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static const struct device *const dev = DEVICE_DT_GET_ONE(festo_veaa_x_3); + +int main(void) +{ + int rc; + struct sensor_value range, setpoint, pressure; + + printk("Testing %s\n", dev->name); + + if (!device_is_ready(dev)) { + printk("%s not ready\n", dev->name); + return -ENODEV; + } + + rc = sensor_attr_get(dev, SENSOR_CHAN_PRESS, + (enum sensor_attribute)SENSOR_ATTR_VEAA_X_3_RANGE, &range); + if (rc != 0) { + printk("get range failed: %d\n", rc); + return rc; + } + printk("Valve range: %u to %u kPa\n", range.val1, range.val2); + + if (IS_ENABLED(CONFIG_SAMPLE_USE_SHELL)) { + printk("Loop is disabled. Use the `sensor` command to test %s", dev->name); + return 0; + } + + setpoint.val1 = range.val1; + while (1) { + rc = sensor_attr_set(dev, SENSOR_CHAN_PRESS, + (enum sensor_attribute)SENSOR_ATTR_VEAA_X_3_SETPOINT, + &setpoint); + if (rc != 0) { + printk("Set setpoint to %u failed: %d\n", setpoint.val1, rc); + } + + /* Sleep before get to allow DAC and ADC to stabilize */ + k_msleep(CONFIG_SAMPLE_LOOP_INTERVAL); + + rc = sensor_sample_fetch(dev); + if (rc != 0) { + printk("Fetch sample failed: %d", rc); + } + + rc = sensor_channel_get(dev, SENSOR_CHAN_PRESS, &pressure); + if (rc != 0) { + printk("Get sample failed: %d", rc); + } + + printk("Setpoint: %4u kPa, actual: %4u kPa\n", setpoint.val1, pressure.val1); + + setpoint.val1 += CONFIG_SAMPLE_LOOP_INCREMENT; + if (setpoint.val1 > range.val2) { + setpoint.val1 = range.val1; + } + } + + return 0; +} From a3ec183d6ae8a20bc0f333a3b6ba48a752a09886 Mon Sep 17 00:00:00 2001 From: Bartosz Bilas Date: Sun, 26 May 2024 22:39:17 +0200 Subject: [PATCH 0957/1389] drivers: spi: remove deprecated spi_is_ready function `spi_is_ready` is depreceted since v3.3 so let's remove it. Signed-off-by: Bartosz Bilas --- doc/releases/release-notes-3.7.rst | 4 ++++ include/zephyr/drivers/spi.h | 26 +------------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index bada6224280036..548b723bdd962e 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -60,6 +60,10 @@ Deprecated in this release Application developer will now need to set the advertised name themselves by updating the advertising data or the scan response data. + * SPI + + * Deprecated :c:func:`spi_is_ready` API function has been removed. + Architectures ************* diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index 067d3419de5ab4..be4e983990b4d8 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -389,9 +389,8 @@ struct spi_dt_spec { * data from the devicetree. * * Important: multiple fields are automatically constructed by this macro - * which must be checked before use. @ref spi_is_ready performs the required + * which must be checked before use. @ref spi_is_ready_dt performs the required * @ref device_is_ready checks. - * @deprecated Use @ref spi_is_ready_dt instead. * * @param node_id Devicetree node identifier for the SPI device whose * struct spi_dt_spec to create an initializer for @@ -683,29 +682,6 @@ static inline bool spi_cs_is_gpio_dt(const struct spi_dt_spec *spec) return spi_cs_is_gpio(&spec->config); } -/** - * @brief Validate that SPI bus is ready. - * - * @param spec SPI specification from devicetree - * - * @retval true if the SPI bus is ready for use. - * @retval false if the SPI bus is not ready for use. - */ -__deprecated -static inline bool spi_is_ready(const struct spi_dt_spec *spec) -{ - /* Validate bus is ready */ - if (!device_is_ready(spec->bus)) { - return false; - } - /* Validate CS gpio port is ready, if it is used */ - if (spi_cs_is_gpio_dt(spec) && - !gpio_is_ready_dt(&spec->config.cs.gpio)) { - return false; - } - return true; -} - /** * @brief Validate that SPI bus (and CS gpio if defined) is ready. * From 384022061541174b067d3709954f122fc9fcec9a Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0958/1389] soc: intel_adsp: tools: merge cavstool.py and acetool.py code Merge codebases of cavstool.py and acetool.py as the two have a lot of duplicated code. To ease with transition, keep acetool.py around with implementation imported from cavstool.py. This will help to keep any automated testing flows working that assume both tools exist. Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/tools/acetool.py | 721 +------------------------ soc/intel/intel_adsp/tools/cavstool.py | 259 +++++++-- 2 files changed, 228 insertions(+), 752 deletions(-) diff --git a/soc/intel/intel_adsp/tools/acetool.py b/soc/intel/intel_adsp/tools/acetool.py index 9dd184b9685fdb..5424e2a68ae817 100755 --- a/soc/intel/intel_adsp/tools/acetool.py +++ b/soc/intel/intel_adsp/tools/acetool.py @@ -2,728 +2,11 @@ # Copyright(c) 2022 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -import os -import sys -import struct -import logging import asyncio -import time -import subprocess -import ctypes -import mmap -import argparse - -start_output = True - -logging.basicConfig(level=logging.INFO) -log = logging.getLogger("ace-fw") - -PAGESZ = 4096 -HUGEPAGESZ = 2 * 1024 * 1024 -HUGEPAGE_FILE = "/dev/hugepages/ace-fw-dma.tmp." - -# SRAM windows. Each appears in a 128k region starting at 512k. -# -# Window 0 is the FW_STATUS area, and 4k after that the IPC "outbox" -# Window 1 is the IPC "inbox" (host-writable memory, just 384 bytes currently) -# Window 2 is unused by this script -# Window 3 is winstream-formatted log output -WINDOW_BASE = 0x180000 -WINDOW_STRIDE = 0x8000 - -OUTBOX_OFFSET = (512 + (0 * 128)) * 1024 + 4096 -INBOX_OFFSET = (512 + (1 * 128)) * 1024 -WINSTREAM_OFFSET = WINDOW_BASE + WINDOW_STRIDE*3 - -# pylint: disable=duplicate-code - -# ADSPCS bits -CRST = 0 -CSTALL = 8 -SPA = 16 -CPA = 24 - -class HDAStream: - # creates an hda stream with at 2 buffers of buf_len - def __init__(self, stream_id: int): - self.stream_id = stream_id - self.base = hdamem + 0x0080 + (stream_id * 0x20) - log.info(f"Mapping registers for hda stream {self.stream_id} at base {self.base:x}") - - self.hda = Regs(hdamem) - self.hda.GCAP = 0x0000 - self.hda.GCTL = 0x0008 - self.hda.DPLBASE = 0x0070 - self.hda.DPUBASE = 0x0074 - self.hda.SPBFCH = 0x0700 - self.hda.SPBFCTL = 0x0704 - self.hda.PPCH = 0x0800 - self.hda.PPCTL = 0x0804 - self.hda.PPSTS = 0x0808 - self.hda.SPIB = 0x0708 + stream_id*0x08 - self.hda.freeze() - - self.regs = Regs(self.base) - self.regs.CTL = 0x00 - self.regs.STS = 0x03 - self.regs.LPIB = 0x04 - self.regs.CBL = 0x08 - self.regs.LVI = 0x0c - self.regs.FIFOW = 0x0e - self.regs.FIFOS = 0x10 - self.regs.FMT = 0x12 - self.regs.FIFOL= 0x14 - self.regs.BDPL = 0x18 - self.regs.BDPU = 0x1c - self.regs.freeze() - - self.dbg0 = Regs(hdamem + 0x0084 + (0x20*stream_id)) - self.dbg0.DPIB = 0x00 - self.dbg0.EFIFOS = 0x10 - self.dbg0.freeze() - - self.reset() - - def __del__(self): - self.reset() - - def config(self, buf_len: int): - log.info(f"Configuring stream {self.stream_id}") - self.buf_len = buf_len - log.info("Allocating huge page and setting up buffers") - self.mem, self.hugef, self.buf_list_addr, self.pos_buf_addr, self.n_bufs = self.setup_buf(buf_len) - - log.info("Setting buffer list, length, and stream id and traffic priority bit") - self.regs.CTL = ((self.stream_id & 0xFF) << 20) | (1 << 18) # must be set to something other than 0? - self.regs.BDPU = (self.buf_list_addr >> 32) & 0xffffffff - self.regs.BDPL = self.buf_list_addr & 0xffffffff - self.regs.CBL = buf_len - self.regs.LVI = self.n_bufs - 1 - self.mem.seek(0) - self.debug() - log.info(f"Configured stream {self.stream_id}") - - def write(self, data): - - bufl = min(len(data), self.buf_len) - log.info(f"Writing data to stream {self.stream_id}, len {bufl}, SPBFCTL {self.hda.SPBFCTL:x}, SPIB {self.hda.SPIB}") - self.mem[0:bufl] = data[0:bufl] - self.mem[bufl:bufl+bufl] = data[0:bufl] - self.hda.SPBFCTL |= (1 << self.stream_id) - self.hda.SPIB += bufl - log.info(f"Wrote data to stream {self.stream_id}, SPBFCTL {self.hda.SPBFCTL:x}, SPIB {self.hda.SPIB}") - - def start(self): - log.info(f"Starting stream {self.stream_id}, CTL {self.regs.CTL:x}") - self.regs.CTL |= 2 - log.info(f"Started stream {self.stream_id}, CTL {self.regs.CTL:x}") - - def stop(self): - log.info(f"Stopping stream {self.stream_id}, CTL {self.regs.CTL:x}") - self.regs.CTL &= 2 - time.sleep(0.1) - self.regs.CTL |= 1 - log.info(f"Stopped stream {self.stream_id}, CTL {self.regs.CTL:x}") - - def setup_buf(self, buf_len: int): - (mem, phys_addr, hugef) = map_phys_mem(self.stream_id) - - log.info(f"Mapped 2M huge page at 0x{phys_addr:x} for buf size ({buf_len})") - - # create two buffers in the page of buf_len and mark them - # in a buffer descriptor list for the hardware to use - buf0_len = buf_len - buf1_len = buf_len - bdl_off = buf0_len + buf1_len - # bdl is 2 (64bits, 16 bytes) per entry, we have two - mem[bdl_off:bdl_off + 32] = struct.pack("> self.stream_id) & 1, self.regs.CTL, self.regs.LPIB, self.regs.BDPU, - self.regs.BDPL, self.regs.CBL, self.regs.LVI) - log.debug(" FIFOW %d, FIFOS %d, FMT %x, FIFOL %d, DPIB %d, EFIFOS %d", - self.regs.FIFOW & 0x7, self.regs.FIFOS, self.regs.FMT, self.regs.FIFOL, self.dbg0.DPIB, self.dbg0.EFIFOS) - log.debug(" status: FIFORDY %d, DESE %d, FIFOE %d, BCIS %d", - (self.regs.STS >> 5) & 1, (self.regs.STS >> 4) & 1, (self.regs.STS >> 3) & 1, (self.regs.STS >> 2) & 1) - - def reset(self): - # Turn DMA off and reset the stream. Clearing START first is a - # noop per the spec, but absolutely required for stability. - # Apparently the reset doesn't stop the stream, and the next load - # starts before it's ready and kills the load (and often the DSP). - # The sleep too is required, on at least one board (a fast - # chromebook) putting the two writes next each other also hangs - # the DSP! - log.info(f"Resetting stream {self.stream_id}") - self.debug() - self.regs.CTL &= ~2 # clear START - time.sleep(0.1) - # set enter reset bit - self.regs.CTL = 1 - while (self.regs.CTL & 1) == 0: pass - # clear enter reset bit to exit reset - self.regs.CTL = 0 - while (self.regs.CTL & 1) == 1: pass - - log.info(f"Disable SPIB and set position 0 of stream {self.stream_id}") - self.hda.SPBFCTL = 0 - self.hda.SPIB = 0 - - #log.info("Setting dma position buffer and enable it") - #self.hda.DPUBASE = self.pos_buf_addr >> 32 & 0xffffffff - #self.hda.DPLBASE = self.pos_buf_addr & 0xfffffff0 | 1 - - log.info(f"Enabling dsp capture (PROCEN) of stream {self.stream_id}") - self.hda.PPCTL |= (1 << self.stream_id) - - self.debug() - log.info(f"Reset stream {self.stream_id}") - - -def map_regs(): - p = runx(f"grep -iEl 'PCI_CLASS=40(10|38)0' /sys/bus/pci/devices/*/uevent") - pcidir = os.path.dirname(p) - - # Platform/quirk detection. ID lists cribbed from the SOF kernel driver - did = int(open(f"{pcidir}/device").read().rstrip(), 16) - ace15 = did in [ 0x7e28 ] - ace20 = did in [ 0xa828 ] - if ace15: - log.info("Detected MTL hardware") - elif ace20: - log.info("Detected LNL hardware") - - # Check sysfs for a loaded driver and remove it - if os.path.exists(f"{pcidir}/driver"): - mod = os.path.basename(os.readlink(f"{pcidir}/driver/module")) - found_msg = f"Existing driver \"{mod}\" found" - if args.log_only: - log.info(found_msg) - else: - log.warning(found_msg + ", unloading module") - runx(f"rmmod -f {mod}") - # Disengage runtime power management so the kernel doesn't put it to sleep - log.info(f"Forcing {pcidir}/power/control to always 'on'") - with open(f"{pcidir}/power/control", "w") as ctrl: - ctrl.write("on") - - # Make sure PCI memory space access and busmastering are enabled. - # Also disable interrupts so as not to confuse the kernel. - with open(f"{pcidir}/config", "wb+") as cfg: - cfg.seek(4) - cfg.write(b'\x06\x04') - - # Standard HD Audio Registers - global hdamem - (hdamem, _) = bar_map(pcidir, 0) - hda = Regs(hdamem) - hda.GCAP = 0x0000 - hda.GCTL = 0x0008 - hda.SPBFCTL = 0x0704 - hda.PPCTL = 0x0804 - - # Find the ID of the first output stream - hda_ostream_id = (hda.GCAP >> 8) & 0x0f # number of input streams - log.info(f"Selected output stream {hda_ostream_id} (GCAP = 0x{hda.GCAP:x})") - hda.SD_SPIB = 0x0708 + (8 * hda_ostream_id) - hda.freeze() - - - # Standard HD Audio Stream Descriptor - sd = Regs(hdamem + 0x0080 + (hda_ostream_id * 0x20)) - sd.CTL = 0x00 - sd.CBL = 0x08 - sd.LVI = 0x0c - sd.BDPL = 0x18 - sd.BDPU = 0x1c - sd.freeze() - - # Intel ACE Audio DSP Registers - global bar4_mmap - (bar4_mem, bar4_mmap) = bar_map(pcidir, 4) - dsp = Regs(bar4_mem) - dsp.HFDSSCS = 0x1000 - dsp.HFPWRCTL = 0x1d18 - dsp.HFPWRSTS = 0x1d1c - dsp.DSP2CXCTL_PRIMARY = 0x178d04 - dsp.HFIPCXTDR = 0x73200 - dsp.HFIPCXTDA = 0x73204 - dsp.HFIPCXIDR = 0x73210 - dsp.HFIPCXIDA = 0x73214 - dsp.HFIPCXCTL = 0x73228 - dsp.HFIPCXTDDY = 0x73300 - dsp.HFIPCXIDDY = 0x73380 - dsp.SRAM_FW_STATUS = WINDOW_BASE - dsp.freeze() - - return (hda, sd, dsp, hda_ostream_id) - -def setup_dma_mem(fw_bytes): - (mem, phys_addr, _) = map_phys_mem(hda_ostream_id) - mem[0:len(fw_bytes)] = fw_bytes - - log.info("Mapped 2M huge page at 0x%x to contain %d bytes of firmware" - % (phys_addr, len(fw_bytes))) - - # HDA requires at least two buffers be defined, but we don't care about - # boundaries because it's all a contiguous region. Place a vestigial - # 128-byte (minimum size and alignment) buffer after the main one, and put - # the 4-entry BDL list into the final 128 bytes of the page. - buf0_len = HUGEPAGESZ - 2 * 128 - buf1_len = 128 - bdl_off = buf0_len + buf1_len - mem[bdl_off:bdl_off + 32] = struct.pack(" /proc/sys/vm/nr_hugepages") - - hugef_name = HUGEPAGE_FILE + str(stream_id) - hugef = open(hugef_name, "w+") - hugef.truncate(HUGEPAGESZ) - mem = mmap.mmap(hugef.fileno(), HUGEPAGESZ) - log.info("type of mem is %s", str(type(mem))) - global_mmaps.append(mem) - os.unlink(hugef_name) - - # Find the local process address of the mapping, then use that to extract - # the physical address from the kernel's pagemap interface. The physical - # page frame number occupies the bottom bits of the entry. - mem[0] = 0 # Fault the page in so it has an address! - vaddr = ctypes.addressof(ctypes.c_int.from_buffer(mem)) - vpagenum = vaddr >> 12 - pagemap = open("/proc/self/pagemap", "rb") - pagemap.seek(vpagenum * 8) - pent = pagemap.read(8) - paddr = (struct.unpack("Q", pent)[0] & ((1 << 55) - 1)) * PAGESZ - pagemap.close() - return (mem, paddr, hugef) - -# Maps a PCI BAR and returns the in-process address -def bar_map(pcidir, barnum): - f = open(pcidir + "/resource" + str(barnum), "r+") - mm = mmap.mmap(f.fileno(), os.fstat(f.fileno()).st_size) - global_mmaps.append(mm) - log.info("Mapped PCI bar %d of length %d bytes." - % (barnum, os.fstat(f.fileno()).st_size)) - return (ctypes.addressof(ctypes.c_int.from_buffer(mm)), mm) - -# Syntactic sugar to make register block definition & use look nice. -# Instantiate from a base address, assign offsets to (uint32) named registers as -# fields, call freeze(), then the field acts as a direct alias for the register! -class Regs: - def __init__(self, base_addr): - vars(self)["base_addr"] = base_addr - vars(self)["ptrs"] = {} - vars(self)["frozen"] = False - def freeze(self): - vars(self)["frozen"] = True - def __setattr__(self, name, val): - if not self.frozen and name not in self.ptrs: - addr = self.base_addr + val - self.ptrs[name] = ctypes.c_uint32.from_address(addr) - else: - self.ptrs[name].value = val - def __getattr__(self, name): - return self.ptrs[name].value - -def runx(cmd): - return subprocess.check_output(cmd, shell=True).decode().rstrip() - -def load_firmware(fw_file): - try: - fw_bytes = open(fw_file, "rb").read() - # Resize fw_bytes for MTL - if len(fw_bytes) < 512 * 1024: - fw_bytes += b'\x00' * (512 * 1024 - len(fw_bytes)) - except Exception as e: - log.error(f"Could not read firmware file: `{fw_file}'") - log.error(e) - sys.exit(1) - - (magic, sz) = struct.unpack("4sI", fw_bytes[0:8]) - if magic == b'$AE1': - log.info(f"Trimming {sz} bytes of extended manifest") - fw_bytes = fw_bytes[sz:len(fw_bytes)] - - # This actually means "enable access to BAR4 registers"! - hda.PPCTL |= (1 << 30) # GPROCEN, "global processing enable" - - log.info("Resetting HDA device") - hda.GCTL = 0 - while hda.GCTL & 1: pass - hda.GCTL = 1 - while not hda.GCTL & 1: pass - - log.info("Turning of DSP subsystem") - dsp.HFDSSCS &= ~(1 << 16) # clear SPA bit - time.sleep(0.002) - # wait for CPA bit clear - while dsp.HFDSSCS & (1 << 24): - log.info("Waiting for DSP subsystem power off") - time.sleep(0.1) - - log.info("Turning on DSP subsystem") - dsp.HFDSSCS |= (1 << 16) # set SPA bit - time.sleep(0.002) # needed as the CPA bit may be unstable - # wait for CPA bit - while not dsp.HFDSSCS & (1 << 24): - log.info("Waiting for DSP subsystem power on") - time.sleep(0.1) - - log.info("Turning on Domain0") - dsp.HFPWRCTL |= 0x1 # set SPA bit - time.sleep(0.002) # needed as the CPA bit may be unstable - # wait for CPA bit - while not dsp.HFPWRSTS & 0x1: - log.info("Waiting for DSP domain0 power on") - time.sleep(0.1) - - log.info("Turning off Primary Core") - dsp.DSP2CXCTL_PRIMARY &= ~(0x1) # clear SPA - time.sleep(0.002) # wait for CPA settlement - while dsp.DSP2CXCTL_PRIMARY & (1 << 8): - log.info("Waiting for DSP primary core power off") - time.sleep(0.1) - - - log.info(f"Configuring HDA stream {hda_ostream_id} to transfer firmware image") - (buf_list_addr, num_bufs) = setup_dma_mem(fw_bytes) - sd.CTL = 1 - while (sd.CTL & 1) == 0: pass - sd.CTL = 0 - while (sd.CTL & 1) == 1: pass - sd.CTL |= (1 << 20) # Set stream ID to anything non-zero - sd.BDPU = (buf_list_addr >> 32) & 0xffffffff - sd.BDPL = buf_list_addr & 0xffffffff - sd.CBL = len(fw_bytes) - sd.LVI = num_bufs - 1 - hda.PPCTL |= (1 << hda_ostream_id) - - # SPIB ("Software Position In Buffer") is an Intel HDA extension - # that puts a transfer boundary into the stream beyond which the - # other side will not read. The ROM wants to poll on a "buffer - # full" bit on the other side that only works with this enabled. - hda.SPBFCTL |= (1 << hda_ostream_id) - hda.SD_SPIB = len(fw_bytes) - - - # Send the DSP an IPC message to tell the device how to boot. - # Note: with cAVS 1.8+ the ROM receives the stream argument as an - # index within the array of output streams (and we always use the - # first one by construction). But with 1.5 it's the HDA index, - # and depends on the number of input streams on the device. - stream_idx = 0 - ipcval = ( (1 << 31) # BUSY bit - | (0x01 << 24) # type = PURGE_FW - | (1 << 14) # purge_fw = 1 - | (stream_idx << 9)) # dma_id - log.info(f"Sending IPC command, HFIPCXIDR = 0x{ipcval:x}") - dsp.HFIPCXIDR = ipcval - - - log.info("Turning on Primary Core") - dsp.DSP2CXCTL_PRIMARY |= 0x1 # clear SPA - time.sleep(0.002) # wait for CPA settlement - while not dsp.DSP2CXCTL_PRIMARY & (1 << 8): - log.info("Waiting for DSP primary core power on") - time.sleep(0.1) - - log.info("Waiting for IPC acceptance") - while dsp.HFIPCXIDR & (1 << 31): - log.info("Waiting for IPC busy bit clear") - time.sleep(0.1) - - log.info("ACK IPC") - dsp.HFIPCXIDA |= (1 << 31) - - log.info(f"Starting DMA, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}") - sd.CTL |= 2 # START flag - - wait_fw_entered() - - # Turn DMA off and reset the stream. Clearing START first is a - # noop per the spec, but absolutely required for stability. - # Apparently the reset doesn't stop the stream, and the next load - # starts before it's ready and kills the load (and often the DSP). - # The sleep too is required, on at least one board (a fast - # chromebook) putting the two writes next each other also hangs - # the DSP! - sd.CTL &= ~2 # clear START - time.sleep(0.1) - sd.CTL |= 1 - log.info(f"cAVS firmware load complete") - -def fw_is_alive(): - return dsp.SRAM_FW_STATUS & ((1 << 28) - 1) == 5 # "FW_ENTERED" - -def wait_fw_entered(timeout_s=2): - log.info("Waiting %s for firmware handoff, FW_STATUS = 0x%x", - "forever" if timeout_s is None else f"{timeout_s} seconds", - dsp.SRAM_FW_STATUS) - hertz = 100 - attempts = None if timeout_s is None else timeout_s * hertz - while True: - alive = fw_is_alive() - if alive: - break - if attempts is not None: - attempts -= 1 - if attempts < 0: - break - time.sleep(1 / hertz) - - if not alive: - log.warning("Load failed? FW_STATUS = 0x%x", dsp.SRAM_FW_STATUS) - else: - log.info("FW alive, FW_STATUS = 0x%x", dsp.SRAM_FW_STATUS) - - -# This SHOULD be just "mem[start:start+length]", but slicing an mmap -# array seems to be unreliable on one of my machines (python 3.6.9 on -# Ubuntu 18.04). Read out bytes individually. -def win_read(start, length): - try: - return b''.join(bar4_mmap[WINSTREAM_OFFSET + x].to_bytes(1, 'little') - for x in range(start, start + length)) - except IndexError as ie: - # A FW in a bad state may cause winstream garbage - log.error("IndexError in bar4_mmap[%d + %d]", WINSTREAM_OFFSET, start) - log.error("bar4_mmap.size()=%d", bar4_mmap.size()) - raise ie - -def win_hdr(): - return struct.unpack(" ((end - start) % wlen): - return (seq, "") - copy = (end - behind) % wlen - suffix = min(behind, wlen - copy) - result = win_read(16 + copy, suffix) - if suffix < behind: - result += win_read(16, behind - suffix) - (wlen, start1, end, seq1) = win_hdr() - if start1 == start and seq1 == seq: - # Best effort attempt at decoding, replacing unusable characters - # Found to be useful when it really goes wrong - return (seq, result.decode("utf-8", "replace")) - - -async def ipc_delay_done(): - await asyncio.sleep(0.1) - dsp.HFIPCXTDA = ~(1<<31) & dsp.HFIPCXTDA # Signal done - - -ipc_timestamp = 0 - -# Super-simple command language, driven by the test code on the DSP -def ipc_command(data, ext_data): - send_msg = False - done = True - log.debug ("ipc data %d, ext_data %x", data, ext_data) - if data == 0: # noop, with synchronous DONE - pass - elif data == 1: # async command: signal DONE after a delay (on 1.8+) - done = False - asyncio.ensure_future(ipc_delay_done()) - elif data == 2: # echo back ext_data as a message command - send_msg = True - elif data == 3: # set ADSPCS - dsp.ADSPCS = ext_data - elif data == 4: # echo back microseconds since last timestamp command - global ipc_timestamp - t = round(time.time() * 1e6) - ext_data = t - ipc_timestamp - ipc_timestamp = t - send_msg = True - elif data == 5: # copy word at outbox[ext_data >> 16] to inbox[ext_data & 0xffff] - src = OUTBOX_OFFSET + 4 * (ext_data >> 16) - dst = INBOX_OFFSET + 4 * (ext_data & 0xffff) - for i in range(4): - bar4_mmap[dst + i] = bar4_mmap[src + i] - elif data == 6: # HDA RESET (init if not exists) - stream_id = ext_data & 0xff - if stream_id in hda_streams: - hda_streams[stream_id].reset() - else: - hda_str = HDAStream(stream_id) - hda_streams[stream_id] = hda_str - elif data == 7: # HDA CONFIG - stream_id = ext_data & 0xFF - buf_len = ext_data >> 8 & 0xFFFF - hda_str = hda_streams[stream_id] - hda_str.config(buf_len) - elif data == 8: # HDA START - stream_id = ext_data & 0xFF - hda_streams[stream_id].start() - hda_streams[stream_id].mem.seek(0) - - elif data == 9: # HDA STOP - stream_id = ext_data & 0xFF - hda_streams[stream_id].stop() - elif data == 10: # HDA VALIDATE - stream_id = ext_data & 0xFF - hda_str = hda_streams[stream_id] - hda_str.debug() - is_ramp_data = True - hda_str.mem.seek(0) - for (i, val) in enumerate(hda_str.mem.read(256)): - if i != val: - is_ramp_data = False - # log.info("stream[%d][%d]: %d", stream_id, i, val) # debug helper - log.info("Is ramp data? " + str(is_ramp_data)) - ext_data = int(is_ramp_data) - log.info(f"Ext data to send back on ramp status {ext_data}") - send_msg = True - elif data == 11: # HDA HOST OUT SEND - stream_id = ext_data & 0xff - buf = bytearray(256) - for i in range(0, 256): - buf[i] = i - hda_streams[stream_id].write(buf) - elif data == 12: # HDA PRINT - stream_id = ext_data & 0xFF - buf_len = ext_data >> 8 & 0xFFFF - hda_str = hda_streams[stream_id] - # check for wrap here - pos = hda_str.mem.tell() - read_lens = [buf_len, 0] - if pos + buf_len >= hda_str.buf_len*2: - read_lens[0] = hda_str.buf_len*2 - pos - read_lens[1] = buf_len - read_lens[0] - # validate the read lens - assert (read_lens[0] + pos) <= (hda_str.buf_len*2) - assert read_lens[0] % 128 == 0 - assert read_lens[1] % 128 == 0 - buf_data0 = hda_str.mem.read(read_lens[0]) - hda_msg0 = buf_data0.decode("utf-8", "replace") - sys.stdout.write(hda_msg0) - if read_lens[1] != 0: - hda_str.mem.seek(0) - buf_data1 = hda_str.mem.read(read_lens[1]) - hda_msg1 = buf_data1.decode("utf-8", "replace") - sys.stdout.write(hda_msg1) - pos = hda_str.mem.tell() - sys.stdout.flush() - else: - log.warning(f"acetool: Unrecognized IPC command 0x{data:x} ext 0x{ext_data:x}") - if not fw_is_alive(): - if args.log_only: - log.info("DSP power seems off") - wait_fw_entered(timeout_s=None) - else: - log.warning("DSP power seems off?!") - time.sleep(2) # potential spam reduction - - return - - dsp.HFIPCXTDR = 1<<31 # Ack local interrupt, also signals DONE on v1.5 - if done: - dsp.HFIPCXTDA = ~(1<<31) & dsp.HFIPCXTDA # Signal done - if send_msg: - log.debug("ipc: sending msg 0x%08x" % ext_data) - dsp.HFIPCXIDDY = ext_data - dsp.HFIPCXIDR = (1<<31) | ext_data - -async def main(): - #TODO this bit me, remove the globals, write a little FirmwareLoader class or something to contain. - global hda, sd, dsp, hda_ostream_id, hda_streams - - try: - (hda, sd, dsp, hda_ostream_id) = map_regs() - except Exception as e: - log.error("Could not map device in sysfs; run as root?") - log.error(e) - sys.exit(1) - - if args.log_only: - wait_fw_entered(timeout_s=None) - else: - if not args.fw_file: - log.error("Firmware file argument missing") - sys.exit(1) - - load_firmware(args.fw_file) - time.sleep(0.1) - if not args.quiet: - sys.stdout.write("--\n") - - hda_streams = dict() - - last_seq = 0 - while start_output is True: - await asyncio.sleep(0.03) - (last_seq, output) = winstream_read(last_seq) - if output: - sys.stdout.write(output) - sys.stdout.flush() - if not args.log_only: - if dsp.HFIPCXIDA & 0x80000000: - log.debug("ipc: Ack DSP reply with IDA_DONE") - dsp.HFIPCXIDA = 1<<31 # must ACK any DONE interrupts that arrive! - if dsp.HFIPCXTDR & 0x80000000: - ipc_command(dsp.HFIPCXTDR & ~0x80000000, dsp.HFIPCXTDDY) - - -ap = argparse.ArgumentParser(description="DSP loader/logger tool", allow_abbrev=False) -ap.add_argument("-q", "--quiet", action="store_true", - help="No loader output, just DSP logging") -ap.add_argument("-v", "--verbose", action="store_true", - help="More loader output, DEBUG logging level") -ap.add_argument("-l", "--log-only", action="store_true", - help="Don't load firmware, just show log output") -ap.add_argument("-n", "--no-history", action="store_true", - help="No current log buffer at start, just new output") -ap.add_argument("fw_file", nargs="?", help="Firmware file") - -args = ap.parse_args() - -if args.quiet: - log.setLevel(logging.WARN) -elif args.verbose: - log.setLevel(logging.DEBUG) +import cavstool if __name__ == "__main__": try: - asyncio.get_event_loop().run_until_complete(main()) + asyncio.run(cavstool.main()) except KeyboardInterrupt: start_output = False diff --git a/soc/intel/intel_adsp/tools/cavstool.py b/soc/intel/intel_adsp/tools/cavstool.py index 97ce9134379105..3b82d5bf336487 100755 --- a/soc/intel/intel_adsp/tools/cavstool.py +++ b/soc/intel/intel_adsp/tools/cavstool.py @@ -21,15 +21,18 @@ HUGEPAGESZ = 2 * 1024 * 1024 HUGEPAGE_FILE = "/dev/hugepages/cavs-fw-dma.tmp." -# SRAM windows. Each appears in a 128k region starting at 512k. +# SRAM windows. Base and stride varies depending on ADSP version # # Window 0 is the FW_STATUS area, and 4k after that the IPC "outbox" # Window 1 is the IPC "inbox" (host-writable memory, just 384 bytes currently) -# Window 2 is unused by this script +# Window 2 is debug, divided into multiple slots, unused by this script # Window 3 is winstream-formatted log output -OUTBOX_OFFSET = (512 + (0 * 128)) * 1024 + 4096 -INBOX_OFFSET = (512 + (1 * 128)) * 1024 -WINSTREAM_OFFSET = (512 + (3 * 128)) * 1024 + +WINDOW_BASE = 0x80000 +WINDOW_STRIDE = 0x20000 + +WINDOW_BASE_ACE = 0x180000 +WINDOW_STRIDE_ACE = 0x8000 # pylint: disable=duplicate-code @@ -188,17 +191,34 @@ def reset(self): self.debug() log.info(f"Reset stream {self.stream_id}") +def adsp_is_cavs(): + return cavs15 or cavs18 or cavs15 + +def adsp_is_ace(): + return ace15 or ace20 + +def adsp_mem_window_config(): + if adsp_is_ace(): + base = WINDOW_BASE_ACE + stride = WINDOW_STRIDE_ACE + else: + base = WINDOW_BASE + stride = WINDOW_STRIDE + + return (base, stride) def map_regs(): p = runx(f"grep -iEl 'PCI_CLASS=40(10|38)0' /sys/bus/pci/devices/*/uevent") pcidir = os.path.dirname(p) # Platform/quirk detection. ID lists cribbed from the SOF kernel driver - global cavs15, cavs18, cavs25 + global cavs15, cavs18, cavs25, ace15, ace20 did = int(open(f"{pcidir}/device").read().rstrip(), 16) cavs15 = did in [ 0x5a98, 0x1a98, 0x3198 ] cavs18 = did in [ 0x9dc8, 0xa348, 0x02c8, 0x06c8, 0xa3f0 ] cavs25 = did in [ 0xa0c8, 0x43c8, 0x4b55, 0x4b58, 0x7ad0, 0x51c8 ] + ace15 = did in [ 0x7e28 ] + ace20 = did in [ 0xa828 ] # Check sysfs for a loaded driver and remove it if os.path.exists(f"{pcidir}/driver"): @@ -249,14 +269,28 @@ def map_regs(): global bar4_mmap (bar4_mem, bar4_mmap) = bar_map(pcidir, 4) dsp = Regs(bar4_mem) - dsp.ADSPCS = 0x00004 - dsp.HIPCTDR = 0x00040 if cavs15 else 0x000c0 - dsp.HIPCTDA = 0x000c4 # 1.8+ only - dsp.HIPCTDD = 0x00044 if cavs15 else 0x000c8 - dsp.HIPCIDR = 0x00048 if cavs15 else 0x000d0 - dsp.HIPCIDA = 0x000d4 # 1.8+ only - dsp.HIPCIDD = 0x0004c if cavs15 else 0x000d8 - dsp.SRAM_FW_STATUS = 0x80000 # Start of first SRAM window + if adsp_is_ace(): + dsp.HFDSSCS = 0x1000 + dsp.HFPWRCTL = 0x1d18 + dsp.HFPWRSTS = 0x1d1c + dsp.DSP2CXCTL_PRIMARY = 0x178d04 + dsp.HFIPCXTDR = 0x73200 + dsp.HFIPCXTDA = 0x73204 + dsp.HFIPCXIDR = 0x73210 + dsp.HFIPCXIDA = 0x73214 + dsp.HFIPCXCTL = 0x73228 + dsp.HFIPCXTDDY = 0x73300 + dsp.HFIPCXIDDY = 0x73380 + dsp.SRAM_FW_STATUS = WINDOW_BASE_ACE + else: + dsp.ADSPCS = 0x00004 + dsp.HIPCTDR = 0x00040 if cavs15 else 0x000c0 + dsp.HIPCTDA = 0x000c4 # 1.8+ only + dsp.HIPCTDD = 0x00044 if cavs15 else 0x000c8 + dsp.HIPCIDR = 0x00048 if cavs15 else 0x000d0 + dsp.HIPCIDA = 0x000d4 # 1.8+ only + dsp.HIPCIDD = 0x0004c if cavs15 else 0x000d8 + dsp.SRAM_FW_STATUS = WINDOW_BASE # Start of first SRAM window dsp.freeze() return (hda, sd, dsp, hda_ostream_id) @@ -461,6 +495,128 @@ def load_firmware(fw_file): sd.CTL |= 1 log.info(f"cAVS firmware load complete") +def load_firmware_ace(fw_file): + try: + fw_bytes = open(fw_file, "rb").read() + # Resize fw_bytes for MTL + if len(fw_bytes) < 512 * 1024: + fw_bytes += b'\x00' * (512 * 1024 - len(fw_bytes)) + except Exception as e: + log.error(f"Could not read firmware file: `{fw_file}'") + log.error(e) + sys.exit(1) + + (magic, sz) = struct.unpack("4sI", fw_bytes[0:8]) + if magic == b'$AE1': + log.info(f"Trimming {sz} bytes of extended manifest") + fw_bytes = fw_bytes[sz:len(fw_bytes)] + + # This actually means "enable access to BAR4 registers"! + hda.PPCTL |= (1 << 30) # GPROCEN, "global processing enable" + + log.info("Resetting HDA device") + hda.GCTL = 0 + while hda.GCTL & 1: pass + hda.GCTL = 1 + while not hda.GCTL & 1: pass + + log.info("Turning of DSP subsystem") + dsp.HFDSSCS &= ~(1 << 16) # clear SPA bit + time.sleep(0.002) + # wait for CPA bit clear + while dsp.HFDSSCS & (1 << 24): + log.info("Waiting for DSP subsystem power off") + time.sleep(0.1) + + log.info("Turning on DSP subsystem") + dsp.HFDSSCS |= (1 << 16) # set SPA bit + time.sleep(0.002) # needed as the CPA bit may be unstable + # wait for CPA bit + while not dsp.HFDSSCS & (1 << 24): + log.info("Waiting for DSP subsystem power on") + time.sleep(0.1) + + log.info("Turning on Domain0") + dsp.HFPWRCTL |= 0x1 # set SPA bit + time.sleep(0.002) # needed as the CPA bit may be unstable + # wait for CPA bit + while not dsp.HFPWRSTS & 0x1: + log.info("Waiting for DSP domain0 power on") + time.sleep(0.1) + + log.info("Turning off Primary Core") + dsp.DSP2CXCTL_PRIMARY &= ~(0x1) # clear SPA + time.sleep(0.002) # wait for CPA settlement + while dsp.DSP2CXCTL_PRIMARY & (1 << 8): + log.info("Waiting for DSP primary core power off") + time.sleep(0.1) + + log.info(f"Configuring HDA stream {hda_ostream_id} to transfer firmware image") + (buf_list_addr, num_bufs) = setup_dma_mem(fw_bytes) + sd.CTL = 1 + while (sd.CTL & 1) == 0: pass + sd.CTL = 0 + while (sd.CTL & 1) == 1: pass + sd.CTL |= (1 << 20) # Set stream ID to anything non-zero + sd.BDPU = (buf_list_addr >> 32) & 0xffffffff + sd.BDPL = buf_list_addr & 0xffffffff + sd.CBL = len(fw_bytes) + sd.LVI = num_bufs - 1 + hda.PPCTL |= (1 << hda_ostream_id) + + # SPIB ("Software Position In Buffer") is an Intel HDA extension + # that puts a transfer boundary into the stream beyond which the + # other side will not read. The ROM wants to poll on a "buffer + # full" bit on the other side that only works with this enabled. + hda.SPBFCTL |= (1 << hda_ostream_id) + hda.SD_SPIB = len(fw_bytes) + + + # Send the DSP an IPC message to tell the device how to boot. + # Note: with cAVS 1.8+ the ROM receives the stream argument as an + # index within the array of output streams (and we always use the + # first one by construction). But with 1.5 it's the HDA index, + # and depends on the number of input streams on the device. + stream_idx = 0 + ipcval = ( (1 << 31) # BUSY bit + | (0x01 << 24) # type = PURGE_FW + | (1 << 14) # purge_fw = 1 + | (stream_idx << 9)) # dma_id + log.info(f"Sending IPC command, HFIPCXIDR = 0x{ipcval:x}") + dsp.HFIPCXIDR = ipcval + + log.info("Turning on Primary Core") + dsp.DSP2CXCTL_PRIMARY |= 0x1 # clear SPA + time.sleep(0.002) # wait for CPA settlement + while not dsp.DSP2CXCTL_PRIMARY & (1 << 8): + log.info("Waiting for DSP primary core power on") + time.sleep(0.1) + + log.info("Waiting for IPC acceptance") + while dsp.HFIPCXIDR & (1 << 31): + log.info("Waiting for IPC busy bit clear") + time.sleep(0.1) + + log.info("ACK IPC") + dsp.HFIPCXIDA |= (1 << 31) + + log.info(f"Starting DMA, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}") + sd.CTL |= 2 # START flag + + wait_fw_entered() + + # Turn DMA off and reset the stream. Clearing START first is a + # noop per the spec, but absolutely required for stability. + # Apparently the reset doesn't stop the stream, and the next load + # starts before it's ready and kills the load (and often the DSP). + # The sleep too is required, on at least one board (a fast + # chromebook) putting the two writes next each other also hangs + # the DSP! + sd.CTL &= ~2 # clear START + time.sleep(0.1) + sd.CTL |= 1 + log.info(f"ACE firmware load complete") + def fw_is_alive(): return dsp.SRAM_FW_STATUS & ((1 << 28) - 1) == 5 # "FW_ENTERED" @@ -485,17 +641,20 @@ def wait_fw_entered(timeout_s=2): else: log.info("FW alive, FW_STATUS = 0x%x", dsp.SRAM_FW_STATUS) +def winstream_offset(): + ( base, stride ) = adsp_mem_window_config() + return base + stride * 3 # This SHOULD be just "mem[start:start+length]", but slicing an mmap # array seems to be unreliable on one of my machines (python 3.6.9 on # Ubuntu 18.04). Read out bytes individually. def win_read(start, length): try: - return b''.join(bar4_mmap[WINSTREAM_OFFSET + x].to_bytes(1, 'little') + return b''.join(bar4_mmap[winstream_offset() + x].to_bytes(1, 'little') for x in range(start, start + length)) except IndexError as ie: # A FW in a bad state may cause winstream garbage - log.error("IndexError in bar4_mmap[%d + %d]", WINSTREAM_OFFSET, start) + log.error("IndexError in bar4_mmap[%d + %d]", winstream_offset(), start) log.error("bar4_mmap.size()=%d", bar4_mmap.size()) raise ie @@ -528,7 +687,18 @@ def winstream_read(last_seq): async def ipc_delay_done(): await asyncio.sleep(0.1) - dsp.HIPCTDA = 1<<31 + if adsp_is_ace(): + dsp.HFIPCXTDA = ~(1<<31) & dsp.HFIPCXTDA # Signal done + else: + dsp.HIPCTDA = 1<<31 + +def inbox_offset(): + ( base, stride ) = adsp_mem_window_config() + return base + stride + +def outbox_offset(): + ( base, _ ) = adsp_mem_window_config() + return base + 4096 ipc_timestamp = 0 @@ -554,8 +724,8 @@ def ipc_command(data, ext_data): ipc_timestamp = t send_msg = True elif data == 5: # copy word at outbox[ext_data >> 16] to inbox[ext_data & 0xffff] - src = OUTBOX_OFFSET + 4 * (ext_data >> 16) - dst = INBOX_OFFSET + 4 * (ext_data & 0xffff) + src = outbox_offset() + 4 * (ext_data >> 16) + dst = inbox_offset() + 4 * (ext_data & 0xffff) for i in range(4): bar4_mmap[dst + i] = bar4_mmap[src + i] elif data == 6: # HDA RESET (init if not exists) @@ -634,15 +804,37 @@ def ipc_command(data, ext_data): return - dsp.HIPCTDR = 1<<31 # Ack local interrupt, also signals DONE on v1.5 - if cavs18: - time.sleep(0.01) # Needed on 1.8, or the command below won't send! - - if done and not cavs15: - dsp.HIPCTDA = 1<<31 # Signal done - if send_msg: - dsp.HIPCIDD = ext_data - dsp.HIPCIDR = (1<<31) | ext_data + if adsp_is_ace(): + dsp.HFIPCXTDR = 1<<31 # Ack local interrupt, also signals DONE on v1.5 + if done: + dsp.HFIPCXTDA = ~(1<<31) & dsp.HFIPCXTDA # Signal done + if send_msg: + log.debug("ipc: sending msg 0x%08x" % ext_data) + dsp.HFIPCXIDDY = ext_data + dsp.HFIPCXIDR = (1<<31) | ext_data + else: + dsp.HIPCTDR = 1<<31 # Ack local interrupt, also signals DONE on v1.5 + if cavs18: + time.sleep(0.01) # Needed on 1.8, or the command below won't send! + if done and not cavs15: + dsp.HIPCTDA = 1<<31 # Signal done + if send_msg: + dsp.HIPCIDD = ext_data + dsp.HIPCIDR = (1<<31) | ext_data + +def handle_ipc(): + if adsp_is_ace(): + if dsp.HFIPCXIDA & 0x80000000: + log.debug("ipc: Ack DSP reply with IDA_DONE") + dsp.HFIPCXIDA = 1<<31 # must ACK any DONE interrupts that arrive! + if dsp.HFIPCXTDR & 0x80000000: + ipc_command(dsp.HFIPCXTDR & ~0x80000000, dsp.HFIPCXTDDY) + return + + if dsp.HIPCIDA & 0x80000000: + dsp.HIPCIDA = 1<<31 # must ACK any DONE interrupts that arrive! + if dsp.HIPCTDR & 0x80000000: + ipc_command(dsp.HIPCTDR & ~0x80000000, dsp.HIPCTDD) async def main(): #TODO this bit me, remove the globals, write a little FirmwareLoader class or something to contain. @@ -664,8 +856,12 @@ async def main(): log.error("Firmware file argument missing") sys.exit(1) - load_firmware(args.fw_file) + if adsp_is_ace(): + load_firmware_ace(args.fw_file) + else: + load_firmware(args.fw_file) time.sleep(0.1) + if not args.quiet: sys.stdout.write("--\n") @@ -679,10 +875,7 @@ async def main(): sys.stdout.write(output) sys.stdout.flush() if not args.log_only: - if dsp.HIPCIDA & 0x80000000: - dsp.HIPCIDA = 1<<31 # must ACK any DONE interrupts that arrive! - if dsp.HIPCTDR & 0x80000000: - ipc_command(dsp.HIPCTDR & ~0x80000000, dsp.HIPCTDD) + handle_ipc() ap = argparse.ArgumentParser(description="DSP loader/logger tool", allow_abbrev=False) From 7dfab4b033cf6697008f55c72ac5d6208aad3d87 Mon Sep 17 00:00:00 2001 From: Benjamin Gwin Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0959/1389] twister: Add logging of stderr for BinaryHandlers In the case where a test causes the test executor to crash, the stderr is currently lost, making it hard to debug failures. This changes it so that the process' stderr gets captured to 'handler_stderr.log' for inspection. Signed-off-by: Benjamin Gwin --- scripts/pylib/twister/twisterlib/handlers.py | 8 ++++++-- scripts/pylib/twister/twisterlib/runner.py | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 16cec58be2f8f9..970e6b2717efe4 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -307,8 +307,9 @@ def handle(self, harness): harness.run_robot_test(command, self) return - with subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, cwd=self.build_dir, env=env) as proc: + stderr_log = "{}/handler_stderr.log".format(self.instance.build_dir) + with open(stderr_log, "w+") as stderr_log_fp, subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=stderr_log_fp, cwd=self.build_dir, env=env) as proc: logger.debug("Spawning BinaryHandler Thread for %s" % self.name) t = threading.Thread(target=self._output_handler, args=(proc, harness,), daemon=True) t.start() @@ -318,6 +319,9 @@ def handle(self, harness): t.join() proc.wait() self.returncode = proc.returncode + if proc.returncode != 0: + self.instance.status = "error" + self.instance.reason = "BinaryHandler returned {}".format(proc.returncode) self.try_kill_process_by_pid() handler_time = time.time() - start_time diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 25037eb2632452..7251f3f733ceba 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -573,6 +573,7 @@ def log_info(self, filename, inline_logs, log_testcases=False): def log_info_file(self, inline_logs): build_dir = self.instance.build_dir h_log = "{}/handler.log".format(build_dir) + he_log = "{}/handler_stderr.log".format(build_dir) b_log = "{}/build.log".format(build_dir) v_log = "{}/valgrind.log".format(build_dir) d_log = "{}/device.log".format(build_dir) @@ -584,6 +585,8 @@ def log_info_file(self, inline_logs): self.log_info("{}".format(pytest_log), inline_logs, log_testcases=True) elif os.path.exists(h_log) and os.path.getsize(h_log) > 0: self.log_info("{}".format(h_log), inline_logs) + elif os.path.exists(he_log) and os.path.getsize(he_log) > 0: + self.log_info("{}".format(he_log), inline_logs) elif os.path.exists(d_log) and os.path.getsize(d_log) > 0: self.log_info("{}".format(d_log), inline_logs) else: @@ -757,6 +760,7 @@ def cleanup_artifacts(self, additional_keep: List[str] = []): allow = [ os.path.join('zephyr', '.config'), 'handler.log', + 'handler_stderr.log', 'build.log', 'device.log', 'recording.csv', From 55ef21821241401e52034c53c44215558fc1b302 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0960/1389] doc: releases: release-notes-3.7: Add info for Handsfree AG Added information about implementing handsfree AG to the Bluetooth section. Signed-off-by: Lyle Zhu --- doc/releases/release-notes-3.7.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 548b723bdd962e..b2b72c14c79690 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -97,6 +97,11 @@ Bluetooth This Service exposes the ability to declare multiple instances of the GATT service, allowing multiple serial endpoints to be used for different purposes. + * Implemented Hands-free Audio Gateway (AG), enabled by the :kconfig:option:`CONFIG_BT_HFP_AG`. + It works as a device that is the gateway of the audio. Typical device acting as Audio + Gateway is cellular phone. It controls the device (Hands-free Unit), that is the remote + audio input and output mechanism. + Boards & SoC Support ******************** From 97b597a95960b601308d7d70ccfa5a2bbdcc652e Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0961/1389] Bluetooth: controller: fixing rx node leak on CPR reject of parallel CPR In case a CPR is intiated but rejected due to CPR active on other connection, rx nodes are leaked due to retained node not being properly released. Signed-off-by: Erik Brockhoff --- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 16 +++++++++++++--- .../bluetooth/controller/ll_sw/ull_llcp_common.c | 1 + .../controller/ll_sw/ull_llcp_conn_upd.c | 16 ++++++++++++---- subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c | 1 + .../controller/ll_sw/ull_llcp_internal.h | 1 + .../bluetooth/controller/ll_sw/ull_llcp_local.c | 6 ++++++ subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c | 1 + .../bluetooth/controller/ll_sw/ull_llcp_remote.c | 6 ++++++ 8 files changed, 41 insertions(+), 7 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index db9bfab8f76bf3..951b5754bc6e3d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -291,17 +291,30 @@ void llcp_rx_node_retain(struct proc_ctx *ctx) ctx->node_ref.rx->hdr.link = ctx->node_ref.link; } +void llcp_rx_node_release(struct proc_ctx *ctx) +{ + LL_ASSERT(ctx->node_ref.rx); + + if (ctx->node_ref.rx->hdr.type == NODE_RX_TYPE_RETAIN) { + /* Mark RX node to release and release */ + ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RELEASE; + ll_rx_put_sched(ctx->node_ref.rx->hdr.link, ctx->node_ref.rx); + } +} + void llcp_nodes_release(struct ll_conn *conn, struct proc_ctx *ctx) { if (ctx->node_ref.rx && ctx->node_ref.rx->hdr.type == NODE_RX_TYPE_RETAIN) { /* RX node retained, so release */ ctx->node_ref.rx->hdr.link->mem = conn->llcp.rx_node_release; + ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RELEASE; conn->llcp.rx_node_release = ctx->node_ref.rx; } #if defined(CONFIG_BT_CTLR_PHY) && defined(CONFIG_BT_CTLR_DATA_LENGTH) if (ctx->proc == PROC_PHY_UPDATE && ctx->data.pu.ntf_dle_node) { /* RX node retained, so release */ ctx->data.pu.ntf_dle_node->hdr.link->mem = conn->llcp.rx_node_release; + ctx->data.pu.ntf_dle_node->hdr.type = NODE_RX_TYPE_RELEASE; conn->llcp.rx_node_release = ctx->data.pu.ntf_dle_node; } #endif @@ -546,9 +559,6 @@ void ull_cp_release_nodes(struct ll_conn *conn) hdr = &rx->hdr; rx = hdr->link->mem; - /* Mark for buffer for release */ - hdr->type = NODE_RX_TYPE_RELEASE; - /* enqueue rx node towards Thread */ ll_rx_put(hdr->link, hdr); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index aea6c72a7b608e..10b4547698a2c6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -1134,6 +1134,7 @@ static void rp_comm_ntf(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t gene /* Allocate ntf node */ ntf = ctx->node_ref.rx; + ctx->node_ref.rx = NULL; LL_ASSERT(ntf); /* This should be an 'old' RX node, so put/sched when done */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index 982fbff1f320b5..eb1f692e55f278 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -634,8 +634,7 @@ static void lp_cu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint lp_cu_ntf_complete(conn, ctx, evt, param); } else { /* Release RX node kept for NTF */ - ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RELEASE; - ll_rx_put_sched(ctx->node_ref.rx->hdr.link, ctx->node_ref.rx); + llcp_rx_node_release(ctx); ctx->node_ref.rx = NULL; lp_cu_complete(conn, ctx); @@ -969,11 +968,18 @@ static void rp_cu_st_wait_conn_param_req_available(struct ll_conn *conn, struct case RP_CU_EVT_RUN: if (cpr_active_is_set(conn)) { ctx->state = RP_CU_STATE_WAIT_CONN_PARAM_REQ_AVAILABLE; + if (!llcp_rr_ispaused(conn) && llcp_tx_alloc_peek(conn, ctx)) { /* We're good to reject immediately */ ctx->data.cu.rejected_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ; ctx->data.cu.error = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL; rp_cu_send_reject_ext_ind(conn, ctx, evt, param); + + /* Possibly retained rx node to be released as we won't need it */ + llcp_rx_node_release(ctx); + ctx->node_ref.rx = NULL; + + break; } /* In case we have to defer NTF */ llcp_rx_node_retain(ctx); @@ -988,6 +994,9 @@ static void rp_cu_st_wait_conn_param_req_available(struct ll_conn *conn, struct rp_cu_conn_param_req_ntf(conn, ctx); ctx->state = RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY; } else { + /* Possibly retained rx node to be released as we won't need it */ + llcp_rx_node_release(ctx); + ctx->node_ref.rx = NULL; #if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE) /* Handle APM as a vendor specific user extension */ if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL && @@ -1173,8 +1182,7 @@ static void rp_cu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint cu_ntf(conn, ctx); } else { /* Release RX node kept for NTF */ - ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RELEASE; - ll_rx_put_sched(ctx->node_ref.rx->hdr.link, ctx->node_ref.rx); + llcp_rx_node_release(ctx); ctx->node_ref.rx = NULL; } rp_cu_complete(conn, ctx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c index 4ce49c68ea0fc0..cc112b11d3ab82 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c @@ -227,6 +227,7 @@ static void lp_enc_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Piggy-back on RX node */ ntf = ctx->node_ref.rx; + ctx->node_ref.rx = NULL; LL_ASSERT(ntf); ntf->hdr.type = NODE_RX_TYPE_DC_PDU; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index faaa660bb75a98..5744f9c57232e8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -421,6 +421,7 @@ void llcp_ntf_set_pending(struct ll_conn *conn); void llcp_ntf_clear_pending(struct ll_conn *conn); bool llcp_ntf_pending(struct ll_conn *conn); void llcp_rx_node_retain(struct proc_ctx *ctx); +void llcp_rx_node_release(struct proc_ctx *ctx); /* * ULL -> LLL Interface diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index 793e33934bce0a..f2a21b2f4f8b66 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -81,6 +81,12 @@ void llcp_lr_check_done(struct ll_conn *conn, struct proc_ctx *ctx) ctx_header = llcp_lr_peek(conn); LL_ASSERT(ctx_header == ctx); + /* If we have a node rx it must not be marked RETAIN as + * the memory referenced would leak + */ + LL_ASSERT(ctx->node_ref.rx == NULL || + ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN); + lr_dequeue(conn); llcp_proc_ctx_release(ctx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index f20155bfa34268..e4f2fc2f83cfdd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -433,6 +433,7 @@ static void pu_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Piggy-back on stored RX node */ ntf = ctx->node_ref.rx; + ctx->node_ref.rx = NULL; LL_ASSERT(ntf); if (ctx->data.pu.ntf_pu) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 2263cd1b23d851..d939abe2d32684 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -118,6 +118,12 @@ void llcp_rr_check_done(struct ll_conn *conn, struct proc_ctx *ctx) ctx_header = llcp_rr_peek(conn); LL_ASSERT(ctx_header == ctx); + /* If we have a node rx it must not be marked RETAIN as + * the memory referenced would leak + */ + LL_ASSERT(ctx->node_ref.rx == NULL || + ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN); + rr_dequeue(conn); llcp_proc_ctx_release(ctx); From 5ffa54a9ff9b98fa9ae71c952ec849e0d02d5998 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0962/1389] Bluetooth: controller: fix node_rx retention mechanism Ensure that in LLCP reference to node_rx is cleared when retention is NOT used, to avoid corruption of node_rx later re-allocated Signed-off-by: Erik Brockhoff --- subsys/bluetooth/controller/ll_sw/ull_llcp_local.c | 5 +++++ subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index f2a21b2f4f8b66..249943b10b2af7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -318,6 +318,11 @@ void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, memq_link_t *link, break; } + /* If rx node was not retained clear reference */ + if (ctx->node_ref.rx && ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN) { + ctx->node_ref.rx = NULL; + } + llcp_lr_check_done(conn, ctx); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index d939abe2d32684..66476aae6dd51d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -313,6 +313,12 @@ void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, memq_link_t *link, LL_ASSERT(0); break; } + + /* If rx node was not retained clear reference */ + if (ctx->node_ref.rx && ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN) { + ctx->node_ref.rx = NULL; + } + llcp_rr_check_done(conn, ctx); } From ee9dcf602b8d5d16d2c47e22983309552258e52d Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0963/1389] Bluetooth: controller: minor cleanup and a fix-up re. LLCP Only perform retention if not already done. Ensure 'sched' is performed on phy ntf even if dle is not. Signed-off-by: Erik Brockhoff --- subsys/bluetooth/controller/ll_sw/ull_llcp.c | 12 ++++++++---- subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c | 6 ------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 951b5754bc6e3d..4dc525adf904e6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -284,17 +284,21 @@ void llcp_rx_node_retain(struct proc_ctx *ctx) { LL_ASSERT(ctx->node_ref.rx); - /* Mark RX node to NOT release */ - ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RETAIN; + /* Only retain if not already retained */ + if (ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN) { + /* Mark RX node to NOT release */ + ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RETAIN; - /* store link element reference to use once this node is moved up */ - ctx->node_ref.rx->hdr.link = ctx->node_ref.link; + /* store link element reference to use once this node is moved up */ + ctx->node_ref.rx->hdr.link = ctx->node_ref.link; + } } void llcp_rx_node_release(struct proc_ctx *ctx) { LL_ASSERT(ctx->node_ref.rx); + /* Only release if retained */ if (ctx->node_ref.rx->hdr.type == NODE_RX_TYPE_RETAIN) { /* Mark RX node to release and release */ ctx->node_ref.rx->hdr.type = NODE_RX_TYPE_RELEASE; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index e4f2fc2f83cfdd..006938d9b2fc24 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -450,15 +450,9 @@ static void pu_ntf(struct ll_conn *conn, struct proc_ctx *ctx) } /* Enqueue notification towards LL */ -#if defined(CONFIG_BT_CTLR_DATA_LENGTH) - /* only 'put' as the 'sched' is handled when handling DLE ntf */ - ll_rx_put(ntf->hdr.link, ntf); -#else ll_rx_put_sched(ntf->hdr.link, ntf); -#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ ctx->data.pu.ntf_pu = 0; - ctx->node_ref.rx = NULL; } #if defined(CONFIG_BT_CTLR_DATA_LENGTH) From dc81dd2673e4f063ec935df1584ea772f2bb1814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0964/1389] boards: st: stm32h745i_disco: Use PLL2Q as FDCAN clock source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this configuration of the device tree, we use 80 MHz as a FDCAN bus clock. This configuration allows to pass the tests. Signed-off-by: Tomáš Juřena --- .../stm32h745i_disco_stm32h745xx_m7.dts | 14 ++++++++++++++ .../stm32h745i_disco_stm32h745xx_m7.yaml | 1 + 2 files changed, 15 insertions(+) diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts index e140f6d22bc0d4..eb33539d8799c7 100644 --- a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts @@ -72,6 +72,16 @@ status = "okay"; }; +&pll2 { + div-m = <5>; + mul-n = <192>; + div-p = <2>; + div-q = <12>; + div-r = <4>; + clocks = <&clk_hse>; + status = "okay"; +}; + &rcc { clocks = <&pll>; clock-frequency = ; @@ -202,6 +212,8 @@ status = "okay"; pinctrl-0 = <&fdcan1_tx_ph13 &fdcan1_rx_ph14>; pinctrl-names = "default"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, + <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; sample-point = <875>; sample-point-data = <875>; @@ -214,6 +226,8 @@ status = "okay"; pinctrl-0 = <&fdcan2_tx_pb13 &fdcan2_rx_pb5>; pinctrl-names = "default"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, + <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; sample-point = <875>; sample-point-data = <875>; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml index 4b261299fed1e9..ba7f0e8d9400a7 100644 --- a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml @@ -20,4 +20,5 @@ supported: - memc - spi - rtc + - can vendor: st From 5105ea56b173d6724d01353508ffcaad64360728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0965/1389] tests: drivers: can: timing: enable all bitrates on STM32H745I-Disco MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable testing of all CiA recommended bitrates on the STM32H745I. Signed-off-by: Tomáš Juřena --- .../can/timing/boards/stm32h745i_disco_stm32h745xx_m7.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/drivers/can/timing/boards/stm32h745i_disco_stm32h745xx_m7.conf diff --git a/tests/drivers/can/timing/boards/stm32h745i_disco_stm32h745xx_m7.conf b/tests/drivers/can/timing/boards/stm32h745i_disco_stm32h745xx_m7.conf new file mode 100644 index 00000000000000..7b071f3a54f51d --- /dev/null +++ b/tests/drivers/can/timing/boards/stm32h745i_disco_stm32h745xx_m7.conf @@ -0,0 +1 @@ +CONFIG_TEST_ALL_BITRATES=y From 7d79ca4b89fb2d65c8cd3739f0d40d840a9c8a5a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0966/1389] net: dns: Convert resolver to use socket service API Instead of using net_context API directly, the DNS resolver is changed to use the socket service API. This allows DNS access for offloaded sockets and can lower overall memory consumption. Signed-off-by: Jukka Rissanen --- include/zephyr/net/dns_resolve.h | 16 +- include/zephyr/net/socket.h | 16 +- include/zephyr/net/socket_poll.h | 42 +++ subsys/net/lib/dns/Kconfig | 2 + subsys/net/lib/dns/resolve.c | 269 ++++++++++++------ subsys/net/lib/sockets/sockets_misc.c | 1 + subsys/net/lib/sockets/sockets_service.c | 1 + tests/net/lib/dns_addremove/prj.conf | 1 + tests/net/lib/dns_addremove/testcase.yaml | 3 + tests/net/lib/dns_cache/testcase.yaml | 3 + tests/net/lib/dns_packet/testcase.yaml | 3 + tests/net/lib/dns_resolve/prj.conf | 2 + tests/net/lib/dns_resolve/src/main.c | 6 +- tests/net/lib/dns_resolve/testcase.yaml | 3 + tests/net/lib/dns_sd/testcase.yaml | 3 + tests/net/socket/getaddrinfo/testcase.yaml | 3 + tests/net/socket/poll/src/main.c | 4 - tests/net/socket/poll/testcase.yaml | 5 +- .../net/socket/reuseaddr_reuseport/src/main.c | 1 + tests/net/socket/socketpair/prj.conf | 1 + tests/net/socket/socketpair/testcase.yaml | 12 +- tests/net/socket/tcp/src/main.c | 1 + 22 files changed, 287 insertions(+), 111 deletions(-) create mode 100644 include/zephyr/net/socket_poll.h diff --git a/include/zephyr/net/dns_resolve.h b/include/zephyr/net/dns_resolve.h index 46e5ad8e4df06a..b0d1fc7dcc9a49 100644 --- a/include/zephyr/net/dns_resolve.h +++ b/include/zephyr/net/dns_resolve.h @@ -13,8 +13,10 @@ #ifndef ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ #define ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ +#include #include -#include +#include +#include #ifdef __cplusplus extern "C" { @@ -172,7 +174,7 @@ struct dns_resolve_context { struct sockaddr dns_server; /** Connection to the DNS server */ - struct net_context *net_ctx; + int sock; /** Is this server mDNS one */ uint8_t is_mdns : 1; @@ -181,6 +183,16 @@ struct dns_resolve_context { uint8_t is_llmnr : 1; } servers[CONFIG_DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS]; +/** @cond INTERNAL_HIDDEN */ +#if (IS_ENABLED(CONFIG_NET_IPV6) && IS_ENABLED(CONFIG_NET_IPV4)) +#define DNS_RESOLVER_MAX_POLL (2 * (CONFIG_DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS)) +#else +#define DNS_RESOLVER_MAX_POLL (1 * (CONFIG_DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS)) +#endif + /** Socket polling for each server connection */ + struct zsock_pollfd fds[DNS_RESOLVER_MAX_POLL]; +/** @endcond */ + /** Prevent concurrent access */ struct k_mutex lock; diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 7dfa893477473c..54e534caf080b9 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -22,30 +22,22 @@ * @{ */ +#include #include #include +#include #include -#include #include +#include #include #include +#include #include #ifdef __cplusplus extern "C" { #endif -/** - * @brief Definition of the monitored socket/file descriptor. - * - * An array of these descriptors is passed as an argument to poll(). - */ -struct zsock_pollfd { - int fd; /**< Socket descriptor */ - short events; /**< Requested events */ - short revents; /**< Returned events */ -}; - /** * @name Options for poll() * @{ diff --git a/include/zephyr/net/socket_poll.h b/include/zephyr/net/socket_poll.h new file mode 100644 index 00000000000000..97e03804311ab2 --- /dev/null +++ b/include/zephyr/net/socket_poll.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_NET_SOCKET_POLL_H_ +#define ZEPHYR_INCLUDE_NET_SOCKET_POLL_H_ + +/* Setting for pollfd to avoid circular inclusion */ + +/** + * @brief BSD Sockets compatible API + * @defgroup bsd_sockets BSD Sockets compatible API + * @ingroup networking + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Definition of the monitored socket/file descriptor. + * + * An array of these descriptors is passed as an argument to poll(). + */ +struct zsock_pollfd { + int fd; /**< Socket descriptor */ + short events; /**< Requested events */ + short revents; /**< Returned events */ +}; + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_NET_SOCKET_POLL_H_ */ diff --git a/subsys/net/lib/dns/Kconfig b/subsys/net/lib/dns/Kconfig index 4503c3e8dc8130..45a9ff16f284d9 100644 --- a/subsys/net/lib/dns/Kconfig +++ b/subsys/net/lib/dns/Kconfig @@ -4,6 +4,8 @@ config DNS_RESOLVER bool "DNS resolver" depends on NET_NATIVE + select NET_SOCKETS + select NET_SOCKETS_SERVICE select CRC help This option enables the DNS client side support for Zephyr diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 4e723944800e00..3e7a22923bc3c5 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -6,6 +6,7 @@ /* * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2024 Nordic Semiconductor * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +25,7 @@ LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL); #include #include #include +#include #include "dns_pack.h" #include "dns_internal.h" #include "dns_cache.h" @@ -62,6 +64,11 @@ LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL); #define DNS_IPV4_LEN sizeof(struct in_addr) #define DNS_IPV6_LEN sizeof(struct in6_addr) +static void svc_handler(struct k_work *work); +static int init_called; + +NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(svc, NULL, svc_handler, DNS_RESOLVER_MAX_POLL); + NET_BUF_POOL_DEFINE(dns_msg_pool, DNS_RESOLVER_BUF_CTR, DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL); @@ -78,7 +85,7 @@ static struct dns_resolve_context dns_default_ctx; static int dns_write(struct dns_resolve_context *ctx, int server_idx, int query_idx, - struct net_buf *dns_data, + uint8_t *buf, size_t buf_len, size_t max_len, struct net_buf *dns_qname, int hop_limit); @@ -213,6 +220,14 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, goto fail; } + ARRAY_FOR_EACH(ctx->servers, j) { + ctx->servers[j].sock = -1; + } + + ARRAY_FOR_EACH(ctx->fds, j) { + ctx->fds[j].fd = -1; + } + if (servers) { for (i = 0; idx < SERVER_COUNT && servers[i]; i++) { struct sockaddr *addr = &ctx->servers[idx].dns_server; @@ -283,22 +298,28 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, goto fail; } - ret = net_context_get(ctx->servers[i].dns_server.sa_family, - SOCK_DGRAM, IPPROTO_UDP, - &ctx->servers[i].net_ctx); + ret = zsock_socket(ctx->servers[i].dns_server.sa_family, + SOCK_DGRAM, IPPROTO_UDP); if (ret < 0) { - NET_DBG("Cannot get net_context (%d)", ret); + NET_DBG("Cannot get socket (%d)", ret); goto fail; } - ret = net_context_bind(ctx->servers[i].net_ctx, - local_addr, addr_len); + ctx->servers[i].sock = ret; + + ret = zsock_bind(ctx->servers[i].sock, local_addr, addr_len); if (ret < 0) { NET_DBG("Cannot bind DNS context (%d)", ret); goto fail; } - iface = net_context_get_iface(ctx->servers[i].net_ctx); + if (ctx->servers[i].dns_server.sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface( + &net_sin6(&ctx->servers[i].dns_server)->sin6_addr); + } else { + iface = net_if_ipv4_select_src_iface( + &net_sin(&ctx->servers[i].dns_server)->sin_addr); + } if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) { net_mgmt_event_notify_with_info( @@ -327,6 +348,7 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, goto fail; } + init_called++; ctx->state = DNS_RESOLVE_CONTEXT_ACTIVE; ctx->buf_timeout = DNS_BUF_TIMEOUT; ret = 0; @@ -714,8 +736,7 @@ int dns_validate_msg(struct dns_resolve_context *ctx, /* Must be invoked with context lock held */ static int dns_read(struct dns_resolve_context *ctx, - struct net_pkt *pkt, - struct net_buf *dns_data, + struct net_buf *dns_data, size_t buf_len, uint16_t *dns_id, struct net_buf *dns_cname, uint16_t *query_hash) @@ -726,15 +747,7 @@ static int dns_read(struct dns_resolve_context *ctx, int ret; int query_idx = -1; - data_len = MIN(net_pkt_remaining_data(pkt), DNS_RESOLVER_MAX_BUF_SIZE); - - /* TODO: Instead of this temporary copy, just use the net_pkt directly. - */ - ret = net_pkt_read(pkt, dns_data->data, data_len); - if (ret < 0) { - ret = DNS_EAI_MEMORY; - goto quit; - } + data_len = MIN(buf_len, DNS_RESOLVER_MAX_BUF_SIZE); dns_msg.msg = dns_data->data; dns_msg.msg_size = data_len; @@ -755,8 +768,6 @@ static int dns_read(struct dns_resolve_context *ctx, /* Marks the end of the results */ release_query(&ctx->queries[query_idx]); - net_pkt_unref(pkt); - return 0; finished: @@ -764,26 +775,22 @@ static int dns_read(struct dns_resolve_context *ctx, ctx->queries[query_idx].query, ctx->queries[query_idx].query_type); quit: - net_pkt_unref(pkt); - return ret; } -static void cb_recv(struct net_context *net_ctx, - struct net_pkt *pkt, - union net_ip_header *ip_hdr, - union net_proto_header *proto_hdr, - int status, - void *user_data) +static int recv_data(struct net_socket_service_event *pev) { - struct dns_resolve_context *ctx = user_data; + COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), + (struct sockaddr_in6), (struct sockaddr_in)) addr; + struct dns_resolve_context *ctx = pev->user_data; + socklen_t optlen = sizeof(int); + size_t addrlen = sizeof(addr); struct net_buf *dns_cname = NULL; struct net_buf *dns_data = NULL; uint16_t query_hash = 0U; uint16_t dns_id = 0U; - int ret, i; - - ARG_UNUSED(net_ctx); + int family = AF_UNSPEC, sock_error; + int ret = 0, i, len; k_mutex_lock(&ctx->lock, K_FOREVER); @@ -791,24 +798,43 @@ static void cb_recv(struct net_context *net_ctx, goto unlock; } - if (status) { + if ((pev->event.revents & ZSOCK_POLLERR) || + (pev->event.revents & ZSOCK_POLLNVAL)) { + (void)zsock_getsockopt(pev->event.fd, SOL_SOCKET, + SO_DOMAIN, &family, &optlen); + (void)zsock_getsockopt(pev->event.fd, SOL_SOCKET, + SO_ERROR, &sock_error, &optlen); + NET_ERR("Receiver IPv%d socket error (%d)", + family == AF_INET ? 4 : 6, sock_error); ret = DNS_EAI_SYSTEM; - goto quit; + goto unlock; } dns_data = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout); if (!dns_data) { ret = DNS_EAI_MEMORY; - goto quit; + goto free_buf; } dns_cname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout); if (!dns_cname) { ret = DNS_EAI_MEMORY; - goto quit; + goto free_buf; } - ret = dns_read(ctx, pkt, dns_data, &dns_id, dns_cname, &query_hash); + ret = zsock_recvfrom(pev->event.fd, dns_data->data, + net_buf_max_len(dns_data), 0, + (struct sockaddr *)&addr, &addrlen); + if (ret < 0) { + ret = -errno; + NET_ERR("recv failed on IPv%d socket (%d)", + family == AF_INET ? 4 : 6, -ret); + goto free_buf; + } + + len = ret; + + ret = dns_read(ctx, dns_data, len, &dns_id, dns_cname, &query_hash); if (!ret) { /* We called the callback already in dns_read() if there * was no errors. @@ -827,11 +853,13 @@ static void cb_recv(struct net_context *net_ctx, } for (j = 0; j < SERVER_COUNT; j++) { - if (!ctx->servers[j].net_ctx) { + if (ctx->servers[j].sock < 0) { continue; } - ret = dns_write(ctx, j, i, dns_data, dns_cname, 0); + ret = dns_write(ctx, j, i, dns_data->data, len, + net_buf_max_len(dns_data), + dns_cname, 0); if (ret < 0) { failure++; } @@ -871,30 +899,50 @@ static void cb_recv(struct net_context *net_ctx, unlock: k_mutex_unlock(&ctx->lock); + + return ret; +} + +static void svc_handler(struct k_work *work) +{ + struct net_socket_service_event *pev = + CONTAINER_OF(work, struct net_socket_service_event, work); + int ret; + + ret = recv_data(pev); + if (ret < 0) { + NET_ERR("DNS recv error (%d)", ret); + } +} + +static int set_ttl_hop_limit(int sock, int level, int option, int new_limit) +{ + return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit)); } /* Must be invoked with context lock held */ static int dns_write(struct dns_resolve_context *ctx, int server_idx, int query_idx, - struct net_buf *dns_data, + uint8_t *buf, size_t buf_len, size_t max_len, struct net_buf *dns_qname, int hop_limit) { enum dns_query_type query_type; - struct net_context *net_ctx; struct sockaddr *server; int server_addr_len; - uint16_t dns_id; - int ret; + uint16_t dns_id, len; + int ret, sock, family; - net_ctx = ctx->servers[server_idx].net_ctx; + sock = ctx->servers[server_idx].sock; + family = ctx->servers[server_idx].dns_server.sa_family; server = &ctx->servers[server_idx].dns_server; dns_id = ctx->queries[query_idx].id; query_type = ctx->queries[query_idx].query_type; - ret = dns_msg_pack_query(dns_data->data, &dns_data->len, - net_buf_max_len(dns_data), + len = buf_len; + + ret = dns_msg_pack_query(buf, &len, (uint16_t)max_len, dns_qname->data, dns_qname->len, dns_id, (enum dns_rr_type)query_type); if (ret < 0) { @@ -905,26 +953,58 @@ static int dns_write(struct dns_resolve_context *ctx, * the dns_qname->len contains the length of \0 */ ctx->queries[query_idx].query_hash = - crc16_ansi(dns_data->data + DNS_MSG_HEADER_SIZE, - dns_qname->len + 2); - - if (IS_ENABLED(CONFIG_NET_IPV6) && - net_context_get_family(net_ctx) == AF_INET6 && - hop_limit > 0) { - net_context_set_ipv6_hop_limit(net_ctx, hop_limit); - } else if (IS_ENABLED(CONFIG_NET_IPV4) && - net_context_get_family(net_ctx) == AF_INET && - hop_limit > 0) { - net_context_set_ipv4_ttl(net_ctx, hop_limit); - } - - ret = net_context_recv(net_ctx, cb_recv, K_NO_WAIT, ctx); - if (ret < 0 && ret != -EALREADY) { - NET_DBG("Could not receive from socket (%d)", ret); + crc16_ansi(buf + DNS_MSG_HEADER_SIZE, dns_qname->len + 2); + + if (hop_limit > 0) { + if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) { + ret = set_ttl_hop_limit(sock, IPPROTO_IPV6, + IPV6_UNICAST_HOPS, + hop_limit); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) { + ret = set_ttl_hop_limit(sock, IPPROTO_IP, IP_TTL, + hop_limit); + } else { + ret = -ENOTSUP; + } + + if (ret < 0) { + NET_DBG("Cannot set %s to socket (%d)", + family == AF_INET6 ? "hop limit" : + (family == AF_INET ? "TTL" : ""), + ret); + return ret; + } + } + + ret = -ENOENT; + + ARRAY_FOR_EACH(ctx->fds, i) { + if (ctx->fds[i].fd == sock) { + /* There was query to this server already */ + ret = 0; + break; + } + + if (ctx->fds[i].fd < 0) { + ctx->fds[i].fd = sock; + ctx->fds[i].events = ZSOCK_POLLIN; + ret = 0; + break; + } + } + + if (ret < 0) { + NET_DBG("Cannot set %s to socket (%d)", "polling", ret); + return ret; + } + + ret = net_socket_service_register(&svc, ctx->fds, ARRAY_SIZE(ctx->fds), ctx); + if (ret < 0) { + NET_DBG("Cannot register socket service (%d)", ret); return ret; } - if (server->sa_family == AF_INET) { + if (family == AF_INET) { server_addr_len = sizeof(struct sockaddr_in); } else { server_addr_len = sizeof(struct sockaddr_in6); @@ -942,9 +1022,7 @@ static int dns_write(struct dns_resolve_context *ctx, "hash %u", query_idx, server_idx, dns_id, ctx->queries[query_idx].query_hash); - ret = net_context_sendto(net_ctx, dns_data->data, dns_data->len, - server, server_addr_len, NULL, - K_NO_WAIT, NULL); + ret = zsock_sendto(sock, buf, len, 0, server, server_addr_len); if (ret < 0) { NET_DBG("Cannot send query (%d)", ret); return ret; @@ -1276,7 +1354,7 @@ int dns_resolve_name(struct dns_resolve_context *ctx, for (j = 0; j < SERVER_COUNT; j++) { hop_limit = 0U; - if (!ctx->servers[j].net_ctx) { + if (ctx->servers[j].sock < 0) { continue; } @@ -1299,7 +1377,10 @@ int dns_resolve_name(struct dns_resolve_context *ctx, hop_limit = 1U; } - ret = dns_write(ctx, j, i, dns_data, dns_qname, hop_limit); + ret = dns_write(ctx, j, i, dns_data->data, + net_buf_max_len(dns_data), + net_buf_max_len(dns_data), + dns_qname, hop_limit); if (ret < 0) { failure++; continue; @@ -1371,25 +1452,45 @@ static int dns_resolve_close_locked(struct dns_resolve_context *ctx) k_mutex_unlock(&ctx->lock); for (i = 0; i < SERVER_COUNT; i++) { - if (ctx->servers[i].net_ctx) { - struct net_if *iface; + struct net_if *iface; - iface = net_context_get_iface(ctx->servers[i].net_ctx); + if (ctx->servers[i].sock < 0) { + continue; + } - if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) { - net_mgmt_event_notify_with_info( - NET_EVENT_DNS_SERVER_DEL, - iface, - (void *)&ctx->servers[i].dns_server, - sizeof(struct sockaddr)); - } else { - net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL, - iface); - } + if (ctx->servers[i].dns_server.sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface( + &net_sin6(&ctx->servers[i].dns_server)->sin6_addr); + } else { + iface = net_if_ipv4_select_src_iface( + &net_sin(&ctx->servers[i].dns_server)->sin_addr); + } - net_context_put(ctx->servers[i].net_ctx); - ctx->servers[i].net_ctx = NULL; + if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) { + net_mgmt_event_notify_with_info( + NET_EVENT_DNS_SERVER_DEL, + iface, + (void *)&ctx->servers[i].dns_server, + sizeof(struct sockaddr)); + } else { + net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL, + iface); + } + + zsock_close(ctx->servers[i].sock); + + ARRAY_FOR_EACH(ctx->fds, j) { + if (ctx->fds[j].fd == ctx->servers[i].sock) { + ctx->fds[j].fd = -1; + } } + + ctx->servers[i].sock = -1; + } + + if (--init_called <= 0) { + (void)net_socket_service_unregister(&svc); + init_called = 0; } k_mutex_lock(&ctx->lock, K_FOREVER); diff --git a/subsys/net/lib/sockets/sockets_misc.c b/subsys/net/lib/sockets/sockets_misc.c index fb3750e110ab17..f16bfc8e962319 100644 --- a/subsys/net/lib/sockets/sockets_misc.c +++ b/subsys/net/lib/sockets/sockets_misc.c @@ -6,6 +6,7 @@ #include #include +#include #include int z_impl_zsock_gethostname(char *buf, size_t len) diff --git a/subsys/net/lib/sockets/sockets_service.c b/subsys/net/lib/sockets/sockets_service.c index ad5c07de601469..f8398e95df1dc3 100644 --- a/subsys/net/lib/sockets/sockets_service.c +++ b/subsys/net/lib/sockets/sockets_service.c @@ -8,6 +8,7 @@ LOG_MODULE_REGISTER(net_sock_svc, CONFIG_NET_SOCKETS_LOG_LEVEL); #include +#include #include #include diff --git a/tests/net/lib/dns_addremove/prj.conf b/tests/net/lib/dns_addremove/prj.conf index db691377acd440..c28f0a14eac195 100644 --- a/tests/net/lib/dns_addremove/prj.conf +++ b/tests/net/lib/dns_addremove/prj.conf @@ -17,3 +17,4 @@ CONFIG_NET_ARP=n CONFIG_PRINTK=y CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_NET_SOCKETS_POLL_MAX=5 diff --git a/tests/net/lib/dns_addremove/testcase.yaml b/tests/net/lib/dns_addremove/testcase.yaml index 5551a41cfbaae6..21b33cba4caad8 100644 --- a/tests/net/lib/dns_addremove/testcase.yaml +++ b/tests/net/lib/dns_addremove/testcase.yaml @@ -5,6 +5,9 @@ common: depends_on: netif min_ram: 16 timeout: 600 + platform_exclude: + - native_posix + - native_posix/native/64 tests: net.dns.addremove: min_ram: 21 diff --git a/tests/net/lib/dns_cache/testcase.yaml b/tests/net/lib/dns_cache/testcase.yaml index a14a8f6fe7de4e..b86087552b53aa 100644 --- a/tests/net/lib/dns_cache/testcase.yaml +++ b/tests/net/lib/dns_cache/testcase.yaml @@ -6,6 +6,9 @@ common: depends_on: netif integration_platforms: - native_sim + platform_exclude: + - native_posix + - native_posix/native/64 tests: net.dns.cache: build_only: false diff --git a/tests/net/lib/dns_packet/testcase.yaml b/tests/net/lib/dns_packet/testcase.yaml index a69ee4ccb73bb1..d1129ca8b424bf 100644 --- a/tests/net/lib/dns_packet/testcase.yaml +++ b/tests/net/lib/dns_packet/testcase.yaml @@ -1,5 +1,8 @@ tests: net.dns: + platform_exclude: + - native_posix + - native_posix/native/64 min_ram: 16 tags: - dns diff --git a/tests/net/lib/dns_resolve/prj.conf b/tests/net/lib/dns_resolve/prj.conf index c43911ac3cd2db..4bc1b8706cec92 100644 --- a/tests/net/lib/dns_resolve/prj.conf +++ b/tests/net/lib/dns_resolve/prj.conf @@ -29,3 +29,5 @@ CONFIG_PRINTK=y CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=1344 +CONFIG_NET_SOCKETS_POLL_MAX=9 +CONFIG_POSIX_MAX_FDS=5 diff --git a/tests/net/lib/dns_resolve/src/main.c b/tests/net/lib/dns_resolve/src/main.c index cc56a7821a2e7f..3d3bdcf9cf5f17 100644 --- a/tests/net/lib/dns_resolve/src/main.c +++ b/tests/net/lib/dns_resolve/src/main.c @@ -348,7 +348,7 @@ ZTEST(dns_resolve, test_dns_query_server_count) continue; } - if (!ctx->servers[i].net_ctx) { + if (ctx->servers[i].sock < 0) { continue; } @@ -369,7 +369,7 @@ ZTEST(dns_resolve, test_dns_query_ipv4_server_count) continue; } - if (!ctx->servers[i].net_ctx) { + if (ctx->servers[i].sock < 0) { continue; } @@ -399,7 +399,7 @@ ZTEST(dns_resolve, test_dns_query_ipv6_server_count) continue; } - if (!ctx->servers[i].net_ctx) { + if (ctx->servers[i].sock < 0) { continue; } diff --git a/tests/net/lib/dns_resolve/testcase.yaml b/tests/net/lib/dns_resolve/testcase.yaml index 5b7b40cc2773b7..b0734b4d17591e 100644 --- a/tests/net/lib/dns_resolve/testcase.yaml +++ b/tests/net/lib/dns_resolve/testcase.yaml @@ -5,6 +5,9 @@ common: depends_on: netif timeout: 600 min_ram: 21 + platform_exclude: + - native_posix + - native_posix/native/64 tests: net.dns.resolve: extra_configs: diff --git a/tests/net/lib/dns_sd/testcase.yaml b/tests/net/lib/dns_sd/testcase.yaml index 22a6d332558021..bfdc751ed7c177 100644 --- a/tests/net/lib/dns_sd/testcase.yaml +++ b/tests/net/lib/dns_sd/testcase.yaml @@ -3,6 +3,9 @@ common: - dns - net depends_on: netif + platform_exclude: + - native_posix + - native_posix/native/64 tests: net.dns.sd: min_ram: 21 diff --git a/tests/net/socket/getaddrinfo/testcase.yaml b/tests/net/socket/getaddrinfo/testcase.yaml index 3d7bb63370356e..14822401179c2e 100644 --- a/tests/net/socket/getaddrinfo/testcase.yaml +++ b/tests/net/socket/getaddrinfo/testcase.yaml @@ -6,6 +6,9 @@ common: - socket - getaddrinfo - userspace + platform_exclude: + - native_posix + - native_posix/native/64 tests: net.socket.get_addr_info: min_ram: 21 diff --git a/tests/net/socket/poll/src/main.c b/tests/net/socket/poll/src/main.c index 7b5eac449d5597..a155461514f550 100644 --- a/tests/net/socket/poll/src/main.c +++ b/tests/net/socket/poll/src/main.c @@ -85,7 +85,6 @@ ZTEST(net_socket_poll, test_poll) tstamp); zassert_equal(res, 0, ""); - /* Send pkt for s_sock and poll with timeout of 10 */ len = zsock_send(c_sock, BUF_AND_SIZE(TEST_STR_SMALL), 0); zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid send len"); @@ -151,9 +150,6 @@ ZTEST(net_socket_poll, test_poll) zassert_equal(res, 1, ""); zassert_equal(pollout[0].revents, ZSOCK_POLLOUT, ""); - /* Let the network stack run */ - k_msleep(10); - res = zsock_close(c_sock_tcp); zassert_equal(res, 0, "close failed"); diff --git a/tests/net/socket/poll/testcase.yaml b/tests/net/socket/poll/testcase.yaml index 56ac475d13e1ff..9d08909605e979 100644 --- a/tests/net/socket/poll/testcase.yaml +++ b/tests/net/socket/poll/testcase.yaml @@ -3,7 +3,10 @@ common: # FIXME: This test fails very frequently on mps2/an385 due to the system # timer stability issues, so keep it disabled until the root cause # is fixed (GitHub issue zephyrproject-rtos/zephyr#48608). - platform_exclude: mps2/an385 + platform_exclude: + - mps2/an385 + - native_posix/native/64 + - native_posix tests: net.socket.poll: min_ram: 21 diff --git a/tests/net/socket/reuseaddr_reuseport/src/main.c b/tests/net/socket/reuseaddr_reuseport/src/main.c index a59dd1a9560585..5e0b95aa8272e6 100644 --- a/tests/net/socket/reuseaddr_reuseport/src/main.c +++ b/tests/net/socket/reuseaddr_reuseport/src/main.c @@ -14,6 +14,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include +#include #include "../../socket_helpers.h" diff --git a/tests/net/socket/socketpair/prj.conf b/tests/net/socket/socketpair/prj.conf index 177d9c991c4aa4..fd15cb5309d88a 100644 --- a/tests/net/socket/socketpair/prj.conf +++ b/tests/net/socket/socketpair/prj.conf @@ -7,6 +7,7 @@ CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETPAIR=y CONFIG_NET_SOCKETPAIR_BUFFER_SIZE=64 +CONFIG_POSIX_MAX_FDS=10 # Network driver config CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/socket/socketpair/testcase.yaml b/tests/net/socket/socketpair/testcase.yaml index bb906c29d0c422..133f2801b95943 100644 --- a/tests/net/socket/socketpair/testcase.yaml +++ b/tests/net/socket/socketpair/testcase.yaml @@ -5,19 +5,22 @@ common: - userspace depends_on: netif min_ram: 21 + platform_exclude: + - native_posix/native/64 + - native_posix + # See #61246 for info about these next two excludes + - vmu_rt1170/mimxrt1176/cm7 + - mimxrt1160_evk/mimxrt1166/cm7 tests: - net.socket.socketpair: - platform_exclude: vmu_rt1170/mimxrt1176/cm7 mimxrt1160_evk/mimxrt1166/cm7 # See #61246 + net.socket.socketpair: {} net.socket.socketpair.newlib: filter: CONFIG_FULL_LIBC_SUPPORTED extra_configs: - CONFIG_REQUIRES_FULL_LIBC=y - platform_exclude: vmu_rt1170/mimxrt1176/cm7 mimxrt1160_evk/mimxrt1166/cm7 # See #61246 net.socket.socketpair.picolibc: filter: CONFIG_PICOLIBC_SUPPORTED extra_configs: - CONFIG_PICOLIBC=y - platform_exclude: vmu_rt1170/mimxrt1176/cm7 mimxrt1160_evk/mimxrt1166/cm7 # See #61246 net.socket.socketpair.high_mem: min_ram: 64 extra_configs: @@ -25,4 +28,3 @@ tests: # fail due to insufficient memory. So, use high buffer sizes. - CONFIG_NET_SOCKETPAIR_BUFFER_SIZE=4096 - CONFIG_HEAP_MEM_POOL_SIZE=32768 - platform_exclude: vmu_rt1170/mimxrt1176/cm7 mimxrt1160_evk/mimxrt1166/cm7 # See #61246 diff --git a/tests/net/socket/tcp/src/main.c b/tests/net/socket/tcp/src/main.c index a4295b74f1debc..5ac3599ca1b20c 100644 --- a/tests/net/socket/tcp/src/main.c +++ b/tests/net/socket/tcp/src/main.c @@ -9,6 +9,7 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include +#include #include #include From d50236b344574c80be6d3ce341506421da26fad0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0967/1389] net: mdns_responder: Convert mDNS responder to use socket service API Instead of using net_context API directly, the mDNS responder is changed to use the socket service API. This allows DNS access for offloaded sockets and can lower overall memory consumption. Signed-off-by: Jukka Rissanen --- subsys/net/lib/dns/Kconfig | 2 + subsys/net/lib/dns/mdns_responder.c | 365 +++++++++++++++------ tests/net/lib/dns_sd/src/main.c | 46 ++- tests/net/lib/mdns_responder/prj.conf | 2 + tests/net/lib/mdns_responder/testcase.yaml | 3 + 5 files changed, 299 insertions(+), 119 deletions(-) diff --git a/subsys/net/lib/dns/Kconfig b/subsys/net/lib/dns/Kconfig index 45a9ff16f284d9..a334b17c8e5bc8 100644 --- a/subsys/net/lib/dns/Kconfig +++ b/subsys/net/lib/dns/Kconfig @@ -166,6 +166,8 @@ config MDNS_RESPONDER select NET_IPV6_MLD if NET_IPV6 select NET_MGMT select NET_MGMT_EVENT + select NET_SOCKETS + select NET_SOCKETS_SERVICE depends on NET_HOSTNAME_ENABLE help This option enables the mDNS responder support for Zephyr. diff --git a/subsys/net/lib/dns/mdns_responder.c b/subsys/net/lib/dns/mdns_responder.c index e10f40d1194e9b..e92db7dd57b459 100644 --- a/subsys/net/lib/dns/mdns_responder.c +++ b/subsys/net/lib/dns/mdns_responder.c @@ -7,6 +7,7 @@ /* * Copyright (c) 2017 Intel Corporation * Copyright (c) 2020 Friedt Professional Engineering Services, Inc + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +26,7 @@ LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL); #include #include #include +#include #include #include "dns_sd.h" @@ -39,14 +41,14 @@ LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL); #if defined(CONFIG_NET_IPV4) #define MAX_IPV4_IFACE_COUNT CONFIG_NET_IF_MAX_IPV4_COUNT -static struct net_context *ipv4[MAX_IPV4_IFACE_COUNT]; +static int ipv4[MAX_IPV4_IFACE_COUNT]; static struct sockaddr_in local_addr4; #else #define MAX_IPV4_IFACE_COUNT 0 #endif #if defined(CONFIG_NET_IPV6) #define MAX_IPV6_IFACE_COUNT CONFIG_NET_IF_MAX_IPV6_COUNT -static struct net_context *ipv6[MAX_IPV6_IFACE_COUNT]; +static int ipv6[MAX_IPV6_IFACE_COUNT]; #else #define MAX_IPV6_IFACE_COUNT 0 #endif @@ -63,8 +65,20 @@ static size_t external_records_count; #define DNS_RESOLVER_BUF_CTR (DNS_RESOLVER_MIN_BUF + \ CONFIG_MDNS_RESOLVER_ADDITIONAL_BUF_CTR) +#if (IS_ENABLED(CONFIG_NET_IPV6) && IS_ENABLED(CONFIG_NET_IPV4)) +#define MDNS_MAX_POLL (2 * (MAX_IPV4_IFACE_COUNT + MAX_IPV6_IFACE_COUNT)) +#else +#define MDNS_MAX_POLL (1 * (MAX_IPV4_IFACE_COUNT + MAX_IPV6_IFACE_COUNT)) +#endif + +static void svc_handler(struct k_work *work); +NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(svc_mdns, NULL, svc_handler, MDNS_MAX_POLL); + +/* Socket polling for each server connection */ +static struct zsock_pollfd fds[MDNS_MAX_POLL]; + #ifndef CONFIG_NET_TEST -static int setup_dst_addr(struct net_context *ctx, sa_family_t family, +static int setup_dst_addr(int sock, sa_family_t family, struct sockaddr *dst, socklen_t *dst_len); #endif /* CONFIG_NET_TEST */ @@ -106,17 +120,32 @@ static void mdns_iface_event_handler(struct net_mgmt_event_callback *cb, } } -int setup_dst_addr(struct net_context *ctx, sa_family_t family, +static int set_ttl_hop_limit(int sock, int level, int option, int new_limit) +{ + return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit)); +} + +int setup_dst_addr(int sock, sa_family_t family, struct sockaddr *dst, socklen_t *dst_len) { + int ret; + if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) { create_ipv4_addr(net_sin(dst)); *dst_len = sizeof(struct sockaddr_in); - net_context_set_ipv4_mcast_ttl(ctx, 255); + + ret = set_ttl_hop_limit(sock, IPPROTO_IP, IP_MULTICAST_TTL, 255); + if (ret < 0) { + NET_DBG("Cannot set %s multicast %s (%d)", "IPv4", "TTL", ret); + } } else if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) { create_ipv6_addr(net_sin6(dst)); *dst_len = sizeof(struct sockaddr_in6); - net_context_set_ipv6_mcast_hop_limit(ctx, 255); + + ret = set_ttl_hop_limit(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255); + if (ret < 0) { + NET_DBG("Cannot set %s multicast %s (%d)", "IPv6", "hoplimit", ret); + } } else { return -EPFNOSUPPORT; } @@ -124,36 +153,34 @@ int setup_dst_addr(struct net_context *ctx, sa_family_t family, return 0; } -static struct net_context *get_ctx(sa_family_t family) +static int get_socket(sa_family_t family) { - struct net_context *ctx; int ret; - ret = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, &ctx); + ret = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP); if (ret < 0) { + ret = -errno; NET_DBG("Cannot get context (%d)", ret); - return NULL; } - return ctx; + return ret; } -static int bind_ctx(struct net_context *ctx, +static int bind_ctx(int sock, struct sockaddr *local_addr, socklen_t addrlen) { int ret; - if (!ctx) { + if (sock < 0) { return -EINVAL; } - ret = net_context_bind(ctx, local_addr, addrlen); + ret = zsock_bind(sock, local_addr, addrlen); if (ret < 0) { - NET_DBG("Cannot bind to mDNS %s port (%d)", + NET_DBG("Cannot bind to %s %s port (%d)", "mDNS", local_addr->sa_family == AF_INET ? "IPv4" : "IPv6", ret); - return ret; } return ret; @@ -230,7 +257,7 @@ static void add_answer(struct net_buf *query, enum dns_rr_type qtype, memcpy(query->data + offset, addr, addr_len); } -static int create_answer(struct net_context *ctx, +static int create_answer(int sock, struct net_buf *query, enum dns_rr_type qtype, uint16_t addr_len, uint8_t *addr) @@ -258,28 +285,37 @@ static int create_answer(struct net_context *ctx, return 0; } -static int send_response(struct net_context *ctx, - struct net_if *iface, +static int send_response(int sock, sa_family_t family, - const void *src_addr, + struct sockaddr *src_addr, + size_t addrlen, struct net_buf *query, enum dns_rr_type qtype) { - struct sockaddr dst; + struct net_if *iface; socklen_t dst_len; int ret; + COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), + (struct sockaddr_in6), (struct sockaddr_in)) dst; - ret = setup_dst_addr(ctx, family, &dst, &dst_len); + ret = setup_dst_addr(sock, family, (struct sockaddr *)&dst, &dst_len); if (ret < 0) { NET_DBG("unable to set up the response address"); return ret; } + if (family == AF_INET6) { + iface = net_if_ipv6_select_src_iface(&net_sin6(src_addr)->sin6_addr); + } else { + iface = net_if_ipv4_select_src_iface(&net_sin(src_addr)->sin_addr); + } + if (IS_ENABLED(CONFIG_NET_IPV4) && qtype == DNS_RR_TYPE_A) { const struct in_addr *addr; if (family == AF_INET) { - addr = net_if_ipv4_select_src_addr(iface, (struct in_addr *)src_addr); + addr = net_if_ipv4_select_src_addr(iface, + &net_sin(src_addr)->sin_addr); } else { struct sockaddr_in tmp_addr; @@ -287,7 +323,7 @@ static int send_response(struct net_context *ctx, addr = net_if_ipv4_select_src_addr(iface, &tmp_addr.sin_addr); } - ret = create_answer(ctx, query, qtype, sizeof(struct in_addr), (uint8_t *)addr); + ret = create_answer(sock, query, qtype, sizeof(struct in_addr), (uint8_t *)addr); if (ret != 0) { return ret; } @@ -295,7 +331,8 @@ static int send_response(struct net_context *ctx, const struct in6_addr *addr; if (family == AF_INET6) { - addr = net_if_ipv6_select_src_addr(iface, (struct in6_addr *)src_addr); + addr = net_if_ipv6_select_src_addr(iface, + &net_sin6(src_addr)->sin6_addr); } else { struct sockaddr_in6 tmp_addr; @@ -303,7 +340,7 @@ static int send_response(struct net_context *ctx, addr = net_if_ipv6_select_src_addr(iface, &tmp_addr.sin6_addr); } - ret = create_answer(ctx, query, qtype, sizeof(struct in6_addr), (uint8_t *)addr); + ret = create_answer(sock, query, qtype, sizeof(struct in6_addr), (uint8_t *)addr); if (ret != 0) { return -ENOMEM; } @@ -312,10 +349,10 @@ static int send_response(struct net_context *ctx, return -EINVAL; } - ret = net_context_sendto(ctx, query->data, query->len, &dst, - dst_len, NULL, K_NO_WAIT, NULL); + ret = zsock_sendto(sock, query->data, query->len, 0, + (struct sockaddr *)&dst, dst_len); if (ret < 0) { - NET_DBG("Cannot send mDNS reply (%d)", ret); + NET_DBG("Cannot send %s reply (%d)", "mDNS", ret); } return ret; @@ -334,19 +371,19 @@ static const char *qtype_to_string(int qtype) } } -static void send_sd_response(struct net_context *ctx, - struct net_if *iface, +static void send_sd_response(int sock, sa_family_t family, - const void *src_addr, + struct sockaddr *src_addr, + size_t addrlen, struct dns_msg_t *dns_msg, struct net_buf *result) { + struct net_if *iface; + socklen_t dst_len; int ret; const struct dns_sd_rec *record; /* filter must be zero-initialized for "wildcard" port */ struct dns_sd_rec filter = {0}; - struct sockaddr dst; - socklen_t dst_len; bool service_type_enum = false; const struct in6_addr *addr6 = NULL; const struct in_addr *addr4 = NULL; @@ -364,6 +401,8 @@ static void send_sd_response(struct net_context *ctx, size_t n = ARRAY_SIZE(label); size_t rec_num; size_t ext_rec_num = external_records_count; + COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), + (struct sockaddr_in6), (struct sockaddr_in)) dst; BUILD_ASSERT(ARRAY_SIZE(label) == ARRAY_SIZE(size), ""); @@ -376,16 +415,23 @@ static void send_sd_response(struct net_context *ctx, label[2] = proto_buf; label[3] = domain_buf; - ret = setup_dst_addr(ctx, family, &dst, &dst_len); + ret = setup_dst_addr(sock, family, (struct sockaddr *)&dst, &dst_len); if (ret < 0) { NET_DBG("unable to set up the response address"); return; } + if (family == AF_INET6) { + iface = net_if_ipv6_select_src_iface(&net_sin6(src_addr)->sin6_addr); + } else { + iface = net_if_ipv4_select_src_iface(&net_sin(src_addr)->sin_addr); + } + if (IS_ENABLED(CONFIG_NET_IPV4)) { /* Look up the local IPv4 address */ if (family == AF_INET) { - addr4 = net_if_ipv4_select_src_addr(iface, (struct in_addr *)src_addr); + addr4 = net_if_ipv4_select_src_addr(iface, + &net_sin(src_addr)->sin_addr); } else { struct sockaddr_in tmp_addr; @@ -397,7 +443,8 @@ static void send_sd_response(struct net_context *ctx, if (IS_ENABLED(CONFIG_NET_IPV6)) { /* Look up the local IPv6 address */ if (family == AF_INET6) { - addr6 = net_if_ipv6_select_src_addr(iface, (struct in6_addr *)src_addr); + addr6 = net_if_ipv6_select_src_addr(iface, + &net_sin6(src_addr)->sin6_addr); } else { struct sockaddr_in6 tmp_addr; @@ -471,20 +518,21 @@ static void send_sd_response(struct net_context *ctx, result->len = ret; /* Send the response */ - ret = net_context_sendto(ctx, result->data, - result->len, &dst, dst_len, NULL, - K_NO_WAIT, NULL); + ret = zsock_sendto(sock, result->data, result->len, 0, + (struct sockaddr *)&dst, dst_len); if (ret < 0) { - NET_DBG("Cannot send mDNS reply (%d)", ret); + NET_DBG("Cannot send %s reply (%d)", "mDNS", ret); continue; } } } } -static int dns_read(struct net_context *ctx, - struct net_pkt *pkt, +static int dns_read(int sock, struct net_buf *dns_data, + size_t len, + struct sockaddr *src_addr, + size_t addrlen, struct dns_addrinfo *info) { /* Helper struct to track the dns msg received from the server */ @@ -492,12 +540,13 @@ static int dns_read(struct net_context *ctx, int hostname_len = strlen(hostname); struct net_buf *result; struct dns_msg_t dns_msg; - const void *src_addr; + socklen_t optlen; int data_len; int queries; + int family; int ret; - data_len = MIN(net_pkt_remaining_data(pkt), DNS_RESOLVER_MAX_BUF_SIZE); + data_len = MIN(len, DNS_RESOLVER_MAX_BUF_SIZE); /* Store the DNS query name into a temporary net_buf, which will be * eventually used to send a response @@ -508,13 +557,6 @@ static int dns_read(struct net_context *ctx, goto quit; } - /* TODO: Instead of this temporary copy, just use the net_pkt directly. - */ - ret = net_pkt_read(pkt, dns_data->data, data_len); - if (ret < 0) { - goto quit; - } - dns_msg.msg = dns_data->data; dns_msg.msg_size = data_len; @@ -526,12 +568,15 @@ static int dns_read(struct net_context *ctx, queries = ret; - src_addr = net_pkt_family(pkt) == AF_INET - ? (const void *)&NET_IPV4_HDR(pkt)->src : (const void *)&NET_IPV6_HDR(pkt)->src; + optlen = sizeof(int); + (void)zsock_getsockopt(sock, SOL_SOCKET, SO_DOMAIN, &family, &optlen); NET_DBG("Received %d %s from %s", queries, queries > 1 ? "queries" : "query", - net_sprint_addr(net_pkt_family(pkt), src_addr)); + net_sprint_addr(family, + family == AF_INET ? + (const void *)&net_sin(src_addr)->sin_addr : + (const void *)&net_sin6(src_addr)->sin6_addr)); do { enum dns_rr_type qtype; @@ -563,13 +608,13 @@ static int dns_read(struct net_context *ctx, if (!strncasecmp(hostname, result->data + 1, hostname_len) && (result->len - 1) >= hostname_len && &(result->data + 1)[hostname_len] == lquery) { - NET_DBG("mDNS query to our hostname %s.local", + NET_DBG("%s query to our hostname %s.local", "mDNS", hostname); - send_response(ctx, net_pkt_iface(pkt), net_pkt_family(pkt), src_addr, + send_response(sock, family, src_addr, addrlen, result, qtype); } else if (IS_ENABLED(CONFIG_MDNS_RESPONDER_DNS_SD) && qtype == DNS_RR_TYPE_PTR) { - send_sd_response(ctx, net_pkt_iface(pkt), net_pkt_family(pkt), src_addr, + send_sd_response(sock, family, src_addr, addrlen, &dns_msg, result); } @@ -585,45 +630,69 @@ static int dns_read(struct net_context *ctx, return ret; } -static void recv_cb(struct net_context *net_ctx, - struct net_pkt *pkt, - union net_ip_header *ip_hdr, - union net_proto_header *proto_hdr, - int status, - void *user_data) +static int recv_data(struct net_socket_service_event *pev) { - struct net_context *ctx = user_data; + COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), + (struct sockaddr_in6), (struct sockaddr_in)) addr; struct net_buf *dns_data = NULL; struct dns_addrinfo info = { 0 }; - int ret; - - ARG_UNUSED(net_ctx); - ARG_UNUSED(ip_hdr); - ARG_UNUSED(proto_hdr); - NET_ASSERT(ctx == net_ctx); - - if (!pkt) { - return; - } - - if (status) { + size_t addrlen = sizeof(addr); + int ret, family, sock_error, len; + socklen_t optlen; + + if ((pev->event.revents & ZSOCK_POLLERR) || + (pev->event.revents & ZSOCK_POLLNVAL)) { + (void)zsock_getsockopt(pev->event.fd, SOL_SOCKET, + SO_DOMAIN, &family, &optlen); + (void)zsock_getsockopt(pev->event.fd, SOL_SOCKET, + SO_ERROR, &sock_error, &optlen); + NET_ERR("Receiver IPv%d socket error (%d)", + family == AF_INET ? 4 : 6, sock_error); + ret = DNS_EAI_SYSTEM; goto quit; } dns_data = net_buf_alloc(&mdns_msg_pool, BUF_ALLOC_TIMEOUT); if (!dns_data) { + ret = -ENOENT; goto quit; } - ret = dns_read(ctx, pkt, dns_data, &info); + ret = zsock_recvfrom(pev->event.fd, dns_data->data, + net_buf_max_len(dns_data), 0, + (struct sockaddr *)&addr, &addrlen); + if (ret < 0) { + ret = -errno; + NET_ERR("recv failed on IPv%d socket (%d)", + family == AF_INET ? 4 : 6, -ret); + goto free_buf; + } + + len = ret; + + ret = dns_read(pev->event.fd, dns_data, len, + (struct sockaddr *)&addr, addrlen, &info); if (ret < 0 && ret != -EINVAL) { - NET_DBG("mDNS read failed (%d)", ret); + NET_DBG("%s read failed (%d)", "mDNS", ret); } +free_buf: net_buf_unref(dns_data); quit: - net_pkt_unref(pkt); + return ret; +} + +static void svc_handler(struct k_work *work) +{ + struct net_socket_service_event *pev = + CONTAINER_OF(work, struct net_socket_service_event, work); + int ret; + + ret = recv_data(pev); + if (ret < 0) { + NET_ERR("DNS recv error (%d)", ret); + } } #if defined(CONFIG_NET_IPV6) @@ -683,14 +752,22 @@ static void setup_ipv4_addr(struct sockaddr_in *local_addr) } #endif /* CONFIG_NET_IPV4 */ +#if defined(CONFIG_NET_INTERFACE_NAME_LEN) +#define INTERFACE_NAME_LEN CONFIG_NET_INTERFACE_NAME_LEN +#else +#define INTERFACE_NAME_LEN 0 +#endif + static int init_listener(void) { - int ret, ok = 0, i; + int ret, ok = 0, i, ifindex; + char name[INTERFACE_NAME_LEN + 1]; + struct ifreq if_req; struct net_if *iface; int iface_count; NET_IFACE_COUNT(&iface_count); - NET_DBG("Setting mDNS listener to %d interface%s", iface_count, + NET_DBG("Setting %s listener to %d interface%s", "mDNS", iface_count, iface_count > 1 ? "s" : ""); if ((iface_count > MAX_IPV6_IFACE_COUNT && MAX_IPV6_IFACE_COUNT > 0) || @@ -701,39 +778,82 @@ static int init_listener(void) MAX_IPV6_IFACE_COUNT), iface_count); } + ARRAY_FOR_EACH(fds, j) { + fds[j].fd = -1; + } + #if defined(CONFIG_NET_IPV6) struct sockaddr_in6 local_addr6; - struct net_context *v6; + int v6; setup_ipv6_addr(&local_addr6); for (i = 0; i < MAX_IPV6_IFACE_COUNT; i++) { - v6 = get_ctx(AF_INET6); - if (v6 == NULL) { - NET_ERR("Cannot get %s context out of %d. Max contexts is %d", + v6 = get_socket(AF_INET6); + if (v6 < 0) { + NET_ERR("Cannot get %s socket out of %d. Max sockets is %d", "IPv6", MAX_IPV6_IFACE_COUNT, CONFIG_NET_MAX_CONTEXTS); continue; } iface = net_if_get_by_index(i + 1); if (iface == NULL) { - net_context_unref(v6); + zsock_close(v6); continue; } - net_context_bind_iface(v6, iface); + ifindex = net_if_get_by_iface(iface); + + ret = net_if_get_name(iface, name, INTERFACE_NAME_LEN); + if (ret < 0) { + NET_DBG("Cannot get interface name for %d (%d)", + ifindex, ret); + } else { + memset(&if_req, 0, sizeof(if_req)); + strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name)); + + ret = zsock_setsockopt(v6, SOL_SOCKET, SO_BINDTODEVICE, + &if_req, sizeof(if_req)); + if (ret < 0) { + NET_DBG("Cannot bind sock %d to interface %d (%d)", + v6, ifindex, ret); + } + } ret = bind_ctx(v6, (struct sockaddr *)&local_addr6, sizeof(local_addr6)); if (ret < 0) { - net_context_put(v6); + zsock_close(v6); goto ipv6_out; } - ret = net_context_recv(v6, recv_cb, K_NO_WAIT, v6); + ret = -ENOENT; + + ARRAY_FOR_EACH(fds, j) { + if (fds[j].fd == v6) { + ret = 0; + break; + } + + if (fds[j].fd < 0) { + fds[j].fd = v6; + fds[j].events = ZSOCK_POLLIN; + ret = 0; + break; + } + } + + if (ret < 0) { + NET_DBG("Cannot set %s to socket (%d)", "polling", ret); + zsock_close(v6); + continue; + } + + ret = net_socket_service_register(&svc_mdns, fds, ARRAY_SIZE(fds), NULL); if (ret < 0) { - NET_WARN("Cannot receive %s mDNS data (%d)", "IPv6", ret); - net_context_put(v6); + NET_DBG("Cannot register %s %s socket service (%d)", + "IPv6", "mDNS", ret); + zsock_close(v6); } else { ipv6[i] = v6; ok++; @@ -746,37 +866,76 @@ static int init_listener(void) #endif /* CONFIG_NET_IPV6 */ #if defined(CONFIG_NET_IPV4) - struct net_context *v4; + int v4; setup_ipv4_addr(&local_addr4); for (i = 0; i < MAX_IPV4_IFACE_COUNT; i++) { - v4 = get_ctx(AF_INET); - if (v4 == NULL) { - NET_ERR("Cannot get %s context out of %d. Max contexts is %d", + v4 = get_socket(AF_INET); + if (v4 < 0) { + NET_ERR("Cannot get %s socket out of %d. Max sockets is %d", "IPv4", MAX_IPV4_IFACE_COUNT, CONFIG_NET_MAX_CONTEXTS); continue; } iface = net_if_get_by_index(i + 1); if (iface == NULL) { - net_context_unref(v4); + zsock_close(v4); continue; } - net_context_bind_iface(v4, iface); + ifindex = net_if_get_by_iface(iface); + + ret = net_if_get_name(iface, name, INTERFACE_NAME_LEN); + if (ret < 0) { + NET_DBG("Cannot get interface name for %d (%d)", + ifindex, ret); + } else { + memset(&if_req, 0, sizeof(if_req)); + strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name)); + + ret = zsock_setsockopt(v4, SOL_SOCKET, SO_BINDTODEVICE, + &if_req, sizeof(if_req)); + if (ret < 0) { + NET_DBG("Cannot bind sock %d to interface %d (%d)", + v4, ifindex, ret); + } + } ret = bind_ctx(v4, (struct sockaddr *)&local_addr4, sizeof(local_addr4)); if (ret < 0) { - net_context_put(v4); + zsock_close(v4); goto ipv4_out; } - ret = net_context_recv(v4, recv_cb, K_NO_WAIT, v4); + ret = -ENOENT; + + ARRAY_FOR_EACH(fds, j) { + if (fds[j].fd == v4) { + ret = 0; + break; + } + + if (fds[j].fd < 0) { + fds[j].fd = v4; + fds[j].events = ZSOCK_POLLIN; + ret = 0; + break; + } + } + + if (ret < 0) { + NET_DBG("Cannot set %s to socket (%d)", "polling", ret); + zsock_close(v4); + continue; + } + + ret = net_socket_service_register(&svc_mdns, fds, ARRAY_SIZE(fds), NULL); if (ret < 0) { - NET_WARN("Cannot receive %s mDNS data (%d)", "IPv4", ret); - net_context_put(v4); + NET_DBG("Cannot register %s %s socket service (%d)", + "IPv4", "mDNS", ret); + zsock_close(v4); } else { ipv4[i] = v4; ok++; @@ -786,7 +945,7 @@ static int init_listener(void) #endif /* CONFIG_NET_IPV4 */ if (!ok) { - NET_WARN("Cannot start mDNS responder"); + NET_WARN("Cannot start %s responder", "mDNS"); } return !ok; diff --git a/tests/net/lib/dns_sd/src/main.c b/tests/net/lib/dns_sd/src/main.c index 31b7a6699a151c..e70482c027c0e2 100644 --- a/tests/net/lib/dns_sd/src/main.c +++ b/tests/net/lib/dns_sd/src/main.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "dns_pack.h" #include "dns_sd.h" @@ -51,7 +52,7 @@ extern int add_srv_record(const struct dns_sd_rec *inst, uint32_t ttl, uint16_t *host_offset); extern size_t service_proto_size(const struct dns_sd_rec *ref); extern bool rec_is_valid(const struct dns_sd_rec *ref); -extern int setup_dst_addr(struct net_context *ctx, sa_family_t family, +extern int setup_dst_addr(int sock, sa_family_t family, struct sockaddr *dst, socklen_t *dst_len); @@ -666,56 +667,69 @@ ZTEST(dns_sd, test_dns_sd_rec_match) /** Test @ref setup_dst_addr */ ZTEST(dns_sd, test_setup_dst_addr) { - int ret; struct net_if *iface; struct sockaddr dst; socklen_t dst_len; + socklen_t optlen; + int ttl; iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); zassert_not_null(iface, "Interface not available"); /* IPv4 case */ - struct net_context *ctx_v4; + int v4; struct in_addr addr_v4_expect = { { { 224, 0, 0, 251 } } }; memset(&dst, 0, sizeof(struct sockaddr)); - ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &ctx_v4); - zassert_equal(ret, 0, "Create IPv4 UDP context failed"); + v4 = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + zassert_true(v4 >= 0, "Create IPv4 UDP context failed (%d)", -errno); - zassert_equal(0, setup_dst_addr(ctx_v4, AF_INET, &dst, &dst_len), ""); - zassert_equal(255, ctx_v4->ipv4_mcast_ttl, ""); + zassert_equal(0, setup_dst_addr(v4, AF_INET, &dst, &dst_len), ""); + + optlen = sizeof(int); + (void)zsock_getsockopt(v4, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &optlen); + + zassert_equal(255, ttl, "TTL invalid (%d vs %d)", 255, ttl); zassert_true(net_ipv4_addr_cmp(&addr_v4_expect, &net_sin(&dst)->sin_addr), ""); zassert_equal(8, dst_len, ""); + (void)zsock_close(v4); + #if defined(CONFIG_NET_IPV6) /* IPv6 case */ - struct net_context *ctx_v6; + int v6; struct in6_addr addr_v6_expect = { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfb } } }; memset(&dst, 0, sizeof(struct sockaddr)); - ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &ctx_v6); - zassert_equal(ret, 0, "Create IPv6 UDP context failed"); + v6 = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + zassert_true(v6 >= 0, "Create IPv6 UDP context failed (%d)", -errno); - zassert_equal(0, setup_dst_addr(ctx_v6, AF_INET6, &dst, &dst_len), ""); - zassert_equal(255, ctx_v6->ipv6_mcast_hop_limit, ""); + zassert_equal(0, setup_dst_addr(v6, AF_INET6, &dst, &dst_len), ""); + + optlen = sizeof(int); + (void)zsock_getsockopt(v6, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, &optlen); + + zassert_equal(255, ttl, "Hoplimit invalid (%d vs %d)", 255, ttl); zassert_true(net_ipv6_addr_cmp(&addr_v6_expect, &net_sin6(&dst)->sin6_addr), ""); zassert_equal(24, dst_len, ""); + + (void)zsock_close(v6); #endif /* Unknown family case */ - struct net_context *ctx_xx; + int xx; - ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &ctx_xx); - zassert_equal(ret, 0, "Create IPV4 udp context failed"); + xx = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + zassert_true(xx >= 0, "Create IPV4 udp socket failed"); zassert_equal(-EPFNOSUPPORT, - setup_dst_addr(ctx_xx, AF_PACKET, &dst, &dst_len), ""); + setup_dst_addr(xx, AF_PACKET, &dst, &dst_len), ""); } /** test for @ref dns_sd_is_service_type_enumeration */ diff --git a/tests/net/lib/mdns_responder/prj.conf b/tests/net/lib/mdns_responder/prj.conf index f7c6945827c095..6d4db394c8db57 100644 --- a/tests/net/lib/mdns_responder/prj.conf +++ b/tests/net/lib/mdns_responder/prj.conf @@ -5,6 +5,7 @@ CONFIG_NET_DRIVERS=y CONFIG_NET_LOOPBACK=y CONFIG_NET_IPV4=y CONFIG_NET_IPV6=y +CONFIG_NET_SOCKETS_POLL_MAX=7 # Network driver config CONFIG_TEST_RANDOM_GENERATOR=y @@ -28,3 +29,4 @@ CONFIG_NET_UDP=y CONFIG_NET_UDP_CHECKSUM=n CONFIG_NET_PKT_RX_COUNT=16 CONFIG_NET_PKT_TX_COUNT=16 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4 diff --git a/tests/net/lib/mdns_responder/testcase.yaml b/tests/net/lib/mdns_responder/testcase.yaml index ae9f6d9dbf2cac..aabe426bdd0596 100644 --- a/tests/net/lib/mdns_responder/testcase.yaml +++ b/tests/net/lib/mdns_responder/testcase.yaml @@ -3,6 +3,9 @@ common: - dns - net depends_on: netif + platform_exclude: + - native_posix/native/64 + - native_posix tests: net.mdns: min_ram: 21 From 8a6eaccc0d32ae25043f3f38dd0e5dd770416563 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0968/1389] net: llmnr_responder: Convert LLMNR responder to use socket service API Instead of using net_context API directly, the LLMNR responder is changed to use the socket service API. This allows DNS access for offloaded sockets and can lower overall memory consumption. Signed-off-by: Jukka Rissanen --- samples/net/mdns_responder/prj.conf | 1 + subsys/net/lib/dns/Kconfig | 2 + subsys/net/lib/dns/llmnr_responder.c | 379 +++++++++++++++------------ 3 files changed, 216 insertions(+), 166 deletions(-) diff --git a/samples/net/mdns_responder/prj.conf b/samples/net/mdns_responder/prj.conf index db58992f3f8e07..644067671b4f37 100644 --- a/samples/net/mdns_responder/prj.conf +++ b/samples/net/mdns_responder/prj.conf @@ -27,6 +27,7 @@ CONFIG_PRINTK=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5 +CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=3 CONFIG_NET_PKT_RX_COUNT=10 CONFIG_NET_PKT_TX_COUNT=10 diff --git a/subsys/net/lib/dns/Kconfig b/subsys/net/lib/dns/Kconfig index a334b17c8e5bc8..9b15408177e740 100644 --- a/subsys/net/lib/dns/Kconfig +++ b/subsys/net/lib/dns/Kconfig @@ -233,6 +233,8 @@ config LLMNR_RESPONDER select NET_IPV6_MLD if NET_IPV6 select NET_MGMT select NET_MGMT_EVENT + select NET_SOCKETS + select NET_SOCKETS_SERVICE depends on NET_HOSTNAME_ENABLE help This option enables the LLMNR responder support for Zephyr. diff --git a/subsys/net/lib/dns/llmnr_responder.c b/subsys/net/lib/dns/llmnr_responder.c index b2881e7829cdb7..deb9802c2a6e6a 100644 --- a/subsys/net/lib/dns/llmnr_responder.c +++ b/subsys/net/lib/dns/llmnr_responder.c @@ -6,6 +6,7 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +24,7 @@ LOG_MODULE_REGISTER(net_llmnr_responder, CONFIG_LLMNR_RESPONDER_LOG_LEVEL); #include #include #include +#include #include #include @@ -36,12 +38,12 @@ LOG_MODULE_REGISTER(net_llmnr_responder, CONFIG_LLMNR_RESPONDER_LOG_LEVEL); #define LLMNR_TTL CONFIG_LLMNR_RESPONDER_TTL /* In seconds */ #if defined(CONFIG_NET_IPV4) -static struct net_context *ipv4; +static int ipv4; static struct sockaddr_in local_addr4; #endif #if defined(CONFIG_NET_IPV6) -static struct net_context *ipv6; +static int ipv6; #endif static struct net_mgmt_event_callback mgmt_cb; @@ -54,7 +56,19 @@ static struct net_mgmt_event_callback mgmt_cb; #define DNS_RESOLVER_BUF_CTR (DNS_RESOLVER_MIN_BUF + \ CONFIG_LLMNR_RESOLVER_ADDITIONAL_BUF_CTR) -NET_BUF_POOL_DEFINE(llmnr_dns_msg_pool, DNS_RESOLVER_BUF_CTR, +#if (IS_ENABLED(CONFIG_NET_IPV6) && IS_ENABLED(CONFIG_NET_IPV4)) +#define LLMNR_MAX_POLL 2 +#else +#define LLMNR_MAX_POLL 1 +#endif + +/* Socket polling for each server connection */ +static struct zsock_pollfd fds[LLMNR_MAX_POLL]; + +static void svc_handler(struct k_work *work); +NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(svc_llmnr, NULL, svc_handler, LLMNR_MAX_POLL); + +NET_BUF_POOL_DEFINE(llmnr_msg_pool, DNS_RESOLVER_BUF_CTR, DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL); #if defined(CONFIG_NET_IPV6) @@ -68,20 +82,14 @@ static void create_ipv6_addr(struct sockaddr_in6 *addr) 0xff02, 0, 0, 0, 0, 0, 0x01, 0x03); } -static void create_ipv6_dst_addr(struct net_pkt *pkt, +static void create_ipv6_dst_addr(struct sockaddr_in6 *src_addr, struct sockaddr_in6 *addr) { - struct net_udp_hdr *udp_hdr, hdr; - - udp_hdr = net_udp_get_hdr(pkt, &hdr); - if (!udp_hdr) { - return; - } - addr->sin6_family = AF_INET6; - addr->sin6_port = udp_hdr->src_port; + addr->sin6_port = src_addr->sin6_port; - net_ipv6_addr_copy_raw((uint8_t *)&addr->sin6_addr, NET_IPV6_HDR(pkt)->src); + net_ipv6_addr_copy_raw((uint8_t *)&addr->sin6_addr, + (uint8_t *)&src_addr->sin6_addr); } #endif @@ -95,21 +103,14 @@ static void create_ipv4_addr(struct sockaddr_in *addr) addr->sin_addr.s_addr = htonl(0xE00000FC); } -static void create_ipv4_dst_addr(struct net_pkt *pkt, +static void create_ipv4_dst_addr(struct sockaddr_in *src_addr, struct sockaddr_in *addr) { - struct net_udp_hdr *udp_hdr, hdr; - - udp_hdr = net_udp_get_hdr(pkt, &hdr); - if (!udp_hdr) { - NET_ERR("could not get UDP header"); - return; - } - addr->sin_family = AF_INET; - addr->sin_port = udp_hdr->src_port; + addr->sin_port = src_addr->sin_port; - net_ipv4_addr_copy_raw((uint8_t *)&addr->sin_addr, NET_IPV4_HDR(pkt)->src); + net_ipv4_addr_copy_raw((uint8_t *)&addr->sin_addr, + (uint8_t *)&src_addr->sin_addr); } #endif @@ -128,33 +129,31 @@ static void llmnr_iface_event_handler(struct net_mgmt_event_callback *cb, } } -static struct net_context *get_ctx(sa_family_t family) +static int get_socket(sa_family_t family) { - struct net_context *ctx; int ret; - ret = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, &ctx); + ret = zsock_socket(family, SOCK_DGRAM, IPPROTO_UDP); if (ret < 0) { NET_DBG("Cannot get context (%d)", ret); - return NULL; } - return ctx; + return ret; } -static int bind_ctx(struct net_context *ctx, +static int bind_ctx(int sock, struct sockaddr *local_addr, socklen_t addrlen) { int ret; - if (!ctx) { + if (sock < 0) { return -EINVAL; } - ret = net_context_bind(ctx, local_addr, addrlen); + ret = zsock_bind(sock, local_addr, addrlen); if (ret < 0) { - NET_DBG("Cannot bind to LLMNR %s port (%d)", + NET_DBG("Cannot bind to %s %s port (%d)", "LLMNR", local_addr->sa_family == AF_INET ? "IPv4" : "IPv6", ret); return ret; @@ -237,8 +236,7 @@ static int add_answer(struct net_buf *query, uint32_t ttl, return offset + addr_len; } -static int create_answer(struct net_context *ctx, - enum dns_rr_type qtype, +static int create_answer(enum dns_rr_type qtype, struct net_buf *query, uint16_t dns_id, uint16_t addr_len, const uint8_t *addr) @@ -292,10 +290,14 @@ static const uint8_t *get_ipv6_src(struct net_if *iface, struct in6_addr *dst) } #endif +static int set_ttl_hop_limit(int sock, int level, int option, int new_limit) +{ + return zsock_setsockopt(sock, level, option, &new_limit, sizeof(new_limit)); +} + #if defined(CONFIG_NET_IPV4) -static int create_ipv4_answer(struct net_context *ctx, - struct net_pkt *pkt, - union net_ip_header *ip_hdr, +static int create_ipv4_answer(int sock, + struct sockaddr_in *src_addr, enum dns_rr_type qtype, struct net_buf *query, uint16_t dns_id, @@ -305,49 +307,30 @@ static int create_ipv4_answer(struct net_context *ctx, const uint8_t *addr; int addr_len; - create_ipv4_dst_addr(pkt, net_sin(dst)); - *dst_len = sizeof(struct sockaddr_in); - - if (qtype == DNS_RR_TYPE_A) { - /* Select proper address according to destination */ - addr = get_ipv4_src(net_pkt_iface(pkt), - &net_sin(dst)->sin_addr); - if (!addr) { - return -ENOENT; - } + create_ipv4_dst_addr(src_addr, net_sin(dst)); - addr_len = sizeof(struct in_addr); - - } else if (qtype == DNS_RR_TYPE_AAAA) { -#if defined(CONFIG_NET_IPV6) - addr = get_ipv6_src(net_pkt_iface(pkt), - (struct in6_addr *)ip_hdr->ipv6->src); - if (!addr) { - return -ENOENT; - } + *dst_len = sizeof(struct sockaddr_in); - addr_len = sizeof(struct in6_addr); -#else - addr = NULL; - addr_len = 0; -#endif - } else { - return -EINVAL; + /* Select proper address according to destination */ + addr = get_ipv4_src(NULL, &net_sin(dst)->sin_addr); + if (!addr) { + return -ENOENT; } - if (create_answer(ctx, qtype, query, dns_id, addr_len, addr)) { + addr_len = sizeof(struct in_addr); + + if (create_answer(qtype, query, dns_id, addr_len, addr)) { return -ENOMEM; } - net_context_set_ipv4_mcast_ttl(ctx, 255); + (void)set_ttl_hop_limit(sock, IPPROTO_IP, IP_MULTICAST_TTL, 255); return 0; } #endif /* CONFIG_NET_IPV4 */ -static int create_ipv6_answer(struct net_context *ctx, - struct net_pkt *pkt, - union net_ip_header *ip_hdr, +static int create_ipv6_answer(int sock, + struct sockaddr_in6 *src_addr, enum dns_rr_type qtype, struct net_buf *query, uint16_t dns_id, @@ -358,62 +341,50 @@ static int create_ipv6_answer(struct net_context *ctx, const uint8_t *addr; int addr_len; - create_ipv6_dst_addr(pkt, net_sin6(dst)); - *dst_len = sizeof(struct sockaddr_in6); + create_ipv6_dst_addr(src_addr, net_sin6(dst)); - if (qtype == DNS_RR_TYPE_AAAA) { - addr = get_ipv6_src(net_pkt_iface(pkt), - (struct in6_addr *)ip_hdr->ipv6->src); - if (!addr) { - return -ENOENT; - } - - addr_len = sizeof(struct in6_addr); - } else if (qtype == DNS_RR_TYPE_A) { -#if defined(CONFIG_NET_IPV4) - addr = get_ipv4_src(net_pkt_iface(pkt), - (struct in_addr *)ip_hdr->ipv4->src); - if (!addr) { - return -ENOENT; - } + *dst_len = sizeof(struct sockaddr_in6); - addr_len = sizeof(struct in_addr); -#else - addr_len = 0; -#endif - } else { - return -EINVAL; + addr = get_ipv6_src(NULL, &src_addr->sin6_addr); + if (!addr) { + return -ENOENT; } - if (create_answer(ctx, qtype, query, dns_id, addr_len, addr)) { + addr_len = sizeof(struct in6_addr); + + if (create_answer(qtype, query, dns_id, addr_len, addr)) { return -ENOMEM; } - net_context_set_ipv6_mcast_hop_limit(ctx, 255); + (void)set_ttl_hop_limit(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255); #endif /* CONFIG_NET_IPV6 */ return 0; } -static int send_response(struct net_context *ctx, struct net_pkt *pkt, - union net_ip_header *ip_hdr, struct net_buf *reply, - enum dns_rr_type qtype, uint16_t dns_id) +static int send_response(int sock, + struct sockaddr *src_addr, + size_t addrlen, + struct net_buf *reply, + enum dns_rr_type qtype, + uint16_t dns_id) { - struct sockaddr dst; socklen_t dst_len; int ret; + COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), + (struct sockaddr_in6), (struct sockaddr_in)) dst; - if (IS_ENABLED(CONFIG_NET_IPV4) && - net_pkt_family(pkt) == AF_INET) { - ret = create_ipv4_answer(ctx, pkt, ip_hdr, qtype, reply, - dns_id, &dst, &dst_len); + if (IS_ENABLED(CONFIG_NET_IPV4) && src_addr->sa_family == AF_INET) { + ret = create_ipv4_answer(sock, (struct sockaddr_in *)src_addr, + qtype, reply, dns_id, + (struct sockaddr *)&dst, &dst_len); if (ret < 0) { return ret; } - } else if (IS_ENABLED(CONFIG_NET_IPV6) && - net_pkt_family(pkt) == AF_INET6) { - ret = create_ipv6_answer(ctx, pkt, ip_hdr, qtype, reply, - dns_id, &dst, &dst_len); + } else if (IS_ENABLED(CONFIG_NET_IPV6) && src_addr->sa_family == AF_INET6) { + ret = create_ipv6_answer(sock, (struct sockaddr_in6 *)src_addr, + qtype, reply, dns_id, + (struct sockaddr *)&dst, &dst_len); if (ret < 0) { return ret; } @@ -422,23 +393,24 @@ static int send_response(struct net_context *ctx, struct net_pkt *pkt, return -EPFNOSUPPORT; } - ret = net_context_sendto(ctx, reply->data, reply->len, &dst, - dst_len, NULL, K_NO_WAIT, NULL); + ret = zsock_sendto(sock, reply->data, reply->len, 0, + (struct sockaddr *)&dst, dst_len); if (ret < 0) { - NET_DBG("Cannot send LLMNR reply to %s (%d)", - net_pkt_family(pkt) == AF_INET ? - net_sprint_ipv4_addr(&net_sin(&dst)->sin_addr) : - net_sprint_ipv6_addr(&net_sin6(&dst)->sin6_addr), + NET_DBG("Cannot send %s reply to %s (%d)", "LLMNR", + src_addr->sa_family == AF_INET ? + net_sprint_ipv4_addr(&net_sin((struct sockaddr *)&dst)->sin_addr) : + net_sprint_ipv6_addr(&net_sin6((struct sockaddr *)&dst)->sin6_addr), ret); } return ret; } -static int dns_read(struct net_context *ctx, - struct net_pkt *pkt, - union net_ip_header *ip_hdr, +static int dns_read(int sock, struct net_buf *dns_data, + size_t len, + struct sockaddr *src_addr, + size_t addrlen, struct dns_addrinfo *info) { /* Helper struct to track the dns msg received from the server */ @@ -447,28 +419,23 @@ static int dns_read(struct net_context *ctx, struct net_buf *result; struct dns_msg_t dns_msg; uint16_t dns_id = 0U; + socklen_t optlen; int data_len; int queries; + int family; int ret; - data_len = MIN(net_pkt_remaining_data(pkt), DNS_RESOLVER_MAX_BUF_SIZE); + data_len = MIN(len, DNS_RESOLVER_MAX_BUF_SIZE); /* Store the DNS query name into a temporary net_buf, which will be * eventually used to send a response */ - result = net_buf_alloc(&llmnr_dns_msg_pool, BUF_ALLOC_TIMEOUT); + result = net_buf_alloc(&llmnr_msg_pool, BUF_ALLOC_TIMEOUT); if (!result) { ret = -ENOMEM; goto quit; } - /* TODO: Instead of this temporary copy, just use the net_pkt directly. - */ - ret = net_pkt_read(pkt, dns_data->data, data_len); - if (ret < 0) { - goto quit; - } - dns_msg.msg = dns_data->data; dns_msg.msg_size = data_len; @@ -480,11 +447,14 @@ static int dns_read(struct net_context *ctx, queries = ret; + optlen = sizeof(int); + (void)zsock_getsockopt(sock, SOL_SOCKET, SO_DOMAIN, &family, &optlen); + NET_DBG("Received %d %s from %s (id 0x%04x)", queries, queries > 1 ? "queries" : "query", - net_pkt_family(pkt) == AF_INET ? - net_sprint_ipv4_addr(&ip_hdr->ipv4->src) : - net_sprint_ipv6_addr(&ip_hdr->ipv6->src), + family == AF_INET ? + net_sprint_ipv4_addr(&net_sin(src_addr)->sin_addr) : + net_sprint_ipv6_addr(&net_sin6(src_addr)->sin6_addr), dns_id); do { @@ -506,9 +476,9 @@ static int dns_read(struct net_context *ctx, /* If the query matches to our hostname, then send reply */ if (!strncasecmp(hostname, result->data + 1, hostname_len) && (result->len - 1) >= hostname_len) { - NET_DBG("LLMNR query to our hostname %s", + NET_DBG("%s query to our hostname %s", "LLMNR", hostname); - ret = send_response(ctx, pkt, ip_hdr, result, qtype, + ret = send_response(sock, src_addr, addrlen, result, qtype, dns_id); if (ret < 0) { NET_DBG("Cannot send response (%d)", ret); @@ -526,43 +496,69 @@ static int dns_read(struct net_context *ctx, return ret; } -static void recv_cb(struct net_context *net_ctx, - struct net_pkt *pkt, - union net_ip_header *ip_hdr, - union net_proto_header *proto_hdr, - int status, - void *user_data) +static int recv_data(struct net_socket_service_event *pev) { - struct net_context *ctx = user_data; + COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), + (struct sockaddr_in6), (struct sockaddr_in)) addr; struct net_buf *dns_data = NULL; struct dns_addrinfo info = { 0 }; - int ret; - - ARG_UNUSED(net_ctx); - NET_ASSERT(ctx == net_ctx); - - if (!pkt) { - return; - } - - if (status) { + size_t addrlen = sizeof(addr); + int ret, family, sock_error, len; + socklen_t optlen; + + if ((pev->event.revents & ZSOCK_POLLERR) || + (pev->event.revents & ZSOCK_POLLNVAL)) { + (void)zsock_getsockopt(pev->event.fd, SOL_SOCKET, + SO_DOMAIN, &family, &optlen); + (void)zsock_getsockopt(pev->event.fd, SOL_SOCKET, + SO_ERROR, &sock_error, &optlen); + NET_ERR("Receiver IPv%d socket error (%d)", + family == AF_INET ? 4 : 6, sock_error); + ret = DNS_EAI_SYSTEM; goto quit; } - dns_data = net_buf_alloc(&llmnr_dns_msg_pool, BUF_ALLOC_TIMEOUT); + dns_data = net_buf_alloc(&llmnr_msg_pool, BUF_ALLOC_TIMEOUT); if (!dns_data) { + ret = -ENOENT; goto quit; } - ret = dns_read(ctx, pkt, ip_hdr, dns_data, &info); + ret = zsock_recvfrom(pev->event.fd, dns_data->data, + net_buf_max_len(dns_data), 0, + (struct sockaddr *)&addr, &addrlen); + if (ret < 0) { + ret = -errno; + NET_ERR("recv failed on IPv%d socket (%d)", + family == AF_INET ? 4 : 6, -ret); + goto free_buf; + } + + len = ret; + + ret = dns_read(pev->event.fd, dns_data, len, + (struct sockaddr *)&addr, addrlen, &info); if (ret < 0 && ret != -EINVAL) { - NET_DBG("LLMNR read failed (%d)", ret); + NET_DBG("%s read failed (%d)", "LLMNR", ret); } +free_buf: net_buf_unref(dns_data); quit: - net_pkt_unref(pkt); + return ret; +} + +static void svc_handler(struct k_work *work) +{ + struct net_socket_service_event *pev = + CONTAINER_OF(work, struct net_socket_service_event, work); + int ret; + + ret = recv_data(pev); + if (ret < 0) { + NET_ERR("DNS recv error (%d)", ret); + } } #if defined(CONFIG_NET_IPV6) @@ -573,8 +569,10 @@ static void iface_ipv6_cb(struct net_if *iface, void *user_data) ret = net_ipv6_mld_join(iface, addr); if (ret < 0) { - NET_DBG("Cannot join %s IPv6 multicast group (%d)", - net_sprint_ipv6_addr(addr), ret); + NET_DBG("Cannot join %s IPv6 multicast group to iface %d (%d)", + net_sprint_ipv6_addr(addr), + net_if_get_by_iface(iface), + ret); } } @@ -594,8 +592,8 @@ static void iface_ipv4_cb(struct net_if *iface, void *user_data) ret = net_ipv4_igmp_join(iface, addr, NULL); if (ret < 0) { - NET_DBG("Cannot add IPv4 multicast address to iface %p", - iface); + NET_DBG("Cannot add %s multicast address to iface %d", "IPv4", + net_if_get_by_iface(iface)); } } @@ -611,25 +609,52 @@ static int init_listener(void) { int ret, ok = 0; + ARRAY_FOR_EACH(fds, j) { + fds[j].fd = -1; + } + #if defined(CONFIG_NET_IPV6) { static struct sockaddr_in6 local_addr; setup_ipv6_addr(&local_addr); - ipv6 = get_ctx(AF_INET6); + ipv6 = get_socket(AF_INET6); ret = bind_ctx(ipv6, (struct sockaddr *)&local_addr, sizeof(local_addr)); if (ret < 0) { - net_context_put(ipv6); + zsock_close(ipv6); + goto ipv6_out; + } + + ret = -ENOENT; + + ARRAY_FOR_EACH(fds, j) { + if (fds[j].fd == ipv6) { + ret = 0; + break; + } + + if (fds[j].fd < 0) { + fds[j].fd = ipv6; + fds[j].events = ZSOCK_POLLIN; + ret = 0; + break; + } + } + + if (ret < 0) { + NET_DBG("Cannot set %s to socket (%d)", "polling", ret); + zsock_close(ipv6); goto ipv6_out; } - ret = net_context_recv(ipv6, recv_cb, K_NO_WAIT, ipv6); + ret = net_socket_service_register(&svc_llmnr, fds, ARRAY_SIZE(fds), NULL); if (ret < 0) { - NET_WARN("Cannot receive IPv6 LLMNR data (%d)", ret); - net_context_put(ipv6); + NET_DBG("Cannot register %s %s socket service (%d)", + "IPv6", "LLMNR", ret); + zsock_close(ipv6); } else { ok++; } @@ -641,19 +666,42 @@ static int init_listener(void) { setup_ipv4_addr(&local_addr4); - ipv4 = get_ctx(AF_INET); + ipv4 = get_socket(AF_INET); ret = bind_ctx(ipv4, (struct sockaddr *)&local_addr4, sizeof(local_addr4)); if (ret < 0) { - net_context_put(ipv4); + zsock_close(ipv4); goto ipv4_out; } - ret = net_context_recv(ipv4, recv_cb, K_NO_WAIT, ipv4); + ret = -ENOENT; + + ARRAY_FOR_EACH(fds, j) { + if (fds[j].fd == ipv4) { + ret = 0; + break; + } + + if (fds[j].fd < 0) { + fds[j].fd = ipv4; + fds[j].events = ZSOCK_POLLIN; + ret = 0; + break; + } + } + if (ret < 0) { - NET_WARN("Cannot receive IPv4 LLMNR data (%d)", ret); - net_context_put(ipv4); + NET_DBG("Cannot set %s to socket (%d)", "polling", ret); + zsock_close(ipv4); + goto ipv4_out; + } + + ret = net_socket_service_register(&svc_llmnr, fds, ARRAY_SIZE(fds), NULL); + if (ret < 0) { + NET_DBG("Cannot register %s %s socket service (%d)", + "IPv4", "LLMNR", ret); + zsock_close(ipv4); } else { ok++; } @@ -662,7 +710,7 @@ static int init_listener(void) #endif /* CONFIG_NET_IPV4 */ if (!ok) { - NET_WARN("Cannot start LLMNR responder"); + NET_WARN("Cannot start %s responder", "LLMNR"); } return !ok; @@ -670,7 +718,6 @@ static int init_listener(void) static int llmnr_responder_init(void) { - net_mgmt_init_event_callback(&mgmt_cb, llmnr_iface_event_handler, NET_EVENT_IF_UP); From 76b6dcff5007454a57f9a13e6a6568a5b522f274 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0969/1389] net: sockets: Add extra debug print for invalid socket access Print also thread name when printing socket access error. This helps debugging what thread caused it. Lowering the Error to Debug as we could be missing vtable for example for eventfd descriptors, this is easily seen when using socket service API. Signed-off-by: Jukka Rissanen --- subsys/net/lib/sockets/sockets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 1a027e2c83dafa..e75c0b0203fa79 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -89,8 +89,8 @@ static inline void *get_sock_vtable(int sock, #endif /* CONFIG_USERSPACE */ if (ctx == NULL) { - NET_ERR("invalid access on sock %d by thread %p", sock, - _current); + NET_DBG("Invalid access on sock %d by thread %p (%s)", sock, + _current, k_thread_name_get(_current)); } return ctx; From cf656bffecfe78cd8380e535f72536012746f819 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0970/1389] net: sockets: Check eventfd errors better With native_sim, this error is seen a lot when socket service API is used. net_sock: get_sock_vtable: (net_socket_service): Invalid access on sock 3 by thread 0x807a8e0 (net_socket_service) If we just ignore the error, then we might get into forever loop which is not good. So if this happens, mark the eventfd fd as not pollable to basically ignore the eventfd support in this case. Signed-off-by: Jukka Rissanen --- subsys/net/lib/sockets/sockets_service.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/subsys/net/lib/sockets/sockets_service.c b/subsys/net/lib/sockets/sockets_service.c index f8398e95df1dc3..6e034d57ea5b60 100644 --- a/subsys/net/lib/sockets/sockets_service.c +++ b/subsys/net/lib/sockets/sockets_service.c @@ -180,6 +180,7 @@ static int trigger_work(struct zsock_pollfd *pev) static void socket_service_thread(void) { int ret, i, fd, count = 0; + int error_count = 0; eventfd_t value; STRUCT_SECTION_COUNT(net_socket_service_desc, &ret); @@ -253,11 +254,25 @@ static void socket_service_thread(void) } if (ret > 0 && ctx.events[0].revents) { + if ((ctx.events[0].revents & ZSOCK_POLLNVAL) || + (ctx.events[0].revents & ZSOCK_POLLERR)) { + /* Ignore eventfd errors and turn eventfd + * support off if we get too many errors + */ + if (++error_count > 2) { + ctx.events[0].fd = -1; + } + + continue; + } + eventfd_read(ctx.events[0].fd, &value); NET_DBG("Received restart event."); goto restart; } + error_count = 0; + for (i = 1; i < (count + 1); i++) { if (ctx.events[i].fd < 0) { continue; From 90ef24d30886b8afff0534bce25ce58f57672cec Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0971/1389] samples: mgmt: updatehub: Fix build failure on frdm_k64f board The CONFIG_MAX_THREAD_BYTES=3 needs to be set otherwise this error is printed by CI. Too many thread objects (17) Increase CONFIG_MAX_THREAD_BYTES to 3 Signed-off-by: Jukka Rissanen --- samples/subsys/mgmt/updatehub/prj.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/subsys/mgmt/updatehub/prj.conf b/samples/subsys/mgmt/updatehub/prj.conf index e3b57ae4f339f5..98a20203bdf230 100644 --- a/samples/subsys/mgmt/updatehub/prj.conf +++ b/samples/subsys/mgmt/updatehub/prj.conf @@ -44,3 +44,5 @@ CONFIG_NET_SHELL=y # Debug helpers CONFIG_LOG=y #CONFIG_UPDATEHUB_LOG_LEVEL_DBG=y + +CONFIG_MAX_THREAD_BYTES=3 From 9207b18e549158b215530355e650116337ff2408 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0972/1389] samples: net: Add net_if.h include Because of changes in other network header files, the net_if.h was not included so add it directly to the echo-client and mqtt_azure sources. Signed-off-by: Jukka Rissanen --- samples/net/cloud/mqtt_azure/src/main.c | 1 + samples/net/sockets/echo_client/src/echo-client.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/net/cloud/mqtt_azure/src/main.c b/samples/net/cloud/mqtt_azure/src/main.c index 46ee6c66820b23..841c1fb7ebe0f1 100644 --- a/samples/net/cloud/mqtt_azure/src/main.c +++ b/samples/net/cloud/mqtt_azure/src/main.c @@ -8,6 +8,7 @@ LOG_MODULE_REGISTER(mqtt_azure, LOG_LEVEL_DBG); #include +#include #include #include diff --git a/samples/net/sockets/echo_client/src/echo-client.c b/samples/net/sockets/echo_client/src/echo-client.c index 9343b3b408e13c..59bc9be99f91ed 100644 --- a/samples/net/sockets/echo_client/src/echo-client.c +++ b/samples/net/sockets/echo_client/src/echo-client.c @@ -28,7 +28,7 @@ LOG_MODULE_REGISTER(net_echo_client_sample, LOG_LEVEL_DBG); #include #include - +#include #include #include #include From 1f104f847620e7f7aeee9ecf1b93f925f43dcd11 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0973/1389] tests: openthread: Add CONFIG_NET_TEST to make self contained Add CONFIG_NET_TEST=y to make the test self contained and not trying to create native_posix Ethernet interface which will normally fail. This prevents this error from printing [00:00:00.000,000] eth_posix: Cannot create zeth (-1) Signed-off-by: Jukka Rissanen --- tests/subsys/openthread/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/subsys/openthread/prj.conf b/tests/subsys/openthread/prj.conf index cee7218f84738a..f3884110630ac6 100644 --- a/tests/subsys/openthread/prj.conf +++ b/tests/subsys/openthread/prj.conf @@ -2,6 +2,7 @@ CONFIG_SHELL=y CONFIG_ZTEST=y CONFIG_IEEE802154=y CONFIG_NETWORKING=y +CONFIG_NET_TEST=y # Network buffers CONFIG_NET_PKT_RX_COUNT=5 From 4c37fea995c10ce9edf999b48b1581e5a297d41b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:18 +0200 Subject: [PATCH 0974/1389] tests: openthread: Disable native_posix board Eventfd is not compatible with native_posix so disable testing for it. Signed-off-by: Jukka Rissanen --- tests/subsys/openthread/testcase.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/subsys/openthread/testcase.yaml b/tests/subsys/openthread/testcase.yaml index c019aa9a8c54ec..163024d86b72b0 100644 --- a/tests/subsys/openthread/testcase.yaml +++ b/tests/subsys/openthread/testcase.yaml @@ -1,9 +1,10 @@ common: platform_allow: - - native_posix - - native_posix/native/64 - native_sim - native_sim/native/64 + platform_exclude: + - native_posix/native/64 + - native_posix integration_platforms: - native_sim tags: From 635df85be349124075a926f07cba4c4a9d4f9a85 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0975/1389] tests: net: socketpair: Fix log printing The LOG_MODULE_REGISTER() was not called anywhere so if one tried to enable logging, there was a linker error about missing logger functions. Signed-off-by: Jukka Rissanen --- tests/net/socket/socketpair/src/_main.c | 4 ++++ tests/net/socket/socketpair/src/_main.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tests/net/socket/socketpair/src/_main.c b/tests/net/socket/socketpair/src/_main.c index ff8027b0982a61..118d8be1209127 100644 --- a/tests/net/socket/socketpair/src/_main.c +++ b/tests/net/socket/socketpair/src/_main.c @@ -4,8 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define _main_defined 1 + #include "_main.h" +LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); + #include #include #include diff --git a/tests/net/socket/socketpair/src/_main.h b/tests/net/socket/socketpair/src/_main.h index f6df1a267f9187..d1dbe939b15892 100644 --- a/tests/net/socket/socketpair/src/_main.h +++ b/tests/net/socket/socketpair/src/_main.h @@ -16,7 +16,9 @@ #include #include +#if !defined(_main_defined) LOG_MODULE_DECLARE(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); +#endif struct net_socketpair_fixture { int sv[2]; From eb2894a3c85b99f796afb17ddd18c3fe68f8ab98 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0976/1389] tests: net: Exclude native_posix because of socket service The native_posix board does not work well with eventfd so disable it with tests that use socket service API. Signed-off-by: Jukka Rissanen --- tests/net/dhcpv4/client/testcase.yaml | 3 +++ tests/net/ipv6/testcase.yaml | 3 +++ tests/net/socket/getnameinfo/testcase.yaml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/tests/net/dhcpv4/client/testcase.yaml b/tests/net/dhcpv4/client/testcase.yaml index 512d4dc159bb6d..68d6c54271bcce 100644 --- a/tests/net/dhcpv4/client/testcase.yaml +++ b/tests/net/dhcpv4/client/testcase.yaml @@ -3,6 +3,9 @@ common: tags: - net - dhcpv4 + platform_exclude: + - native_posix/native/64 + - native_posix tests: net.dhcpv4_client: extra_configs: diff --git a/tests/net/ipv6/testcase.yaml b/tests/net/ipv6/testcase.yaml index 78be3c872afd7b..efc60810da2694 100644 --- a/tests/net/ipv6/testcase.yaml +++ b/tests/net/ipv6/testcase.yaml @@ -4,6 +4,9 @@ common: - ipv6 - ipv6_pe depends_on: netif + platform_exclude: + - native_posix/native/64 + - native_posix tests: net.ipv6: extra_configs: diff --git a/tests/net/socket/getnameinfo/testcase.yaml b/tests/net/socket/getnameinfo/testcase.yaml index 9edc6b2502e962..2e60ca44fe0061 100644 --- a/tests/net/socket/getnameinfo/testcase.yaml +++ b/tests/net/socket/getnameinfo/testcase.yaml @@ -1,6 +1,9 @@ common: depends_on: netif filter: CONFIG_FULL_LIBC_SUPPORTED + platform_exclude: + - native_posix + - native_posix/native/64 tests: net.socket.get_name_info: min_ram: 21 From 6966d47c68118c965773fddb551b32c6c5c2bad3 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0977/1389] logging: Fix network backend compilation Because of include file changes, we now need to include both hostname.h and net_if.h in the syslog logging module directly. Signed-off-by: Jukka Rissanen --- subsys/logging/backends/log_backend_net.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/logging/backends/log_backend_net.c b/subsys/logging/backends/log_backend_net.c index 0f15770cd4676e..3f49e0a40881c7 100644 --- a/subsys/logging/backends/log_backend_net.c +++ b/subsys/logging/backends/log_backend_net.c @@ -12,6 +12,8 @@ LOG_MODULE_REGISTER(log_backend_net, CONFIG_LOG_DEFAULT_LEVEL); #include #include #include +#include +#include #include /* Set this to 1 if you want to see what is being sent to server */ From 16661d77a4332ca16a0e01349cd4834a21b74b41 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0978/1389] net: ipv6: Fix RA RDNSS and DNS_RESOLVER interdependencies A support for RDNSS option should not force DNS subsystem being enabled in the system, especially that the option is enabled by default. It should work the other way around - the option is supported only if DNS was enabled by the user. Signed-off-by: Robert Lubos --- subsys/net/ip/Kconfig.ipv6 | 2 +- tests/net/ipv6/prj.conf | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/Kconfig.ipv6 b/subsys/net/ip/Kconfig.ipv6 index 21b7aad397b8dc..aa1f215b1ff3d2 100644 --- a/subsys/net/ip/Kconfig.ipv6 +++ b/subsys/net/ip/Kconfig.ipv6 @@ -159,7 +159,7 @@ config NET_IPV6_DAD config NET_IPV6_RA_RDNSS bool "Support RA RDNSS option" depends on NET_IPV6_ND - select DNS_RESOLVER + depends on DNS_RESOLVER default y help Support Router Advertisement Recursive DNS Server option. diff --git a/tests/net/ipv6/prj.conf b/tests/net/ipv6/prj.conf index e6a4a365e2bc18..b2b2f0886733bb 100644 --- a/tests/net/ipv6/prj.conf +++ b/tests/net/ipv6/prj.conf @@ -17,6 +17,7 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_IPV6_ND=y CONFIG_NET_IPV6_DAD=y +CONFIG_DNS_RESOLVER=y # To verify NET_IPV6_RA_RDNSS CONFIG_NET_PKT_TX_COUNT=20 CONFIG_NET_PKT_RX_COUNT=20 CONFIG_NET_BUF_RX_COUNT=20 From 6ef08461ac32a6ab54ee35a254ff8939faaa6a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20S=C3=B8rensen?= Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0979/1389] boards: fixed SPI DTS bug for nrf5340_audio_dk board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the SPI DTS bug on the nrf5340_audio_dk board which was introduced by b8978e9: unit address and first address in 'reg' (0x0) don't match for /soc/peripheral@50000000/spi@a000/sdhc@1 unit address and first address in 'reg' (0x1) don't match for /soc/peripheral@50000000/spi@a000/cs47l63@2 Signed-off-by: Tim Sørensen --- .../nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi index 278f78530780a8..8504e23ed7e507 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi @@ -193,7 +193,7 @@ arduino_spi: &spi4 { pinctrl-names = "default", "sleep"; sdhc0: sdhc@1 { compatible = "zephyr,sdhc-spi-slot"; - reg = <0>; + reg = <1>; status = "okay"; sdmmc { compatible = "zephyr,sdmmc-disk"; @@ -205,7 +205,7 @@ arduino_spi: &spi4 { cs47l63: cs47l63@2 { compatible = "cirrus,cs47l63"; - reg = <1>; + reg = <2>; spi-max-frequency = <8000000>; irq-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; From 0c8903d5d562c8410d48074e686356e8241ea423 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0980/1389] net: ipv6: Fix DAD conflict detection Filtering out received packets which source address matches one of our own addresses has broken the duplicate address detection conflict reporting. In case Neighbor Advertisement is sent during DAD collision, the source address of such packet might be set to the address that triggered the collision. This address would also be set on our interface, marked as tentative. Therefore in order to make duplicate address detection work, we cannot filter out packets in case our own address is still in tentative state. Signed-off-by: Robert Lubos --- subsys/net/ip/ipv6.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/ipv6.c b/subsys/net/ip/ipv6.c index d1f1d176350f03..9d094c9c4c9f8f 100644 --- a/subsys/net/ip/ipv6.c +++ b/subsys/net/ip/ipv6.c @@ -505,6 +505,8 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback) } if (!is_loopback) { + struct net_if_addr *ifaddr; + if (net_ipv6_is_addr_loopback((struct in6_addr *)hdr->dst) || net_ipv6_is_addr_loopback((struct in6_addr *)hdr->src)) { NET_DBG("DROP: ::1 packet"); @@ -521,7 +523,12 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback) goto drop; } - if (net_ipv6_is_my_addr((struct in6_addr *)hdr->src)) { + /* We need to pass the packet through in case our address is + * tentative, as receiving a packet with a tentative address as + * source means that duplicate address has been detected. + */ + ifaddr = net_if_ipv6_addr_lookup((struct in6_addr *)hdr->src, NULL); + if (ifaddr != NULL && ifaddr->addr_state != NET_ADDR_TENTATIVE) { NET_DBG("DROP: src addr is %s", "mine"); goto drop; } From c7a0652a86ef33762f0277ba158fb99442efb1a5 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0981/1389] tests: net: mld: Add more test cases involving iface state changes Add more test cases verifying that MLD events/reports are sent accordingly when interface state changes. Introduce separate semaphores for waiting for network events, as having a single one for transmit and events is ambiguous in tests. Signed-off-by: Robert Lubos --- tests/net/mld/prj.conf | 1 + tests/net/mld/src/main.c | 189 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 176 insertions(+), 14 deletions(-) diff --git a/tests/net/mld/prj.conf b/tests/net/mld/prj.conf index a0e0020d729efa..8030ffb7910525 100644 --- a/tests/net/mld/prj.conf +++ b/tests/net/mld/prj.conf @@ -20,6 +20,7 @@ CONFIG_NET_BUF_RX_COUNT=20 CONFIG_NET_BUF_TX_COUNT=20 CONFIG_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=8 CONFIG_NET_SOCKETS=y diff --git a/tests/net/mld/src/main.c b/tests/net/mld/src/main.c index abfaca57a30726..e1bcce056cfaf3 100644 --- a/tests/net/mld/src/main.c +++ b/tests/net/mld/src/main.c @@ -72,6 +72,7 @@ static struct in6_addr peer_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, static struct in6_addr mcast_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +static struct in6_addr *exp_mcast_group; static struct net_if *net_iface; static bool is_group_joined; static bool is_group_left; @@ -84,6 +85,8 @@ static bool ignore_already; static struct mld_report_handler *report_handler; K_SEM_DEFINE(wait_data, 0, UINT_MAX); +K_SEM_DEFINE(wait_joined, 0, UINT_MAX); +K_SEM_DEFINE(wait_left, 0, UINT_MAX); #define WAIT_TIME 500 #define WAIT_TIME_LONG MSEC_PER_SEC @@ -209,6 +212,30 @@ NET_DEVICE_INIT(net_test_null_iface, "net_test_null_iface", net_test_dev_init, N &net_test_null_data, NULL, 99, &net_test_null_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE, 127); +static void test_iface_down_up(void) +{ + zassert_ok(net_if_down(net_iface), "Failed to bring iface down"); + k_msleep(10); + zassert_ok(net_if_up(net_iface), "Failed to bring iface up"); +} + +static void test_iface_down_up_delayed_carrier(void) +{ + zassert_ok(net_if_down(net_iface), "Failed to bring iface down"); + k_msleep(10); + net_if_carrier_off(net_iface); + zassert_ok(net_if_up(net_iface), "Failed to bring iface up"); + k_msleep(10); + net_if_carrier_on(net_iface); +} + +static void test_iface_carrier_off_on(void) +{ + net_if_carrier_off(net_iface); + k_msleep(10); + net_if_carrier_on(net_iface); +} + static void group_joined(struct net_mgmt_event_callback *cb, uint32_t nm_event, struct net_if *iface) { @@ -217,9 +244,12 @@ static void group_joined(struct net_mgmt_event_callback *cb, return; } - is_group_joined = true; + if (exp_mcast_group == NULL || + net_ipv6_addr_cmp(exp_mcast_group, cb->info)) { + is_group_joined = true; - k_sem_give(&wait_data); + k_sem_give(&wait_joined); + } } static void group_left(struct net_mgmt_event_callback *cb, @@ -230,9 +260,12 @@ static void group_left(struct net_mgmt_event_callback *cb, return; } - is_group_left = true; + if (exp_mcast_group == NULL || + net_ipv6_addr_cmp(exp_mcast_group, cb->info)) { + is_group_left = true; - k_sem_give(&wait_data); + k_sem_give(&wait_left); + } } static struct mgmt_events { @@ -262,8 +295,6 @@ static void *test_mld_setup(void) { struct net_if_addr *ifaddr; - report_handler = NULL; - setup_mgmt_events(); net_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY)); @@ -278,6 +309,14 @@ static void *test_mld_setup(void) return NULL; } +static void test_mld_before(void *fixture) +{ + ARG_UNUSED(fixture); + + report_handler = NULL; + exp_mcast_group = NULL; +} + static void test_join_group(void) { int ret; @@ -319,7 +358,7 @@ static void test_catch_join_group(void) test_join_group(); - if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) { + if (k_sem_take(&wait_joined, K_MSEC(WAIT_TIME))) { zassert_true(0, "Timeout while waiting join event"); } @@ -336,7 +375,7 @@ static void test_catch_leave_group(void) test_leave_group(); - if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) { + if (k_sem_take(&wait_left, K_MSEC(WAIT_TIME))) { zassert_true(0, "Timeout while waiting leave event"); } @@ -355,7 +394,7 @@ static void test_verify_join_group(void) test_join_group(); - if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) { + if (k_sem_take(&wait_joined, K_MSEC(WAIT_TIME))) { zassert_true(0, "Timeout while waiting join event"); } @@ -372,7 +411,7 @@ static void test_verify_leave_group(void) test_leave_group(); - if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) { + if (k_sem_take(&wait_left, K_MSEC(WAIT_TIME))) { zassert_true(0, "Timeout while waiting leave event"); } @@ -598,6 +637,82 @@ ZTEST(net_mld_test_suite, test_allnodes) "allnodes multicast address"); } +static void expect_exclude_mcast_report(struct net_pkt *pkt, void *user_data) +{ + struct mld_report_mcast_record record; + uint16_t records_count; + uint16_t res_bytes; + bool *report_sent = user_data; + + zassert_not_null(exp_mcast_group, "Expected mcast group not sent"); + + net_pkt_set_overwrite(pkt, true); + net_pkt_skip(pkt, sizeof(struct net_icmp_hdr)); + + zassert_ok(net_pkt_read_be16(pkt, &res_bytes), "Failed to read reserved bytes"); + zassert_equal(0, res_bytes, "Reserved bytes must be zeroed"); + + zassert_ok(net_pkt_read_be16(pkt, &records_count), "Failed to read addr count"); + zexpect_equal(records_count, 1, "Incorrect record count "); + + net_pkt_read(pkt, &record, sizeof(struct mld_report_mcast_record)); + + if (record.record_type == NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE && + net_ipv6_addr_cmp_raw((const uint8_t *)exp_mcast_group, + (const uint8_t *)&record.mcast_addr)) { + *report_sent = true; + } +} + +static void verify_allnodes_on_iface_event(void (*action)(void)) +{ + struct net_if *iface = NULL; + struct net_if_mcast_addr *ifmaddr; + struct in6_addr addr; + bool exclude_report_sent = false; + struct mld_report_handler handler = { + .fn = expect_exclude_mcast_report, + .user_data = &exclude_report_sent + }; + + net_ipv6_addr_create_ll_allnodes_mcast(&addr); + k_sem_reset(&wait_joined); + + is_group_joined = false; + exp_mcast_group = &addr; + report_handler = &handler; + + action(); + + zassert_ok(k_sem_take(&wait_joined, K_MSEC(WAIT_TIME)), + "Timeout while waiting for an event"); + + ifmaddr = net_if_ipv6_maddr_lookup(&addr, &iface); + zassert_not_null(ifmaddr, "Interface does not contain " + "allnodes multicast address"); + + zassert_true(is_group_joined, "Did not join mcast group"); + zassert_true(exclude_report_sent, "Did not send report"); +} + +/* Verify that mcast all nodes is present after interface admin state toggle */ +ZTEST(net_mld_test_suite, test_allnodes_after_iface_up) +{ + verify_allnodes_on_iface_event(test_iface_down_up); +} + +/* Verify that mcast all nodes is present after delayed carrier on */ +ZTEST(net_mld_test_suite, test_allnodes_after_iface_up_carrier_delayed) +{ + verify_allnodes_on_iface_event(test_iface_down_up_delayed_carrier); +} + +/* Verify that mcast all nodes is present after carrier toggle */ +ZTEST(net_mld_test_suite, test_allnodes_after_carrier_toggle) +{ + verify_allnodes_on_iface_event(test_iface_carrier_off_on); +} + ZTEST(net_mld_test_suite, test_solicit_node) { struct net_if *iface = NULL; @@ -612,6 +727,55 @@ ZTEST(net_mld_test_suite, test_solicit_node) "solicit node multicast address"); } +static void verify_solicit_node_on_iface_event(void (*action)(void)) +{ + struct net_if *iface = NULL; + struct net_if_mcast_addr *ifmaddr; + struct in6_addr addr; + bool exclude_report_sent = false; + struct mld_report_handler handler = { + .fn = expect_exclude_mcast_report, + .user_data = &exclude_report_sent + }; + + net_ipv6_addr_create_solicited_node(&my_addr, &addr); + k_sem_reset(&wait_joined); + + is_group_joined = false; + exp_mcast_group = &addr; + report_handler = &handler; + + action(); + + zassert_ok(k_sem_take(&wait_joined, K_MSEC(WAIT_TIME)), + "Timeout while waiting for an event"); + + ifmaddr = net_if_ipv6_maddr_lookup(&addr, &iface); + zassert_not_null(ifmaddr, "Interface does not contain " + "solicit node multicast address"); + + zassert_true(is_group_joined, "Did not join mcast group"); + zassert_true(exclude_report_sent, "Did not send report"); +} + +/* Verify that mcast solicited node is present after interface admin state toggle */ +ZTEST(net_mld_test_suite, test_solicit_node_after_iface_up) +{ + verify_solicit_node_on_iface_event(test_iface_down_up); +} + +/* Verify that mcast solicited node is present after delayed carrier on */ +ZTEST(net_mld_test_suite, test_solicit_node_after_iface_up_carrier_delayed) +{ + verify_solicit_node_on_iface_event(test_iface_down_up_delayed_carrier); +} + +/* Verify that mcast solicited node is present after delayed carrier toggle */ +ZTEST(net_mld_test_suite, test_solicit_node_after_carrier_toggle) +{ + verify_solicit_node_on_iface_event(test_iface_carrier_off_on); +} + ZTEST(net_mld_test_suite, test_join_leave) { test_join_group(); @@ -851,9 +1015,6 @@ ZTEST(net_mld_test_suite, test_mcast_routes_in_mld) verify_mcast_routes_in_mld(&info); } - /* Disable report handler */ - report_handler = NULL; - leave_mldv2_capable_routers_group(); } @@ -941,4 +1102,4 @@ ZTEST_USER(net_mld_test_suite, test_socket_catch_join_with_index) socket_leave_group_with_index(&my_addr); } -ZTEST_SUITE(net_mld_test_suite, NULL, test_mld_setup, NULL, NULL, NULL); +ZTEST_SUITE(net_mld_test_suite, NULL, test_mld_setup, test_mld_before, NULL, NULL); From bb8ea8576572693929e96376c61298857c89f842 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0982/1389] tests: net: ipv6: Restore original LL address in test_change_ll_addr Restore the original LL address on the interface after tests, instead of generating a new one, to avoid dangling link-local IPv6 on the interface. Signed-off-by: Robert Lubos --- tests/net/ipv6/src/main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index 59f374024c02e3..9ce127bf9feb56 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -1182,12 +1182,7 @@ ZTEST(net_ipv6, test_change_ll_addr) zassert_true(memcmp(ll->addr, ll_iface->addr, ll->len) != 0, "Wrong link address 2"); - ll_iface->addr[0] = 0x00; - ll_iface->addr[1] = 0x00; - ll_iface->addr[2] = 0x5E; - ll_iface->addr[3] = 0x00; - ll_iface->addr[4] = 0x53; - ll_iface->addr[5] = sys_rand8_get(); + ll_iface->addr = net_test_data.mac_addr; } ZTEST(net_ipv6, test_dad_timeout) From dcdad10b604c76ab8d91765c55d34247b1aa87b9 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0983/1389] tests: net: ipv6: Fix packet leak Receive callback has to unref the packet received, otherwise we leak packet. Signed-off-by: Robert Lubos --- tests/net/ipv6/src/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index 9ce127bf9feb56..c1cafe6f3704cd 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -1403,6 +1403,8 @@ static void recv_cb(struct net_context *context, recv_cb_called = true; + net_pkt_unref(pkt); + k_sem_give(&wait_data); } From 60cba36d073951075f77a9cc040f2354601ec930 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0984/1389] test: net: ipv6: Cleanup Ethernet test interface operation One of the test interfaces is defined as Ethernet interface, however it was missing ethernet_init() call, hence for example interface flags were uninitialized. This can cause issues with multicast tests, as NET_L2_MULTICAST flag was missing on the interface. Additionally, Ethernet-type interfaces should use struct ethernet_context as a base for their context data, otherwise Ethernet L2 will reach to some rubbish memory locations. Finally, since the interface now defines correct flags, all-nodes multicast address is now added to the interface automatically as a part of ND logic. Therefore, skip adding that address manually from ipv6_setup(). Signed-off-by: Robert Lubos --- tests/net/ipv6/src/main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index c1cafe6f3704cd..8c1f32940d08d2 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -155,6 +155,7 @@ struct net_if_addr *ifaddr_record; #define PEER_PORT 16233 struct net_test_ipv6 { + struct ethernet_context ctx; uint8_t mac_addr[sizeof(struct net_eth_addr)]; struct net_linkaddr ll_addr; }; @@ -187,6 +188,10 @@ static void net_test_iface_init(struct net_if *iface) net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr), NET_LINK_ETHERNET); + + if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + ethernet_init(iface); + } } /** @@ -471,7 +476,6 @@ static void nbr_lookup_ok(void) static void *ipv6_setup(void) { struct net_if_addr *ifaddr = NULL, *ifaddr2; - struct net_if_mcast_addr *maddr; struct net_if *iface = TEST_NET_IF; struct net_if *iface2 = NULL; struct net_if_ipv6 *ipv6; @@ -507,12 +511,6 @@ static void *ipv6_setup(void) ifaddr2 = net_if_ipv6_addr_lookup(&my_addr, &iface2); zassert_true(ifaddr2 == ifaddr, "Invalid ifaddr (%p vs %p)\n", ifaddr, ifaddr2); - net_ipv6_addr_create(&multicast_addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001); - - maddr = net_if_ipv6_maddr_add(iface, &multicast_addr); - zassert_not_null(maddr, "Cannot add multicast IPv6 address %s\n", - net_sprint_ipv6_addr(&multicast_addr)); - /* The semaphore is there to wait the data to be received. */ k_sem_init(&wait_data, 0, UINT_MAX); From c3df230a88775dbd74d7a1a7c7171cde8d925af0 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0985/1389] tests: net: ipv6: Add more test cases involving iface state changes Add tests verifying valid IPv6 ND behaviors on interface state changes, specifically: * Verify RS is sent, and upon RA reception prefix and autoconf address added accordingly. * DAD is triggered for autoconf, static and LL IPv6 addresses. * IPv6 address is not used upon DAD conflict. * IPv6 neighbor discovery works as expected. * Multicast transmission/reception is functional after interface state changes. Signed-off-by: Robert Lubos --- tests/net/ipv6/src/main.c | 520 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 505 insertions(+), 15 deletions(-) diff --git a/tests/net/ipv6/src/main.c b/tests/net/ipv6/src/main.c index 8c1f32940d08d2..02df9ac650c6c6 100644 --- a/tests/net/ipv6/src/main.c +++ b/tests/net/ipv6/src/main.c @@ -43,13 +43,28 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_LOG_LEVEL); #endif #define TEST_NET_IF net_if_lookup_by_dev(DEVICE_GET(eth_ipv6_net)) +#define TEST_MSG_SIZE 128 static struct in6_addr my_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; static struct in6_addr peer_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; static struct in6_addr multicast_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +static struct in6_addr all_nodes_mcast = { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; + +/* Below should match prefix/addr distributed in RA message. */ +static struct in6_addr test_router_addr = { { { + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x2, 0x60, + 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea +} } }; +static struct in6_addr test_ra_prefix = { { { 0x3f, 0xfe, 0x05, 0x07, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0 } } }; +static struct in6_addr test_ra_autoconf_addr = { { { + 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x5e, 0xff, 0xfe, 0x00, 0x53, 0x00 +} } }; /* ICMPv6 NS frame (74 bytes) */ static const unsigned char icmpv6_ns_invalid[] = { @@ -141,12 +156,22 @@ static const unsigned char ipv6_hbho[] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* ...... */ }; +static int send_msg(struct in6_addr *src, struct in6_addr *dst); + +typedef void (*ns_callback)(struct net_pkt *pkt, void *user_data); + +struct test_ns_handler { + ns_callback fn; + void *user_data; +}; + static bool expecting_ra; static uint32_t dad_time[3]; static bool test_failed; static struct k_sem wait_data; static bool recv_cb_called; struct net_if_addr *ifaddr_record; +static struct test_ns_handler *ns_handler; #define WAIT_TIME 250 #define WAIT_TIME_LONG MSEC_PER_SEC @@ -221,6 +246,55 @@ static void prepare_ra_message(struct net_pkt *pkt) net_pkt_cursor_init(pkt); } +static void inject_na_message(struct net_if *iface, struct in6_addr *src, + struct in6_addr *dst, struct in6_addr *target, + uint8_t flags) +{ + struct net_eth_hdr hdr; + struct net_pkt *pkt; + uint8_t na_flags[] = { flags, 0, 0, 0 }; + uint8_t na_tlla_opt[] = { 0x02, 0x01, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; + + pkt = net_pkt_alloc_with_buffer(iface, TEST_MSG_SIZE, AF_INET6, + IPPROTO_ICMPV6, K_NO_WAIT); + zassert_not_null(pkt, "Failed to allocate packet"); + + net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT); + + hdr.type = htons(NET_ETH_PTYPE_IPV6); + memset(&hdr.src, 0xaa, sizeof(struct net_eth_addr)); + memcpy(&hdr.dst, net_pkt_iface(pkt)->if_dev->link_addr.addr, + sizeof(struct net_eth_addr)); + + /* Reserve space for the L2 header. */ + net_buf_reserve(pkt->frags, sizeof(struct net_eth_hdr)); + net_pkt_cursor_init(pkt); + net_pkt_set_overwrite(pkt, false); + + zassert_ok(net_ipv6_create(pkt, src, dst)); + zassert_ok(net_icmpv6_create(pkt, NET_ICMPV6_NA, 0)); + zassert_ok(net_pkt_write(pkt, na_flags, sizeof(na_flags))); + zassert_ok(net_pkt_write(pkt, target, sizeof(struct in6_addr))); + zassert_ok(net_pkt_write(pkt, na_tlla_opt, sizeof(na_tlla_opt))); + + net_pkt_cursor_init(pkt); + net_ipv6_finalize(pkt, IPPROTO_ICMPV6); + + /* Fill L2 header. */ + net_buf_push_mem(pkt->frags, &hdr, sizeof(struct net_eth_hdr)); + + net_pkt_cursor_init(pkt); + zassert_ok((net_recv_data(iface, pkt)), "Data receive for NA failed."); +} + +static void skip_headers(struct net_pkt *pkt) +{ + net_pkt_cursor_init(pkt); + net_pkt_skip(pkt, sizeof(struct net_eth_hdr)); + net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt)); + net_pkt_skip(pkt, sizeof(struct net_icmp_hdr)); +} + static struct net_icmp_hdr *get_icmp_hdr(struct net_pkt *pkt) { NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr); @@ -272,6 +346,10 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt) } if (icmp->type == NET_ICMPV6_NS) { + if (ns_handler != NULL) { + ns_handler->fn(pkt, ns_handler->user_data); + } + if (dad_time[0] == 0U) { dad_time[0] = k_uptime_get_32(); } else if (dad_time[1] == 0U) { @@ -315,6 +393,30 @@ NET_DEVICE_INIT(eth_ipv6_net, "eth_ipv6_net", &net_test_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE, NET_ETH_MTU); +static void test_iface_down_up(void) +{ + zassert_ok(net_if_down(TEST_NET_IF), "Failed to bring iface down"); + k_msleep(10); + zassert_ok(net_if_up(TEST_NET_IF), "Failed to bring iface up"); +} + +static void test_iface_down_up_delayed_carrier(void) +{ + zassert_ok(net_if_down(TEST_NET_IF), "Failed to bring iface down"); + k_msleep(10); + net_if_carrier_off(TEST_NET_IF); + zassert_ok(net_if_up(TEST_NET_IF), "Failed to bring iface up"); + k_msleep(10); + net_if_carrier_on(TEST_NET_IF); +} + +static void test_iface_carrier_off_on(void) +{ + net_if_carrier_off(TEST_NET_IF); + k_msleep(10); + net_if_carrier_on(TEST_NET_IF); +} + /* dummy interface for multi-interface tests */ static int dummy_send(const struct device *dev, struct net_pkt *pkt) { @@ -520,9 +622,20 @@ static void *ipv6_setup(void) nbr_lookup_ok(); k_sleep(K_MSEC(50)); + /* Last, randomized MAC byte needs to be copied to the expected autoconf + * address. + */ + test_ra_autoconf_addr.s6_addr[15] = net_if_get_link_addr(iface)->addr[5]; + return NULL; } +static void ipv6_before(void *fixture) +{ + ARG_UNUSED(fixture); + + ns_handler = NULL; +} static void ipv6_teardown(void *dummy) { @@ -629,6 +742,73 @@ ZTEST(net_ipv6, test_send_ns_no_options) "Data receive for invalid NS failed."); } +struct test_nd_context { + struct k_sem wait_ns; + struct in6_addr *exp_ns_addr; + bool reply; +}; + +static void expect_nd_ns(struct net_pkt *pkt, void *user_data) +{ + uint32_t res_bytes; + struct in6_addr target; + struct test_nd_context *ctx = user_data; + + skip_headers(pkt); + + zassert_ok(net_pkt_read_be32(pkt, &res_bytes), "Failed to read reserved bytes"); + zassert_equal(0, res_bytes, "Reserved bytes must be zeroed"); + zassert_ok(net_pkt_read(pkt, &target, sizeof(struct in6_addr)), + "Failed to read target address"); + + if (net_ipv6_addr_cmp(ctx->exp_ns_addr, &target)) { + if (ctx->reply) { + inject_na_message(net_pkt_iface(pkt), &target, &my_addr, + &target, NET_ICMPV6_NA_FLAG_SOLICITED); + } + + k_sem_give(&ctx->wait_ns); + } +} + +ZTEST(net_ipv6, test_send_neighbor_discovery) +{ + struct test_nd_context ctx = { + .exp_ns_addr = &test_router_addr, + .reply = true + }; + struct test_ns_handler handler = { + .fn = expect_nd_ns, + .user_data = &ctx + }; + enum net_verdict verdict; + struct net_nbr *nbr; + + k_sem_init(&ctx.wait_ns, 0, 1); + ns_handler = &handler; + + (void)net_ipv6_nbr_rm(TEST_NET_IF, &test_router_addr); + + verdict = send_msg(&my_addr, &test_router_addr); + zassert_equal(verdict, NET_OK, "Packet was dropped (%d)", verdict); + zassert_ok(k_sem_take(&ctx.wait_ns, K_MSEC(WAIT_TIME)), + "Timeout while waiting for expected NS"); + + k_sleep(K_MSEC(10)); + + /* Neighbor should be here now. */ + nbr = net_ipv6_nbr_lookup(TEST_NET_IF, &test_router_addr); + zassert_not_null(nbr, "Neighbor not found."); + zassert_equal(net_ipv6_nbr_data(nbr)->state, NET_IPV6_NBR_STATE_REACHABLE, + "Neighbor should be reachable at this point."); + + /* Second attempt (neighbor valid) should give no NS. */ + verdict = send_msg(&my_addr, &test_router_addr); + zassert_equal(verdict, NET_OK, "Packet was dropped (%d)", verdict); + zassert_equal(k_sem_take(&ctx.wait_ns, K_MSEC(10)), -EAGAIN, + "Should not get NS"); +} + /** * @brief IPv6 prefix timeout */ @@ -701,10 +881,6 @@ static void rs_message(void) static void ra_message(void) { - struct in6_addr addr = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x2, 0x60, - 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea } } }; - struct in6_addr prefix = { { { 0x3f, 0xfe, 0x05, 0x07, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0 } } }; struct in6_addr route_prefix = { { { 0x20, 0x01, 0x0d, 0xb0, 0x0f, 0xff } } }; struct sockaddr_in6 dns_addr = { .sin6_family = AF_INET6, @@ -715,6 +891,7 @@ static void ra_message(void) struct net_route_entry *route; struct dns_resolve_context *ctx; struct sockaddr_in6 *dns_server; + struct net_if_addr *ifaddr; /* We received RA message earlier, make sure that the information * in that message is placed to proper prefix and lookup info. @@ -722,13 +899,21 @@ static void ra_message(void) expecting_ra = false; - zassert_false(!net_if_ipv6_prefix_lookup(TEST_NET_IF, &prefix, 32), + zassert_false(!net_if_ipv6_prefix_lookup(TEST_NET_IF, &test_ra_prefix, 64), "Prefix %s should be here\n", - net_sprint_ipv6_addr(&prefix)); + net_sprint_ipv6_addr(&test_ra_prefix)); - zassert_false(!net_if_ipv6_router_lookup(TEST_NET_IF, &addr), + zassert_false(!net_if_ipv6_router_lookup(TEST_NET_IF, &test_router_addr), "Router %s should be here\n", - net_sprint_ipv6_addr(&addr)); + net_sprint_ipv6_addr(&test_router_addr)); + + /* Check if autoconf address was added correctly. */ + ifaddr = net_if_ipv6_addr_lookup_by_iface(TEST_NET_IF, + &test_ra_autoconf_addr); + zassert_not_null(ifaddr, "Autoconf address %s missing", + net_sprint_ipv6_addr(&test_ra_autoconf_addr)); + zassert_equal(ifaddr->addr_type, NET_ADDR_AUTOCONF, + "Address type should be autoconf"); /* Check if route was added correctly. */ route = net_route_lookup(TEST_NET_IF, &route_prefix); @@ -759,6 +944,86 @@ ZTEST(net_ipv6, test_rs_ra_message) ra_message(); } +struct test_dad_context { + struct k_sem wait_dad; + struct in6_addr *exp_dad_addr; + bool reply; +}; + +static void expect_dad_ns(struct net_pkt *pkt, void *user_data) +{ + uint32_t res_bytes; + struct in6_addr target; + struct test_dad_context *ctx = user_data; + + skip_headers(pkt); + + zassert_ok(net_pkt_read_be32(pkt, &res_bytes), "Failed to read reserved bytes"); + zassert_equal(0, res_bytes, "Reserved bytes must be zeroed"); + zassert_ok(net_pkt_read(pkt, &target, sizeof(struct in6_addr)), + "Failed to read target address"); + + if (net_ipv6_addr_cmp(ctx->exp_dad_addr, &target)) { + if (ctx->reply) { + inject_na_message(net_pkt_iface(pkt), &target, + &all_nodes_mcast, &target, 0); + } + + k_sem_give(&ctx->wait_dad); + } +} + +/* Verify that RS is sent after interface state change, RA processed, + * prefix added and autoconf address configured. + */ +static void verify_rs_on_iface_event(void (*action)(void)) +{ + struct net_if_router *router; + struct test_dad_context ctx = { + .exp_dad_addr = &test_ra_autoconf_addr + }; + struct test_ns_handler handler = { + .fn = expect_dad_ns, + .user_data = &ctx + }; + + (void)net_if_ipv6_prefix_rm(TEST_NET_IF, &test_ra_prefix, 64); + + router = net_if_ipv6_router_lookup(TEST_NET_IF, &test_router_addr); + if (router) { + (void)net_if_ipv6_router_rm(router); + } + + k_sem_init(&ctx.wait_dad, 0, 1); + + ns_handler = &handler; + expecting_ra = true; + + action(); + + k_sleep(K_MSEC(10)); + + ra_message(); + + zassert_ok(k_sem_take(&ctx.wait_dad, K_MSEC(WAIT_TIME)), + "Timeout while waiting for DAD NS"); +} + +ZTEST(net_ipv6, test_rs_after_iface_up) +{ + verify_rs_on_iface_event(test_iface_down_up); +} + +ZTEST(net_ipv6, test_rs_after_iface_up_carrier_delayed) +{ + verify_rs_on_iface_event(test_iface_down_up_delayed_carrier); +} + +ZTEST(net_ipv6, test_rs_after_carrier_toggle) +{ + verify_rs_on_iface_event(test_iface_carrier_off_on); +} + /** * @brief IPv6 parse Hop-By-Hop Option */ @@ -1136,20 +1401,17 @@ ZTEST(net_ipv6, test_change_ll_addr) static uint8_t new_mac[] = { 00, 01, 02, 03, 04, 05 }; struct net_linkaddr_storage *ll; struct net_linkaddr *ll_iface; - struct in6_addr dst; struct net_if *iface; struct net_nbr *nbr; uint32_t flags; int ret; - net_ipv6_addr_create(&dst, 0xff02, 0, 0, 0, 0, 0, 0, 1); - iface = TEST_NET_IF; flags = NET_ICMPV6_NA_FLAG_ROUTER | NET_ICMPV6_NA_FLAG_OVERRIDE; - ret = net_ipv6_send_na(iface, &peer_addr, &dst, + ret = net_ipv6_send_na(iface, &peer_addr, &all_nodes_mcast, &peer_addr, flags); zassert_false(ret < 0, "Cannot send NA 1"); @@ -1168,7 +1430,7 @@ ZTEST(net_ipv6, test_change_ll_addr) */ ll_iface->addr = new_mac; - ret = net_ipv6_send_na(iface, &peer_addr, &dst, + ret = net_ipv6_send_na(iface, &peer_addr, &all_nodes_mcast, &peer_addr, flags); zassert_false(ret < 0, "Cannot send NA 2"); @@ -1223,6 +1485,118 @@ ZTEST(net_ipv6, test_dad_timeout) #endif } + +/* Verify that DAD NS is sent after interface state change, for static address + * (added to the interface in ipv6_setup()). + */ +static void verify_dad_on_static_addr_on_iface_event(void (*action)(void)) +{ + struct test_dad_context ctx = { + .exp_dad_addr = &my_addr + }; + struct test_ns_handler handler = { + .fn = expect_dad_ns, + .user_data = &ctx + }; + + k_sem_init(&ctx.wait_dad, 0, 1); + + ns_handler = &handler; + + action(); + + zassert_ok(k_sem_take(&ctx.wait_dad, K_MSEC(WAIT_TIME)), + "Timeout while waiting for DAD NS"); +} + +ZTEST(net_ipv6, test_dad_on_static_addr_after_iface_up) +{ + verify_dad_on_static_addr_on_iface_event(test_iface_down_up); +} + +ZTEST(net_ipv6, test_dad_on_static_addr_after_iface_up_carrier_delayed) +{ + verify_dad_on_static_addr_on_iface_event(test_iface_down_up_delayed_carrier); +} + +ZTEST(net_ipv6, test_dad_on_static_addr_after_carrier_toggle) +{ + verify_dad_on_static_addr_on_iface_event(test_iface_carrier_off_on); +} + +/* Verify that DAD NS is sent after interface state change, for link-local + * address. + */ +static void verify_dad_on_ll_addr_on_iface_event(void (*action)(void)) +{ + struct in6_addr link_local_addr; + struct test_dad_context ctx = { + .exp_dad_addr = &link_local_addr + }; + struct test_ns_handler handler = { + .fn = expect_dad_ns, + .user_data = &ctx + }; + + net_ipv6_addr_create_iid(&link_local_addr, + net_if_get_link_addr(TEST_NET_IF)); + k_sem_init(&ctx.wait_dad, 0, 1); + + ns_handler = &handler; + + action(); + + zassert_ok(k_sem_take(&ctx.wait_dad, K_MSEC(WAIT_TIME)), + "Timeout while waiting for DAD NS"); +} + +ZTEST(net_ipv6, test_dad_on_ll_addr_after_iface_up) +{ + verify_dad_on_ll_addr_on_iface_event(test_iface_down_up); +} + +ZTEST(net_ipv6, test_dad_on_ll_addr_after_iface_up_carrier_delayed) +{ + verify_dad_on_ll_addr_on_iface_event(test_iface_down_up_delayed_carrier); +} + +ZTEST(net_ipv6, test_dad_on_ll_addr_after_carrier_toggle) +{ + verify_dad_on_ll_addr_on_iface_event(test_iface_carrier_off_on); +} + +/* Verify that in case of DAD conflict, address is not used on the interface. */ +ZTEST(net_ipv6, test_dad_conflict) +{ + struct in6_addr addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x99, 0x4 } } }; + struct test_dad_context ctx = { + .exp_dad_addr = &addr, + .reply = true + }; + struct test_ns_handler handler = { + .fn = expect_dad_ns, + .user_data = &ctx + }; + struct net_if_addr *ifaddr; + + k_sem_init(&ctx.wait_dad, 0, 1); + + ns_handler = &handler; + + ifaddr = net_if_ipv6_addr_add(TEST_NET_IF, &addr, NET_ADDR_AUTOCONF, 0xffff); + zassert_not_null(ifaddr, "Address cannot be added"); + + zassert_ok(k_sem_take(&ctx.wait_dad, K_MSEC(WAIT_TIME)), + "Timeout while waiting for DAD NS"); + + /* Small delay to let the stack process NA response. */ + k_sleep(K_MSEC(100)); + + ifaddr = net_if_ipv6_addr_lookup_by_iface(TEST_NET_IF, &addr); + zassert_is_null(ifaddr, "Address should not be present on the interface"); +} + #define NET_UDP_HDR(pkt) ((struct net_udp_hdr *)(net_udp_get_hdr(pkt, NULL))) static struct net_pkt *setup_ipv6_udp(struct net_if *iface, @@ -1632,6 +2006,122 @@ ZTEST(net_ipv6, test_dst_is_other_iface_mcast_recv) net_context_put(ctx); } +/* Verify that after interface state change it's possible to transmit mcast + * packets to theoretically joined groups. + */ +static void verify_iface_mcast_send_on_iface_event(void (*action)(void)) +{ + enum net_verdict verdict; + struct net_context *ctx; + struct in6_addr solicited_node_mcast; + + action(); + + /* All nodes */ + net_ctx_create(&ctx); + net_ctx_bind_mcast(ctx, &all_nodes_mcast); + net_ctx_listen(ctx); + net_ctx_recv(ctx); + + verdict = send_msg(&my_addr, &all_nodes_mcast); + zassert_equal(verdict, NET_OK, + "All nodes multicast packet was dropped (%d)", + verdict); + + net_context_put(ctx); + + /* Solicited node */ + net_ipv6_addr_create_solicited_node(&my_addr, &solicited_node_mcast); + + net_ctx_create(&ctx); + net_ctx_bind_mcast(ctx, &solicited_node_mcast); + net_ctx_listen(ctx); + net_ctx_recv(ctx); + + verdict = send_msg(&my_addr, &solicited_node_mcast); + zassert_equal(verdict, NET_OK, + "Solicited node multicast packet was dropped (%d)", + verdict); + + net_context_put(ctx); +} + +ZTEST(net_ipv6, test_iface_mcast_send_after_iface_up) +{ + verify_iface_mcast_send_on_iface_event(test_iface_down_up); +} + +ZTEST(net_ipv6, test_iface_mcast_send_after_iface_up_carrier_delayed) +{ + verify_iface_mcast_send_on_iface_event(test_iface_down_up_delayed_carrier); +} + +ZTEST(net_ipv6, test_iface_mcast_send_after_carrier_toggle) +{ + verify_iface_mcast_send_on_iface_event(test_iface_carrier_off_on); +} + +/* Verify that after interface state change it's possible to receive mcast + * packets on theoretically joined groups. + */ +static void verify_iface_mcast_recv_on_iface_event(void (*action)(void)) +{ + enum net_verdict verdict; + struct net_context *ctx; + struct in6_addr solicited_node_mcast; + + action(); + + k_sem_reset(&wait_data); + + /* All nodes */ + net_ctx_create(&ctx); + net_ctx_bind_mcast(ctx, &all_nodes_mcast); + net_ctx_listen(ctx); + net_ctx_recv(ctx); + + verdict = recv_msg(&peer_addr, &all_nodes_mcast); + zassert_equal(verdict, NET_OK, + "All nodes multicast packet was dropped (%d)", + verdict); + zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), + "Timeout while waiting for mcast packet"); + + net_context_put(ctx); + + /* Solicited node */ + net_ipv6_addr_create_solicited_node(&my_addr, &solicited_node_mcast); + + net_ctx_create(&ctx); + net_ctx_bind_mcast(ctx, &solicited_node_mcast); + net_ctx_listen(ctx); + net_ctx_recv(ctx); + + verdict = recv_msg(&peer_addr, &solicited_node_mcast); + zassert_equal(verdict, NET_OK, + "Solicited node multicast packet was dropped (%d)", + verdict); + zassert_ok(k_sem_take(&wait_data, K_MSEC(WAIT_TIME)), + "Timeout while waiting for mcast packet"); + + net_context_put(ctx); +} + +ZTEST(net_ipv6, test_iface_mcast_recv_after_iface_up) +{ + verify_iface_mcast_recv_on_iface_event(test_iface_down_up); +} + +ZTEST(net_ipv6, test_iface_mcast_recv_after_iface_up_carrier_delayed) +{ + verify_iface_mcast_recv_on_iface_event(test_iface_down_up_delayed_carrier); +} + +ZTEST(net_ipv6, test_iface_mcast_recv_after_carrier_toggle) +{ + verify_iface_mcast_recv_on_iface_event(test_iface_carrier_off_on); +} + ZTEST(net_ipv6, test_no_nd_flag) { bool ret; @@ -1891,4 +2381,4 @@ ZTEST(net_ipv6, test_z_privacy_extension_03_get_addr) } } -ZTEST_SUITE(net_ipv6, NULL, ipv6_setup, NULL, NULL, ipv6_teardown); +ZTEST_SUITE(net_ipv6, NULL, ipv6_setup, ipv6_before, NULL, ipv6_teardown); From 0ea8ed16ba12e68934ce68d9ea6f52b95d96bfd5 Mon Sep 17 00:00:00 2001 From: Chauncy Liu Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0986/1389] include: net: fix compiler warning on unused variable & unsupported type Use ARG_UNUSED on unused variable Cast variables to correct type to avoid compilation warnings. Signed-off-by: Chauncy Liu --- include/zephyr/net/buf.h | 2 +- include/zephyr/net/net_context.h | 10 +++++----- include/zephyr/net/net_ip.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/zephyr/net/buf.h b/include/zephyr/net/buf.h index 3af2782a442e76..c50e5e592451b1 100644 --- a/include/zephyr/net/buf.h +++ b/include/zephyr/net/buf.h @@ -963,7 +963,7 @@ struct net_buf_simple_state { static inline void net_buf_simple_save(struct net_buf_simple *buf, struct net_buf_simple_state *state) { - state->offset = net_buf_simple_headroom(buf); + state->offset = (uint16_t)net_buf_simple_headroom(buf); state->len = buf->len; } diff --git a/include/zephyr/net/net_context.h b/include/zephyr/net/net_context.h index 7c0de1eccd662e..34dffdfe73729b 100644 --- a/include/zephyr/net/net_context.h +++ b/include/zephyr/net/net_context.h @@ -442,7 +442,7 @@ static inline void net_context_set_accepting(struct net_context *context, if (accepting) { context->flags |= NET_CONTEXT_ACCEPTING_SOCK; } else { - context->flags &= ~NET_CONTEXT_ACCEPTING_SOCK; + context->flags &= (uint16_t)~NET_CONTEXT_ACCEPTING_SOCK; } } @@ -474,7 +474,7 @@ static inline void net_context_set_closing(struct net_context *context, if (closing) { context->flags |= NET_CONTEXT_CLOSING_SOCK; } else { - context->flags &= ~NET_CONTEXT_CLOSING_SOCK; + context->flags &= (uint16_t)~NET_CONTEXT_CLOSING_SOCK; } } @@ -554,7 +554,7 @@ static inline void net_context_set_family(struct net_context *context, if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6 || family == AF_PACKET || family == AF_CAN) { /* Family is in BIT(4), BIT(5) and BIT(6) */ - flag = family << 3; + flag = (uint8_t)(family << 3); } context->flags |= flag; @@ -596,7 +596,7 @@ static inline void net_context_set_type(struct net_context *context, if (type == SOCK_DGRAM || type == SOCK_STREAM || type == SOCK_RAW) { /* Type is in BIT(6) and BIT(7)*/ - flag = type << 6; + flag = (uint16_t)(type << 6); } context->flags |= flag; @@ -714,7 +714,7 @@ static inline void net_context_set_iface(struct net_context *context, { NET_ASSERT(iface); - context->iface = net_if_get_by_iface(iface); + context->iface = (uint8_t)net_if_get_by_iface(iface); } /** diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index cf5bc56f1da432..4c9acb85ac76e7 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -687,7 +687,7 @@ static inline bool net_ipv6_is_prefix(const uint8_t *addr1, } /* Create a mask that has remaining most significant bits set */ - mask = ((0xff << (8 - remain)) ^ 0xff) << remain; + mask = (uint8_t)((0xff << (8 - remain)) ^ 0xff) << remain; return (addr1[bytes] & mask) == (addr2[bytes] & mask); } From 019907d0257837f24c72efd156e9a56b2d77347a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0987/1389] Bluetooth: Mesh: Change log lvl for element_model_recv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes the log level from ERR to DBG for element_model_recv for the following cases: - Element does not have the appkey for incoming message. - Element does not have destination address for incoming meesage. When the received message is for a group address, element_model_recv is called for all elements on the device. One or more elements may contain a model that is subscribing to this address. If more than one element contains the same model. but they do not all share the same application key as the incoming message is encrypted with, or they do not all subscribe to the same group address, then the log will show error message for these elements, which is misleading. Signed-off-by: Anders Storrø --- subsys/bluetooth/mesh/access.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 558836504d67bd..da04b15db73b22 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -1487,12 +1487,13 @@ static int element_model_recv(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple } if (!bt_mesh_model_has_key(model, ctx->app_idx)) { - LOG_ERR("Wrong key"); + LOG_DBG("Model at 0x%04x is not bound to app idx %d", elem->rt->addr, ctx->app_idx); return ACCESS_STATUS_WRONG_KEY; } if (!model_has_dst(model, ctx->recv_dst, ctx->uuid)) { - LOG_ERR("Invalid address 0x%02x", ctx->recv_dst); + LOG_DBG("Dst addr 0x%02x is invalid for model at 0x%04x", ctx->recv_dst, + elem->rt->addr); return ACCESS_STATUS_INVALID_ADDRESS; } From b1f903951c33ad0ef04043542f783d6ab8a1d4be Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0988/1389] modem: backend: Add statistics module Add statistics module which tracks the usage of modem backend transmit/receive buffers if implemented by a backend. A modem backend may register itself to the modem backend stat module, and advertise its transmit and receive buffer sizes and momentary usage (length). The modem backend module tracks the maximum usage, which can be output to the shell using the "modem_stats buffer" shell command. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/stats.h | 50 +++++++++++ subsys/modem/CMakeLists.txt | 1 + subsys/modem/Kconfig | 13 +++ subsys/modem/modem_stats.c | 166 +++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 include/zephyr/modem/stats.h create mode 100644 subsys/modem/modem_stats.c diff --git a/include/zephyr/modem/stats.h b/include/zephyr/modem/stats.h new file mode 100644 index 00000000000000..23fb3eac50bc84 --- /dev/null +++ b/include/zephyr/modem/stats.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifndef ZEPHYR_MODEM_STATS_ +#define ZEPHYR_MODEM_STATS_ + +/** + * @cond INTERNAL_HIDDEN + */ + +/** Modem statistics buffer structure */ +struct modem_stats_buffer { + sys_snode_t node; + char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE]; + uint32_t max_used; + uint32_t size; +}; + +/** + * @endcond + */ + +/** + * @brief Initialize modem statistics buffer + * + * @param buffer Modem statistics buffer instance + * @param name Name of buffer instance + * @param size Size of buffer + */ +void modem_stats_buffer_init(struct modem_stats_buffer *buffer, + const char *name, uint32_t size); + +/** + * @brief Advertise modem statistics buffer size + * + * @param buffer Modem statistics buffer instance + * @param length Length of buffer + * + * @note Invoke when buffer size changes + * @note Safe to invoke from ISR + */ +void modem_stats_buffer_advertise_length(struct modem_stats_buffer *buffer, uint32_t length); + +#endif /* ZEPHYR_MODEM_STATS_ */ diff --git a/subsys/modem/CMakeLists.txt b/subsys/modem/CMakeLists.txt index a19916a0dd3f26..b366b73ce21ff6 100644 --- a/subsys/modem/CMakeLists.txt +++ b/subsys/modem/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_MODEM_CHAT modem_chat.c) zephyr_library_sources_ifdef(CONFIG_MODEM_CMUX modem_cmux.c) zephyr_library_sources_ifdef(CONFIG_MODEM_PIPE modem_pipe.c) zephyr_library_sources_ifdef(CONFIG_MODEM_PPP modem_ppp.c) +zephyr_library_sources_ifdef(CONFIG_MODEM_STATS modem_stats.c) zephyr_library_sources_ifdef(CONFIG_MODEM_UBX modem_ubx.c) add_subdirectory(backends) diff --git a/subsys/modem/Kconfig b/subsys/modem/Kconfig index a71542a706a348..7dfdcbfe635ca5 100644 --- a/subsys/modem/Kconfig +++ b/subsys/modem/Kconfig @@ -59,6 +59,19 @@ config MODEM_PPP_NET_BUF_FRAG_SIZE endif +config MODEM_STATS + bool "Modem statistics" + depends on SHELL + help + Enables modem statistics shell commands which track the usage of + buffers across the modem modules. The statistics are useful for + scaling buffer sizes, as these are application specific. + +config MODEM_STATS_BUFFER_NAME_SIZE + int "Maximum string size of modem stats buffer name" + default 32 + range 8 64 + config MODEM_UBX bool "Modem U-BLOX module" select RING_BUFFER diff --git a/subsys/modem/modem_stats.c b/subsys/modem/modem_stats.c new file mode 100644 index 00000000000000..2ab90d3be6ee46 --- /dev/null +++ b/subsys/modem/modem_stats.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef _POSIX_VERSION +#undef _POSIX_VERSION +#endif +#define _POSIX_VERSION 200809L + +#include +#include + +#include +LOG_MODULE_REGISTER(modem_stats); + +static struct k_spinlock stats_buffer_lock; +static sys_slist_t stats_buffer_list; + +static struct modem_stats_buffer *stats_buffer_from_node(sys_snode_t *node) +{ + return (struct modem_stats_buffer *)node; +} + +static void stats_buffer_list_append(struct modem_stats_buffer *buffer) +{ + K_SPINLOCK(&stats_buffer_lock) { + sys_slist_append(&stats_buffer_list, &buffer->node); + } +} + +static struct modem_stats_buffer *stats_buffer_list_first(void) +{ + struct modem_stats_buffer *first; + + K_SPINLOCK(&stats_buffer_lock) { + first = stats_buffer_from_node(sys_slist_peek_head(&stats_buffer_list)); + } + + return first; +} + +static struct modem_stats_buffer *stats_buffer_list_next(struct modem_stats_buffer *buffer) +{ + struct modem_stats_buffer *next; + + K_SPINLOCK(&stats_buffer_lock) { + next = stats_buffer_from_node(sys_slist_peek_next(&buffer->node)); + } + + return next; +} + +static uint8_t percent_used(uint32_t max_used, uint32_t cap) +{ + uint64_t percent; + + if (max_used == 0) { + return 0; + } + + if (max_used == cap) { + return 100; + } + + percent = 100; + percent *= max_used; + percent /= cap; + + return (uint8_t)percent; +} + +static void stats_buffer_get_and_clear_max_used(struct modem_stats_buffer *buffer, + uint32_t *max_used) +{ + K_SPINLOCK(&stats_buffer_lock) { + *max_used = buffer->max_used; + buffer->max_used = 0; + } +} + +static bool stats_buffer_length_is_valid(const struct modem_stats_buffer *buffer, uint32_t length) +{ + return length <= buffer->size; +} + +static void stats_buffer_log_invalid_length(const struct modem_stats_buffer *buffer, + uint32_t length) +{ + LOG_ERR("%s: length (%u) exceeds size (%u)", buffer->name, length, buffer->size); +} + +static void stats_buffer_update_max_used(struct modem_stats_buffer *buffer, uint32_t length) +{ + K_SPINLOCK(&stats_buffer_lock) { + if (buffer->max_used < length) { + buffer->max_used = length; + } + } +} + +static void stats_buffer_print_to_shell(const struct shell *sh, + const struct modem_stats_buffer *buffer, + uint32_t max_used) +{ + shell_print(sh, "%s: used at most: %u of %u (%u%%)", buffer->name, max_used, + buffer->size, percent_used(max_used, buffer->size)); +} + +static int stats_buffer_shell_cmd_handler(const struct shell *sh, size_t argc, char **argv) +{ + struct modem_stats_buffer *buffer; + uint32_t max_used; + + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + buffer = stats_buffer_list_first(); + + if (buffer == NULL) { + shell_print(sh, "no buffers exist"); + return 0; + } + + while (buffer != NULL) { + stats_buffer_get_and_clear_max_used(buffer, &max_used); + stats_buffer_print_to_shell(sh, buffer, max_used); + buffer = stats_buffer_list_next(buffer); + } + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE( + sub_stats_cmds, + SHELL_CMD(buffer, NULL, "Get buffer statistics", stats_buffer_shell_cmd_handler), + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_REGISTER(modem_stats, &sub_stats_cmds, "Modem statistics commands", NULL); + +static void stats_buffer_set_name(struct modem_stats_buffer *buffer, const char *name) +{ + buffer->name[sizeof(buffer->name) - 1] = '\0'; + strncpy(buffer->name, name, sizeof(buffer->name) - 1); +} + +void modem_stats_buffer_init(struct modem_stats_buffer *buffer, + const char *name, uint32_t size) +{ + stats_buffer_set_name(buffer, name); + buffer->max_used = 0; + buffer->size = size; + stats_buffer_list_append(buffer); +} + +void modem_stats_buffer_advertise_length(struct modem_stats_buffer *buffer, uint32_t length) +{ + if (!stats_buffer_length_is_valid(buffer, length)) { + stats_buffer_log_invalid_length(buffer, length); + return; + } + + stats_buffer_update_max_used(buffer, length); +} From 6a92c2901504cb7b483647dbd526818ca3f089de Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0989/1389] modem: backend: uart: isr: Implement modem backend stat Implement modem backend statistics into isr uart modem backend. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/backend/uart.h | 7 ++ .../modem/backends/modem_backend_uart_isr.c | 74 ++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/include/zephyr/modem/backend/uart.h b/include/zephyr/modem/backend/uart.h index 0280494e3502e6..f68f411c6e222e 100644 --- a/include/zephyr/modem/backend/uart.h +++ b/include/zephyr/modem/backend/uart.h @@ -12,6 +12,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_BACKEND_UART_ #define ZEPHYR_MODEM_BACKEND_UART_ @@ -24,6 +25,7 @@ struct modem_backend_uart_isr { struct ring_buf receive_rdb[2]; struct ring_buf transmit_rb; atomic_t transmit_buf_len; + atomic_t receive_buf_len; uint8_t receive_rdb_used; uint32_t transmit_buf_put_limit; }; @@ -45,6 +47,11 @@ struct modem_backend_uart { struct k_work_delayable receive_ready_work; struct k_work transmit_idle_work; +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif + union { struct modem_backend_uart_isr isr; struct modem_backend_uart_async async; diff --git a/subsys/modem/backends/modem_backend_uart_isr.c b/subsys/modem/backends/modem_backend_uart_isr.c index c67c8f7644e409..ea8d99d6032681 100644 --- a/subsys/modem/backends/modem_backend_uart_isr.c +++ b/subsys/modem/backends/modem_backend_uart_isr.c @@ -118,9 +118,51 @@ static int modem_backend_uart_isr_open(void *data) return 0; } +static uint32_t get_transmit_buf_length(struct modem_backend_uart *backend) +{ + return atomic_get(&backend->isr.transmit_buf_len); +} + +#if CONFIG_MODEM_STATS +static uint32_t get_receive_buf_length(struct modem_backend_uart *backend) +{ + return ring_buf_size_get(&backend->isr.receive_rdb[0]) + + ring_buf_size_get(&backend->isr.receive_rdb[1]); +} + +static uint32_t get_receive_buf_size(struct modem_backend_uart *backend) +{ + return ring_buf_capacity_get(&backend->isr.receive_rdb[0]) + + ring_buf_capacity_get(&backend->isr.receive_rdb[1]); +} + +static uint32_t get_transmit_buf_size(struct modem_backend_uart *backend) +{ + return ring_buf_capacity_get(&backend->isr.transmit_rb); +} + +static void advertise_transmit_buf_stats(struct modem_backend_uart *backend) +{ + uint32_t length; + + length = get_transmit_buf_length(backend); + modem_stats_buffer_advertise_length(&backend->transmit_buf_stats, length); +} + +static void advertise_receive_buf_stats(struct modem_backend_uart *backend) +{ + uint32_t length; + + uart_irq_rx_disable(backend->uart); + length = get_receive_buf_length(backend); + uart_irq_rx_enable(backend->uart); + modem_stats_buffer_advertise_length(&backend->receive_buf_stats, length); +} +#endif + static bool modem_backend_uart_isr_transmit_buf_above_limit(struct modem_backend_uart *backend) { - return backend->isr.transmit_buf_put_limit < atomic_get(&backend->isr.transmit_buf_len); + return backend->isr.transmit_buf_put_limit < get_transmit_buf_length(backend); } static int modem_backend_uart_isr_transmit(void *data, const uint8_t *buf, size_t size) @@ -138,6 +180,11 @@ static int modem_backend_uart_isr_transmit(void *data, const uint8_t *buf, size_ /* Update transmit buf capacity tracker */ atomic_add(&backend->isr.transmit_buf_len, written); + +#if CONFIG_MODEM_STATS + advertise_transmit_buf_stats(backend); +#endif + return written; } @@ -148,6 +195,10 @@ static int modem_backend_uart_isr_receive(void *data, uint8_t *buf, size_t size) uint32_t read_bytes; uint8_t receive_rdb_unused; +#if CONFIG_MODEM_STATS + advertise_receive_buf_stats(backend); +#endif + read_bytes = 0; receive_rdb_unused = (backend->isr.receive_rdb_used == 1) ? 0 : 1; @@ -189,6 +240,23 @@ struct modem_pipe_api modem_backend_uart_isr_api = { .close = modem_backend_uart_isr_close, }; +#if CONFIG_MODEM_STATS +static void init_stats(struct modem_backend_uart *backend) +{ + char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE]; + uint32_t receive_buf_size; + uint32_t transmit_buf_size; + + receive_buf_size = get_receive_buf_size(backend); + transmit_buf_size = get_transmit_buf_size(backend); + + snprintk(name, sizeof(name), "%s_%s", backend->uart->name, "rx"); + modem_stats_buffer_init(&backend->receive_buf_stats, name, receive_buf_size); + snprintk(name, sizeof(name), "%s_%s", backend->uart->name, "tx"); + modem_stats_buffer_init(&backend->transmit_buf_stats, name, transmit_buf_size); +} +#endif + void modem_backend_uart_isr_init(struct modem_backend_uart *backend, const struct modem_backend_uart_config *config) { @@ -215,4 +283,8 @@ void modem_backend_uart_isr_init(struct modem_backend_uart *backend, backend); modem_pipe_init(&backend->pipe, backend, &modem_backend_uart_isr_api); + +#if CONFIG_MODEM_STATS + init_stats(backend); +#endif } From 1f2c1301111872a6edcc48f8cc169e357d9e7cc2 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0990/1389] modem: backend: uart: async: Implement modem backend stat Implement modem backend statistics in async uart modem backend. Signed-off-by: Bjarki Arge Andreasen --- .../modem/backends/modem_backend_uart_async.c | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/subsys/modem/backends/modem_backend_uart_async.c b/subsys/modem/backends/modem_backend_uart_async.c index c7d4b6297e6779..184f83a8e461d1 100644 --- a/subsys/modem/backends/modem_backend_uart_async.c +++ b/subsys/modem/backends/modem_backend_uart_async.c @@ -42,6 +42,11 @@ static bool modem_backend_uart_async_is_open(struct modem_backend_uart *backend) MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT); } +static uint32_t get_receive_buf_length(struct modem_backend_uart *backend) +{ + return ring_buf_size_get(&backend->async.receive_rb); +} + static void modem_backend_uart_async_event_handler(const struct device *dev, struct uart_event *evt, void *user_data) { @@ -54,7 +59,6 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, atomic_clear_bit(&backend->async.state, MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT); k_work_submit(&backend->transmit_idle_work); - break; case UART_TX_ABORTED: @@ -112,7 +116,7 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, evt->data.rx.len); if (received < evt->data.rx.len) { - const unsigned int buf_size = ring_buf_size_get(&backend->async.receive_rb); + const unsigned int buf_size = get_receive_buf_length(backend); ring_buf_reset(&backend->async.receive_rb); k_spin_unlock(&backend->async.receive_rb_lock, key); @@ -171,6 +175,31 @@ static int modem_backend_uart_async_open(void *data) return 0; } +#if CONFIG_MODEM_STATS +static uint32_t get_receive_buf_size(struct modem_backend_uart *backend) +{ + return ring_buf_capacity_get(&backend->async.receive_rb); +} + +static void advertise_transmit_buf_stats(struct modem_backend_uart *backend, uint32_t length) +{ + modem_stats_buffer_advertise_length(&backend->transmit_buf_stats, length); +} + +static void advertise_receive_buf_stats(struct modem_backend_uart *backend) +{ + uint32_t length; + + length = get_receive_buf_length(backend); + modem_stats_buffer_advertise_length(&backend->receive_buf_stats, length); +} +#endif + +static uint32_t get_transmit_buf_size(struct modem_backend_uart *backend) +{ + return backend->async.transmit_buf_size; +} + static int modem_backend_uart_async_transmit(void *data, const uint8_t *buf, size_t size) { struct modem_backend_uart *backend = (struct modem_backend_uart *)data; @@ -185,7 +214,7 @@ static int modem_backend_uart_async_transmit(void *data, const uint8_t *buf, siz } /* Determine amount of bytes to transmit */ - bytes_to_transmit = MIN(size, backend->async.transmit_buf_size); + bytes_to_transmit = MIN(size, get_transmit_buf_size(backend)); /* Copy buf to transmit buffer which is passed to UART */ memcpy(backend->async.transmit_buf, buf, bytes_to_transmit); @@ -193,6 +222,10 @@ static int modem_backend_uart_async_transmit(void *data, const uint8_t *buf, siz ret = uart_tx(backend->uart, backend->async.transmit_buf, bytes_to_transmit, CONFIG_MODEM_BACKEND_UART_ASYNC_TRANSMIT_TIMEOUT_MS * 1000L); +#if CONFIG_MODEM_STATS + advertise_transmit_buf_stats(backend, bytes_to_transmit); +#endif + if (ret != 0) { LOG_ERR("Failed to %s %u bytes. (%d)", "start async transmit for", bytes_to_transmit, ret); @@ -210,6 +243,11 @@ static int modem_backend_uart_async_receive(void *data, uint8_t *buf, size_t siz bool empty; key = k_spin_lock(&backend->async.receive_rb_lock); + +#if CONFIG_MODEM_STATS + advertise_receive_buf_stats(backend); +#endif + received = ring_buf_get(&backend->async.receive_rb, buf, size); empty = ring_buf_is_empty(&backend->async.receive_rb); k_spin_unlock(&backend->async.receive_rb_lock, key); @@ -255,6 +293,23 @@ static void modem_backend_uart_async_notify_closed(struct k_work *item) modem_pipe_notify_closed(&backend->pipe); } +#if CONFIG_MODEM_STATS +static void init_stats(struct modem_backend_uart *backend) +{ + char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE]; + uint32_t receive_buf_size; + uint32_t transmit_buf_size; + + receive_buf_size = get_receive_buf_size(backend); + transmit_buf_size = get_transmit_buf_size(backend); + + snprintk(name, sizeof(name), "%s_%s", backend->uart->name, "rx"); + modem_stats_buffer_init(&backend->receive_buf_stats, name, receive_buf_size); + snprintk(name, sizeof(name), "%s_%s", backend->uart->name, "tx"); + modem_stats_buffer_init(&backend->transmit_buf_stats, name, transmit_buf_size); +} +#endif + void modem_backend_uart_async_init(struct modem_backend_uart *backend, const struct modem_backend_uart_config *config) { @@ -273,4 +328,8 @@ void modem_backend_uart_async_init(struct modem_backend_uart *backend, backend->async.transmit_buf_size = config->transmit_buf_size; k_work_init(&backend->async.rx_disabled_work, modem_backend_uart_async_notify_closed); modem_pipe_init(&backend->pipe, backend, &modem_backend_uart_async_api); + +#if CONFIG_MODEM_STATS + init_stats(backend); +#endif } From f9d0e46f73554d763cf8e8fe5696eb5fa283a6c4 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0991/1389] modem: cmux: Implement modem backend statistics Implement modem backend statistics into modem CMUX DLCI channel receive buffer and CMUX transmit and receive buffers. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/cmux.h | 12 +++++ subsys/modem/modem_cmux.c | 104 ++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/include/zephyr/modem/cmux.h b/include/zephyr/modem/cmux.h index 57ee6a8505b8af..2e6990f5aa06d6 100644 --- a/include/zephyr/modem/cmux.h +++ b/include/zephyr/modem/cmux.h @@ -25,6 +25,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_CMUX_ #define ZEPHYR_MODEM_CMUX_ @@ -102,6 +103,11 @@ struct modem_cmux_dlci { /* State */ enum modem_cmux_dlci_state state; + + /* Statistics */ +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; +#endif }; struct modem_cmux_frame { @@ -160,6 +166,12 @@ struct modem_cmux { /* Synchronize actions */ struct k_event event; + + /* Statistics */ +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif }; /** diff --git a/subsys/modem/modem_cmux.c b/subsys/modem/modem_cmux.c index 3fcca3d6068afb..f4e2280dccbebf 100644 --- a/subsys/modem/modem_cmux.c +++ b/subsys/modem/modem_cmux.c @@ -144,6 +144,54 @@ static void modem_cmux_log_received_frame(const struct modem_cmux_frame *frame) modem_cmux_log_frame(frame, "rcvd", frame->data_len); } +#if CONFIG_MODEM_STATS +static uint32_t modem_cmux_get_receive_buf_length(struct modem_cmux *cmux) +{ + return cmux->receive_buf_len; +} + +static uint32_t modem_cmux_get_receive_buf_size(struct modem_cmux *cmux) +{ + return cmux->receive_buf_size; +} + +static uint32_t modem_cmux_get_transmit_buf_length(struct modem_cmux *cmux) +{ + return ring_buf_size_get(&cmux->transmit_rb); +} + +static uint32_t modem_cmux_get_transmit_buf_size(struct modem_cmux *cmux) +{ + return ring_buf_capacity_get(&cmux->transmit_rb); +} + +static void modem_cmux_init_buf_stats(struct modem_cmux *cmux) +{ + uint32_t size; + + size = modem_cmux_get_receive_buf_size(cmux); + modem_stats_buffer_init(&cmux->receive_buf_stats, "cmux_rx", size); + size = modem_cmux_get_transmit_buf_size(cmux); + modem_stats_buffer_init(&cmux->transmit_buf_stats, "cmux_tx", size); +} + +static void modem_cmux_advertise_transmit_buf_stats(struct modem_cmux *cmux) +{ + uint32_t length; + + length = modem_cmux_get_transmit_buf_length(cmux); + modem_stats_buffer_advertise_length(&cmux->transmit_buf_stats, length); +} + +static void modem_cmux_advertise_receive_buf_stats(struct modem_cmux *cmux) +{ + uint32_t length; + + length = modem_cmux_get_receive_buf_length(cmux); + modem_stats_buffer_advertise_length(&cmux->receive_buf_stats, length); +} +#endif + static const char *modem_cmux_command_type_to_str(enum modem_cmux_command_types command_type) { switch (command_type) { @@ -649,6 +697,10 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux) static void modem_cmux_on_frame(struct modem_cmux *cmux) { +#if CONFIG_MODEM_STATS + modem_cmux_advertise_receive_buf_stats(cmux); +#endif + if (cmux->frame.dlci_address == 0) { modem_cmux_on_control_frame(cmux); } else { @@ -658,6 +710,10 @@ static void modem_cmux_on_frame(struct modem_cmux *cmux) static void modem_cmux_drop_frame(struct modem_cmux *cmux) { +#if CONFIG_MODEM_STATS + modem_cmux_advertise_receive_buf_stats(cmux); +#endif + LOG_WRN("Dropped frame"); cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_SOF; @@ -884,6 +940,10 @@ static void modem_cmux_transmit_handler(struct k_work *item) k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); +#if CONFIG_MODEM_STATS + modem_cmux_advertise_transmit_buf_stats(cmux); +#endif + while (true) { transmit_rb_empty = ring_buf_is_empty(&cmux->transmit_rb); @@ -975,6 +1035,36 @@ static void modem_cmux_disconnect_handler(struct k_work *item) k_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT); } +#if CONFIG_MODEM_STATS +static uint32_t modem_cmux_dlci_get_receive_buf_length(struct modem_cmux_dlci *dlci) +{ + return ring_buf_size_get(&dlci->receive_rb); +} + +static uint32_t modem_cmux_dlci_get_receive_buf_size(struct modem_cmux_dlci *dlci) +{ + return ring_buf_capacity_get(&dlci->receive_rb); +} + +static void modem_cmux_dlci_init_buf_stats(struct modem_cmux_dlci *dlci) +{ + uint32_t size; + char name[sizeof("dlci_xxxxx_rx")]; + + size = modem_cmux_dlci_get_receive_buf_size(dlci); + snprintk(name, sizeof(name), "dlci_%u_rx", dlci->dlci_address); + modem_stats_buffer_init(&dlci->receive_buf_stats, name, size); +} + +static void modem_cmux_dlci_advertise_receive_buf_stat(struct modem_cmux_dlci *dlci) +{ + uint32_t length; + + length = modem_cmux_dlci_get_receive_buf_length(dlci); + modem_stats_buffer_advertise_length(&dlci->receive_buf_stats, length); +} +#endif + static int modem_cmux_dlci_pipe_api_open(void *data) { struct modem_cmux_dlci *dlci = (struct modem_cmux_dlci *)data; @@ -1010,6 +1100,11 @@ static int modem_cmux_dlci_pipe_api_receive(void *data, uint8_t *buf, size_t siz uint32_t ret; k_mutex_lock(&dlci->receive_rb_lock, K_FOREVER); + +#if CONFIG_MODEM_STATS + modem_cmux_dlci_advertise_receive_buf_stat(dlci); +#endif + ret = ring_buf_get(&dlci->receive_rb, buf, size); k_mutex_unlock(&dlci->receive_rb_lock); return ret; @@ -1126,6 +1221,10 @@ void modem_cmux_init(struct modem_cmux *cmux, const struct modem_cmux_config *co k_event_init(&cmux->event); k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); + +#if CONFIG_MODEM_STATS + modem_cmux_init_buf_stats(cmux); +#endif } struct modem_pipe *modem_cmux_dlci_init(struct modem_cmux *cmux, struct modem_cmux_dlci *dlci, @@ -1148,6 +1247,11 @@ struct modem_pipe *modem_cmux_dlci_init(struct modem_cmux *cmux, struct modem_cm k_work_init_delayable(&dlci->close_work, modem_cmux_dlci_close_handler); dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED; sys_slist_append(&dlci->cmux->dlcis, &dlci->node); + +#if CONFIG_MODEM_STATS + modem_cmux_dlci_init_buf_stats(dlci); +#endif + return &dlci->pipe; } From 837bc25eae3fbfd5160eb0a924f2143cb636ccb4 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:19 +0200 Subject: [PATCH 0992/1389] modem: ppp: implement modem_statistics Implement modem buffer statistics for ppp module. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/ppp.h | 6 ++++ subsys/modem/modem_ppp.c | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/include/zephyr/modem/ppp.h b/include/zephyr/modem/ppp.h index c0eca885fcdc34..799aac60b0b136 100644 --- a/include/zephyr/modem/ppp.h +++ b/include/zephyr/modem/ppp.h @@ -12,6 +12,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_PPP_ #define ZEPHYR_MODEM_PPP_ @@ -113,6 +114,11 @@ struct modem_ppp { #if defined(CONFIG_NET_STATISTICS_PPP) struct net_stats_ppp stats; #endif + +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif }; /** diff --git a/subsys/modem/modem_ppp.c b/subsys/modem/modem_ppp.c index 91085317d99f22..17e3081f55ab6a 100644 --- a/subsys/modem/modem_ppp.c +++ b/subsys/modem/modem_ppp.c @@ -313,6 +313,26 @@ static void modem_ppp_process_received_byte(struct modem_ppp *ppp, uint8_t byte) } } +#if CONFIG_MODEM_STATS +static uint32_t get_transmit_buf_length(struct modem_ppp *ppp) +{ + return ring_buf_size_get(&ppp->transmit_rb); +} + +static void advertise_transmit_buf_stats(struct modem_ppp *ppp) +{ + uint32_t length; + + length = get_transmit_buf_length(ppp); + modem_stats_buffer_advertise_length(&ppp->transmit_buf_stats, length); +} + +static void advertise_receive_buf_stats(struct modem_ppp *ppp, uint32_t length) +{ + modem_stats_buffer_advertise_length(&ppp->receive_buf_stats, length); +} +#endif + static void modem_ppp_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event, void *user_data) { @@ -365,6 +385,10 @@ static void modem_ppp_send_handler(struct k_work *item) } } +#if CONFIG_MODEM_STATS + advertise_transmit_buf_stats(ppp); +#endif + while (!ring_buf_is_empty(&ppp->transmit_rb)) { reserved_size = ring_buf_get_claim(&ppp->transmit_rb, &reserved, UINT32_MAX); @@ -392,6 +416,10 @@ static void modem_ppp_process_handler(struct k_work *item) return; } +#if CONFIG_MODEM_STATS + advertise_receive_buf_stats(ppp, ret); +#endif + for (int i = 0; i < ret; i++) { modem_ppp_process_received_byte(ppp, ppp->receive_buf[i]); } @@ -460,6 +488,32 @@ static struct net_stats_ppp *modem_ppp_ppp_get_stats(const struct device *dev) } #endif +#if CONFIG_MODEM_STATS +static uint32_t get_buf_size(struct modem_ppp *ppp) +{ + return ppp->buf_size; +} + +static void init_buf_stats(struct modem_ppp *ppp) +{ + char iface_name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE - sizeof("_xx")]; + char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE]; + int ret; + uint32_t size; + + ret = net_if_get_name(ppp->iface, iface_name, sizeof(iface_name)); + if (ret < 0) { + snprintk(iface_name, sizeof(iface_name), "ppp"); + } + + size = get_buf_size(ppp); + snprintk(name, sizeof(name), "%s_rx", iface_name); + modem_stats_buffer_init(&ppp->receive_buf_stats, name, size); + snprintk(name, sizeof(name), "%s_tx", iface_name); + modem_stats_buffer_init(&ppp->transmit_buf_stats, name, size); +} +#endif + const struct ppp_api modem_ppp_ppp_api = { .iface_api.init = modem_ppp_ppp_api_init, .start = modem_ppp_ppp_api_start, @@ -535,5 +589,8 @@ int modem_ppp_init_internal(const struct device *dev) k_work_init(&ppp->process_work, modem_ppp_process_handler); k_fifo_init(&ppp->tx_pkt_fifo); +#if CONFIG_MODEM_STATS + init_buf_stats(ppp); +#endif return 0; } From 3ec0690d21cd09fb3ba0e44b0be7b8c5853630ad Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0993/1389] modem: chat: implement buffer stats implement buffer statistics for modem_chat module. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/chat.h | 7 ++++ subsys/modem/modem_chat.c | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index afb57c912fc2f0..a30a7191ba967d 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -10,6 +10,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_CHAT_ #define ZEPHYR_MODEM_CHAT_ @@ -269,6 +270,12 @@ struct modem_chat { /* Process received data */ struct k_work receive_work; + + /* Statistics */ +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer work_buf_stats; +#endif }; /** diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index 51d1cf2e9b60d1..b13334d145ba6a 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -356,8 +356,27 @@ static void modem_chat_script_send_timeout_handler(struct k_work *item) modem_chat_script_next(chat, false); } +#if CONFIG_MODEM_STATS +static uint32_t get_receive_buf_length(struct modem_chat *chat) +{ + return chat->receive_buf_len; +} + +static void advertise_receive_buf_stats(struct modem_chat *chat) +{ + uint32_t length; + + length = get_receive_buf_length(chat); + modem_stats_buffer_advertise_length(&chat->receive_buf_stats, length); +} +#endif + static void modem_chat_parse_reset(struct modem_chat *chat) { +#if CONFIG_MODEM_STATS + advertise_receive_buf_stats(chat); +#endif + /* Reset parameters used for parsing */ chat->receive_buf_len = 0; chat->delimiter_match_len = 0; @@ -685,6 +704,21 @@ static void modem_chat_process_bytes(struct modem_chat *chat) } } +#if CONFIG_MODEM_STATS +static uint32_t get_work_buf_length(struct modem_chat *chat) +{ + return chat->work_buf_len; +} + +static void advertise_work_buf_stats(struct modem_chat *chat) +{ + uint32_t length; + + length = get_work_buf_length(chat); + modem_stats_buffer_advertise_length(&chat->work_buf_stats, length); +} +#endif + static void modem_chat_process_handler(struct k_work *item) { struct modem_chat *chat = CONTAINER_OF(item, struct modem_chat, receive_work); @@ -699,6 +733,10 @@ static void modem_chat_process_handler(struct k_work *item) /* Save received data length */ chat->work_buf_len = (size_t)ret; +#if CONFIG_MODEM_STATS + advertise_work_buf_stats(chat); +#endif + /* Process data */ modem_chat_process_bytes(chat); k_work_submit(&chat->receive_work); @@ -723,6 +761,28 @@ static void modem_chat_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_ev } } +#if CONFIG_MODEM_STATS +static uint32_t get_receive_buf_size(struct modem_chat *chat) +{ + return chat->receive_buf_size; +} + +static uint32_t get_work_buf_size(struct modem_chat *chat) +{ + return sizeof(chat->work_buf); +} + +static void init_buf_stats(struct modem_chat *chat) +{ + uint32_t size; + + size = get_receive_buf_size(chat); + modem_stats_buffer_init(&chat->receive_buf_stats, "chat_rx", size); + size = get_work_buf_size(chat); + modem_stats_buffer_init(&chat->work_buf_stats, "chat_work", size); +} +#endif + int modem_chat_init(struct modem_chat *chat, const struct modem_chat_config *config) { __ASSERT_NO_MSG(chat != NULL); @@ -759,6 +819,10 @@ int modem_chat_init(struct modem_chat *chat, const struct modem_chat_config *con k_work_init_delayable(&chat->script_send_timeout_work, modem_chat_script_send_timeout_handler); +#if CONFIG_MODEM_STATS + init_buf_stats(chat); +#endif + return 0; } From d4e168af38d01774e05032cfb99f0ba666ef373c Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0994/1389] samples: net: cellular modem: Select modem backend statistics select modem backend statistics and enable shell in cellular modem sample. This will help advertise the feature, and can help quickly identify issues with to small buffers. Signed-off-by: Bjarki Arge Andreasen --- samples/net/cellular_modem/prj.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/net/cellular_modem/prj.conf b/samples/net/cellular_modem/prj.conf index 345d49bf463fdc..4656fe52d651bc 100644 --- a/samples/net/cellular_modem/prj.conf +++ b/samples/net/cellular_modem/prj.conf @@ -26,6 +26,10 @@ CONFIG_MODEM=y CONFIG_PM_DEVICE=y CONFIG_MODEM_CELLULAR=y +# Statistics +CONFIG_MODEM_STATS=y +CONFIG_SHELL=y + # Logging CONFIG_LOG=y CONFIG_MODEM_MODULES_LOG_LEVEL_DBG=y From 82f1b985150fcd4efce1241b30d8833b55ff56a3 Mon Sep 17 00:00:00 2001 From: Joel Guittet Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0995/1389] modules: mbedtls: fix pk ecc functions undefined references Fix undefined reference to mbedtls_pk_ecc_xxx functions following update to latest mbedtls version. Signed-off-by: Joel Guittet --- modules/mbedtls/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 01a7ed09c28ea8..30ddce44eb176e 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -139,6 +139,7 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/pkparse.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pkwrite.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pk.c + ${ZEPHYR_CURRENT_MODULE_DIR}/library/pk_ecc.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pk_wrap.c ) From f92f5a104eece2cf500f828cc1a6d525ca3e4cc1 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0996/1389] Bluetooth: Add `BT_LE_ADV_CONN_ONE_TIME` The adv auto resume feature is planned for deprecation. This new define is the new default applications should use. Signed-off-by: Aleksander Wasaznik --- include/zephyr/bluetooth/bluetooth.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index 364514fc343cd4..59689974b87636 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -912,6 +912,12 @@ struct bt_le_per_adv_param { BT_GAP_ADV_FAST_INT_MIN_2, \ BT_GAP_ADV_FAST_INT_MAX_2, NULL) +/** This is the recommended default for connectable advertisers. + */ +#define BT_LE_ADV_CONN_ONE_TIME \ + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, \ + BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL) + /** * @deprecated This macro will be removed in the near future, see * https://github.com/zephyrproject-rtos/zephyr/issues/71686 From 1e3d9da088ac67b0fc0c24ed7d43b44bb70ecdfd Mon Sep 17 00:00:00 2001 From: frei tycho Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0997/1389] arch: x86: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- arch/x86/core/early_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/core/early_serial.c b/arch/x86/core/early_serial.c index 3a0bc7465e1ff1..53fb8af7e3ac12 100644 --- a/arch/x86/core/early_serial.c +++ b/arch/x86/core/early_serial.c @@ -25,8 +25,8 @@ * together. */ static mm_reg_t mmio; -#define IN(reg) (sys_read32(mmio + reg * 4) & 0xff) -#define OUT(reg, val) sys_write32((val) & 0xff, mmio + reg * 4) +#define IN(reg) (sys_read32(mmio + (reg) * 4) & 0xff) +#define OUT(reg, val) sys_write32((val) & 0xff, mmio + (reg) * 4) #elif defined(X86_SOC_EARLY_SERIAL_MMIO8_ADDR) /* Still other devices use a MMIO region containing packed byte * registers From fc98f0ebf059eedd62776334c5c941840589d921 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0998/1389] Bluetooth: Controller: Add BT_CTLR_HCI Kconfig option Add a new option to split off the building of the HCI layer of the controller. This layer is not needed by the controller unit tests, and becomes problematic with the planned change to use devicetree for HCI drivers. Signed-off-by: Johan Hedberg --- subsys/bluetooth/controller/CMakeLists.txt | 4 ++++ subsys/bluetooth/controller/Kconfig | 11 ++++++++++- .../unit_testing/unit_testing/Kconfig.defconfig | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/CMakeLists.txt b/subsys/bluetooth/controller/CMakeLists.txt index 42008750d6db0a..a2fb0d22508b27 100644 --- a/subsys/bluetooth/controller/CMakeLists.txt +++ b/subsys/bluetooth/controller/CMakeLists.txt @@ -21,6 +21,10 @@ zephyr_library_sources( ll_sw/ll_addr.c ll_sw/ull.c ll_sw/lll_common.c + ) + +zephyr_library_sources_ifdef( + CONFIG_BT_CTLR_HCI hci/hci_driver.c hci/hci.c ) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 11dc46dcc838f4..dc7143bc7f52d7 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -124,6 +124,14 @@ config BT_LL_SW_SPLIT endchoice +config BT_CTLR_HCI + bool "Host Controller Interface (HCI)" + default y + help + Enable the Host Controller interface (HCI) in the Controller. + This should almost always be enabled, except in a few special + cases, like for unit testing. + comment "BLE Controller configuration" config BT_CTLR_CRYPTO @@ -137,7 +145,7 @@ config BT_CTLR_CRYPTO config BT_CTLR_HCI_VS_BUILD_INFO string "Zephyr HCI VS Build Info string" default "" - depends on BT_HCI_VS + depends on BT_CTLR_HCI && BT_HCI_VS help User-defined string that will be returned by the Zephyr VS Read Build Information command after the Zephyr version and build time. When @@ -988,6 +996,7 @@ config BT_CTLR_SMI_TX_SETTING config BT_CTLR_HCI_CODEC_AND_DELAY_INFO bool "Codecs and controller delay information commands" + depends on BT_CTLR_HCI help Enable HCI commands to read information about supported codecs, codec capabilities, and controller delay. diff --git a/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig b/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig index 939f1c97e71041..38c6d4b3019885 100644 --- a/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig +++ b/subsys/testsuite/boards/unit_testing/unit_testing/Kconfig.defconfig @@ -6,3 +6,8 @@ choice BT_HCI_BUS_TYPE default BT_NO_DRIVER endchoice + +# Controller HCI support requires e.g. devicetree, which isn't available +# for unit tests. +config BT_CTLR_HCI + default n From 691d06c4f4d212d789d96df394a52597f67fe900 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 0999/1389] drivers: counter: fix the bug for atcpit100 Let the callback execute after the interrupt status has cleared. Because if the callback is executed before the interrupt status is cleared, it might cause subsequent counter interrupts to fail to trigger due to the callback function taking too long to execute. Signed-off-by: Kevin Wang --- drivers/counter/counter_andes_atcpit100.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/counter/counter_andes_atcpit100.c b/drivers/counter/counter_andes_atcpit100.c index 5252c2c56cb3aa..3fc69215f60ccc 100644 --- a/drivers/counter/counter_andes_atcpit100.c +++ b/drivers/counter/counter_andes_atcpit100.c @@ -103,12 +103,6 @@ static void atcpit100_irq_handler(void *arg) if (int_status & TIMER0_CHANNEL(i)) { int_enable &= ~TIMER0_CHANNEL(i); ch_enable &= ~TIMER0_CHANNEL(i); - - cb = data->ch_data[i].alarm_callback; - data->ch_data[i].alarm_callback = NULL; - - cur_ticks = get_current_tick(dev, 3); - cb(dev, i, cur_ticks, data->ch_data[i].alarm_user_data); } } @@ -118,6 +112,17 @@ static void atcpit100_irq_handler(void *arg) /* Clear interrupt status */ sys_write32(int_status, PIT_ISTA(dev)); + + for (i = 0; i < CH_NUM_PER_COUNTER; i++) { + if (int_status & TIMER0_CHANNEL(i)) { + cur_ticks = get_current_tick(dev, 3); + cb = data->ch_data[i].alarm_callback; + data->ch_data[i].alarm_callback = NULL; + if (cb != NULL) { + cb(dev, i, cur_ticks, data->ch_data[i].alarm_user_data); + } + } + } } static int counter_atcpit100_init(const struct device *dev) @@ -494,7 +499,7 @@ static const struct counter_driver_api atcpit100_driver_api = { NULL, \ &atcpit100_data_##n, \ &atcpit100_config_##n, \ - POST_KERNEL, \ + PRE_KERNEL_1, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ &atcpit100_driver_api); \ \ From 2be24d035c6e5b2d175546f26c0c72aa426cac65 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1000/1389] scripts: twisterlib: handlers: early QEMU timeout Terminate QEMU earlier if the test finishes and no output data is received for 1 second. This new timeout operates in parallel with the global test timeout. For coverage testing, this can reduce the time spent running individual tests by up to 29 seconds, while still giving the full 30 extra seconds to dump gcov data if needed. Signed-off-by: Jordan Yates --- scripts/pylib/twister/twisterlib/handlers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 970e6b2717efe4..414f89f207ace8 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -882,6 +882,9 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, while True: this_timeout = int((timeout_time - time.time()) * 1000) + if timeout_extended: + # Quit early after timeout extension if no more data is being received + this_timeout = min(this_timeout, 1000) if this_timeout < 0 or not p.poll(this_timeout): try: if pid and this_timeout > 0: From c54f1c1d4b41413206966a550046828fe5a707bc Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1001/1389] llvm: stdint: Don't define integer constant macros in llvm.h Zephyr minimal libc implements integer constant macros using internal headers provided by GCC, for example INT64_C(x) is just a __INT64_C(x) which is implemented by the GCC. Clang compiler doesn't provide these definitions, so we define them (__INT64_C() and INT64_C()) in zephyr/toolchain/llvm.h, but it looks like INT64_C() definition doesn't come from llvm.h, but from stdlib.h despite of checking if __GNUC__ is defined. This is because Clang sometimes pretends to be GNU compiler: $ x86_64-pc-linux-gnu-clang -dM -E - < /dev/null | grep "GNU" #define __GNUC_MINOR__ 2 #define __GNUC_PATCHLEVEL__ 1 #define __GNUC_STDC_INLINE__ 1 #define __GNUC__ 4 Let's keep the integer constant macros in stdlib.h and their actual implementation in llvm.h. Also define these macros if __clang__ is defined, just in case. Signed-off-by: Patryk Duda --- include/zephyr/toolchain/llvm.h | 38 ------------------------------- lib/libc/minimal/include/stdint.h | 4 ++-- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/include/zephyr/toolchain/llvm.h b/include/zephyr/toolchain/llvm.h index 8a78d4e8404864..a77e82a45e2b84 100644 --- a/include/zephyr/toolchain/llvm.h +++ b/include/zephyr/toolchain/llvm.h @@ -34,80 +34,42 @@ #define __INT8_C(x) x #endif -#ifndef INT8_C -#define INT8_C(x) __INT8_C(x) -#endif - #ifndef __UINT8_C #define __UINT8_C(x) x ## U #endif -#ifndef UINT8_C -#define UINT8_C(x) __UINT8_C(x) -#endif - #ifndef __INT16_C #define __INT16_C(x) x #endif -#ifndef INT16_C -#define INT16_C(x) __INT16_C(x) -#endif - #ifndef __UINT16_C #define __UINT16_C(x) x ## U #endif -#ifndef UINT16_C -#define UINT16_C(x) __UINT16_C(x) -#endif - #ifndef __INT32_C #define __INT32_C(x) x #endif -#ifndef INT32_C -#define INT32_C(x) __INT32_C(x) -#endif - #ifndef __UINT32_C #define __UINT32_C(x) x ## U #endif -#ifndef UINT32_C -#define UINT32_C(x) __UINT32_C(x) -#endif - #ifndef __INT64_C #define __INT64_C(x) x #endif -#ifndef INT64_C -#define INT64_C(x) __INT64_C(x) -#endif - #ifndef __UINT64_C #define __UINT64_C(x) x ## ULL #endif -#ifndef UINT64_C -#define UINT64_C(x) __UINT64_C(x) -#endif - #ifndef __INTMAX_C #define __INTMAX_C(x) x #endif -#ifndef INTMAX_C -#define INTMAX_C(x) __INTMAX_C(x) -#endif #ifndef __UINTMAX_C #define __UINTMAX_C(x) x ## ULL #endif -#ifndef UINTMAX_C -#define UINTMAX_C(x) __UINTMAX_C(x) -#endif #endif /* ZEPHYR_INCLUDE_TOOLCHAIN_LLVM_H_ */ diff --git a/lib/libc/minimal/include/stdint.h b/lib/libc/minimal/include/stdint.h index 904f0b49b2560b..80a2ff1ab2929a 100644 --- a/lib/libc/minimal/include/stdint.h +++ b/lib/libc/minimal/include/stdint.h @@ -104,7 +104,7 @@ typedef __UINT_LEAST64_TYPE__ uint_least64_t; typedef __INTPTR_TYPE__ intptr_t; typedef __UINTPTR_TYPE__ uintptr_t; -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) /* These macros must produce constant integer expressions, which can't * be done in the preprocessor (casts aren't allowed). Defer to the * GCC internal functions where they're available. @@ -120,7 +120,7 @@ typedef __UINTPTR_TYPE__ uintptr_t; #define UINT32_C(_v) __UINT32_C(_v) #define UINT64_C(_v) __UINT64_C(_v) #define UINTMAX_C(_v) __UINTMAX_C(_v) -#endif /* __GNUC__ */ +#endif /* defined(__GNUC__) || defined(__clang__) */ #ifdef __CCAC__ #ifndef __INT8_C From 28f98173b705cefe2096e4243e3d4be3cd0d426a Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1002/1389] toolchain/llvm: Provide integer macros only when necessary Using '#ifndef' before defining a macro is a good way to provide default version of the macro if not defined elsewhere. But it has some disadvantages: - It hides information about the users of these macros. It's hard to determine when this implementation is used. - Correctness depends on file including order. It looks like these macros are used only by minimal libc and only if ENFORCE_ZEPHYR_STDINT is not selected. We expect other libc to provide their own implementation. Signed-off-by: Patryk Duda --- include/zephyr/toolchain/llvm.h | 39 +++++++++------------------------ 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/include/zephyr/toolchain/llvm.h b/include/zephyr/toolchain/llvm.h index a77e82a45e2b84..fb203f5becd08f 100644 --- a/include/zephyr/toolchain/llvm.h +++ b/include/zephyr/toolchain/llvm.h @@ -30,46 +30,27 @@ #include -#ifndef __INT8_C -#define __INT8_C(x) x -#endif +/* + * Provide these definitions only when minimal libc is used. + * Avoid collision with defines from include/zephyr/toolchain/zephyr_stdint.h + */ +#ifdef CONFIG_MINIMAL_LIBC +#ifndef CONFIG_ENFORCE_ZEPHYR_STDINT -#ifndef __UINT8_C +#define __INT8_C(x) x #define __UINT8_C(x) x ## U -#endif - -#ifndef __INT16_C #define __INT16_C(x) x -#endif - -#ifndef __UINT16_C #define __UINT16_C(x) x ## U -#endif - -#ifndef __INT32_C #define __INT32_C(x) x -#endif - -#ifndef __UINT32_C #define __UINT32_C(x) x ## U -#endif - -#ifndef __INT64_C #define __INT64_C(x) x -#endif - -#ifndef __UINT64_C #define __UINT64_C(x) x ## ULL -#endif - -#ifndef __INTMAX_C -#define __INTMAX_C(x) x -#endif +#endif /* !CONFIG_ENFORCE_ZEPHYR_STDINT */ -#ifndef __UINTMAX_C +#define __INTMAX_C(x) x #define __UINTMAX_C(x) x ## ULL -#endif +#endif /* CONFIG_MINIMAL_LIBC */ #endif /* ZEPHYR_INCLUDE_TOOLCHAIN_LLVM_H_ */ From 9da13fe458c3dd16b422371e2835594fc5b461d4 Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1003/1389] toolchain/llvm: Fix integer macros implementation Currently __INT64_C() doesn't add any suffix to provided constant which causes the constant to have 'int' type. On the other side, __UINT64_C() adds ULL suffix which makes the constant 'unsigned long long'. Of course, __INT64_C() is wrong here because 'int' type, in most cases, has 32 bit width. According to the C standard, these macros are for minimum-width integer constants. For example, it means that using INT16_C() macro will give you constant with type the same as 'int_least16_t' type. Clang doesn't provide defines like __INT_LEAST16_C_SUFFIX__, which makes implementation difficult, because we need to determine appropriate type first. Signed-off-by: Patryk Duda --- include/zephyr/toolchain/llvm.h | 91 ++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/include/zephyr/toolchain/llvm.h b/include/zephyr/toolchain/llvm.h index fb203f5becd08f..d2bc4aeac34f29 100644 --- a/include/zephyr/toolchain/llvm.h +++ b/include/zephyr/toolchain/llvm.h @@ -37,19 +37,94 @@ #ifdef CONFIG_MINIMAL_LIBC #ifndef CONFIG_ENFORCE_ZEPHYR_STDINT -#define __INT8_C(x) x -#define __UINT8_C(x) x ## U -#define __INT16_C(x) x -#define __UINT16_C(x) x ## U +#define __int_c(v, suffix) v ## suffix +#define int_c(v, suffix) __int_c(v, suffix) +#define uint_c(v, suffix) __int_c(v ## U, suffix) + +#ifdef __INT64_TYPE__ +#undef __int_least64_c_suffix__ +#undef __int_least32_c_suffix__ +#undef __int_least16_c_suffix__ +#undef __int_least8_c_suffix__ +#ifdef __INT64_C_SUFFIX__ +#define __int_least64_c_suffix__ __INT64_C_SUFFIX__ +#define __int_least32_c_suffix__ __INT64_C_SUFFIX__ +#define __int_least16_c_suffix__ __INT64_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT64_C_SUFFIX__ +#endif /* __INT64_C_SUFFIX__ */ +#endif /* __INT64_TYPE__ */ + +#ifdef __INT_LEAST64_TYPE__ +#ifdef __int_least64_c_suffix__ +#define __INT64_C(x) int_c(x, __int_least64_c_suffix__) +#define __UINT64_C(x) uint_c(x, __int_least64_c_suffix__) +#else +#define __INT64_C(x) x +#define __UINT64_C(x) x ## U +#endif /* __int_least64_c_suffix__ */ +#endif /* __INT_LEAST64_TYPE__ */ + +#ifdef __INT32_TYPE__ +#undef __int_least32_c_suffix__ +#undef __int_least16_c_suffix__ +#undef __int_least8_c_suffix__ +#ifdef __INT32_C_SUFFIX__ +#define __int_least32_c_suffix__ __INT32_C_SUFFIX__ +#define __int_least16_c_suffix__ __INT32_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT32_C_SUFFIX__ +#endif /* __INT32_C_SUFFIX__ */ +#endif /* __INT32_TYPE__ */ + +#ifdef __INT_LEAST32_TYPE__ +#ifdef __int_least32_c_suffix__ +#define __INT32_C(x) int_c(x, __int_least32_c_suffix__) +#define __UINT32_C(x) uint_c(x, __int_least32_c_suffix__) +#else #define __INT32_C(x) x #define __UINT32_C(x) x ## U -#define __INT64_C(x) x -#define __UINT64_C(x) x ## ULL +#endif /* __int_least32_c_suffix__ */ +#endif /* __INT_LEAST32_TYPE__ */ + +#ifdef __INT16_TYPE__ +#undef __int_least16_c_suffix__ +#undef __int_least8_c_suffix__ +#ifdef __INT16_C_SUFFIX__ +#define __int_least16_c_suffix__ __INT16_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT16_C_SUFFIX__ +#endif /* __INT16_C_SUFFIX__ */ +#endif /* __INT16_TYPE__ */ + +#ifdef __INT_LEAST16_TYPE__ +#ifdef __int_least16_c_suffix__ +#define __INT16_C(x) int_c(x, __int_least16_c_suffix__) +#define __UINT16_C(x) uint_c(x, __int_least16_c_suffix__) +#else +#define __INT16_C(x) x +#define __UINT16_C(x) x ## U +#endif /* __int_least16_c_suffix__ */ +#endif /* __INT_LEAST16_TYPE__ */ + +#ifdef __INT8_TYPE__ +#undef __int_least8_c_suffix__ +#ifdef __INT8_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT8_C_SUFFIX__ +#endif /* __INT8_C_SUFFIX__ */ +#endif /* __INT8_TYPE__ */ + +#ifdef __INT_LEAST8_TYPE__ +#ifdef __int_least8_c_suffix__ +#define __INT8_C(x) int_c(x, __int_least8_c_suffix__) +#define __UINT8_C(x) uint_c(x, __int_least8_c_suffix__) +#else +#define __INT8_C(x) x +#define __UINT8_C(x) x ## U +#endif /* __int_least8_c_suffix__ */ +#endif /* __INT_LEAST8_TYPE__ */ #endif /* !CONFIG_ENFORCE_ZEPHYR_STDINT */ -#define __INTMAX_C(x) x -#define __UINTMAX_C(x) x ## ULL +#define __INTMAX_C(x) int_c(x, __INTMAX_C_SUFFIX__) +#define __UINTMAX_C(x) int_c(x, __UINTMAX_C_SUFFIX__) #endif /* CONFIG_MINIMAL_LIBC */ From bc3bcf79c032fa8c6635f535c86491f8b3b30afe Mon Sep 17 00:00:00 2001 From: Juliane Schulze Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1004/1389] drivers: set LIS2DH default trigger mode to "EDGE_BOTH" Previous value just activated the ability to trigger for both edges, without (de)-activating the gpio. This caused an assrtion error in GPIO.h. Fixes #71227 Signed-off-by: Juliane Schulze --- drivers/sensor/st/lis2dh/lis2dh_trigger.c | 2 +- dts/bindings/sensor/st,lis2dh-common.yaml | 4 ++-- include/zephyr/dt-bindings/sensor/lis2dh.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/st/lis2dh/lis2dh_trigger.c b/drivers/sensor/st/lis2dh/lis2dh_trigger.c index 6afa8af839b1f3..16b0ea52fb850c 100644 --- a/drivers/sensor/st/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/st/lis2dh/lis2dh_trigger.c @@ -19,7 +19,7 @@ LOG_MODULE_DECLARE(lis2dh, CONFIG_SENSOR_LOG_LEVEL); #include "lis2dh.h" static const gpio_flags_t gpio_int_cfg[5] = { - GPIO_INT_EDGE, + GPIO_INT_EDGE_BOTH, GPIO_INT_EDGE_RISING, GPIO_INT_EDGE_FALLING, GPIO_INT_LEVEL_HIGH, diff --git a/dts/bindings/sensor/st,lis2dh-common.yaml b/dts/bindings/sensor/st,lis2dh-common.yaml index 1988a7c1deb5e9..e4c41f586d5139 100644 --- a/dts/bindings/sensor/st,lis2dh-common.yaml +++ b/dts/bindings/sensor/st,lis2dh-common.yaml @@ -34,7 +34,7 @@ properties: The default of 0 is the most common situation to avoid multiple interrupts to be triggered by same event. - - 0 # LIS2DH_DT_GPIO_INT_EDGE + - 0 # LIS2DH_DT_GPIO_INT_EDGE_BOTH - 1 # LIS2DH_DT_GPIO_INT_EDGE_RISING - 2 # LIS2DH_DT_GPIO_INT_EDGE_FALLING - 3 # LIS2DH_DT_GPIO_INT_LEVEL_HIGH @@ -51,7 +51,7 @@ properties: The default of 0 is the most common situation to avoid multiple interrupts to be triggered by same event. - - 0 # LIS2DH_DT_GPIO_INT_EDGE + - 0 # LIS2DH_DT_GPIO_INT_EDGE_BOTH - 1 # LIS2DH_DT_GPIO_INT_EDGE_RISING - 2 # LIS2DH_DT_GPIO_INT_EDGE_FALLING - 3 # LIS2DH_DT_GPIO_INT_LEVEL_HIGH diff --git a/include/zephyr/dt-bindings/sensor/lis2dh.h b/include/zephyr/dt-bindings/sensor/lis2dh.h index a697f34cc80246..ff13d13a321b50 100644 --- a/include/zephyr/dt-bindings/sensor/lis2dh.h +++ b/include/zephyr/dt-bindings/sensor/lis2dh.h @@ -7,7 +7,7 @@ #define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DH_H_ /* GPIO interrupt configuration */ -#define LIS2DH_DT_GPIO_INT_EDGE 0 +#define LIS2DH_DT_GPIO_INT_EDGE_BOTH 0 #define LIS2DH_DT_GPIO_INT_EDGE_RISING 1 #define LIS2DH_DT_GPIO_INT_EDGE_FALLING 2 #define LIS2DH_DT_GPIO_INT_LEVEL_HIGH 3 From c66f34e964e1bc1cd0d98da049113faa3028ae17 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1005/1389] coding guidelines: comply with MISRA Rule 11.6 removed unneeded conversions from integer to pointer Signed-off-by: Hess Nathan --- arch/x86/core/x86_mmu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index 313afbb7922e16..7bfa2088a418e7 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -1169,8 +1169,8 @@ static int range_map(void *virt, uintptr_t phys, size_t size, { int ret = 0, ret2; - LOG_DBG("%s: %p -> %p (%zu) flags " PRI_ENTRY " mask " - PRI_ENTRY " opt 0x%x", __func__, (void *)phys, virt, size, + LOG_DBG("%s: 0x%" PRIxPTR " -> %p (%zu) flags " PRI_ENTRY " mask " + PRI_ENTRY " opt 0x%x", __func__, phys, virt, size, entry_flags, mask, options); #ifdef CONFIG_X86_64 @@ -1781,8 +1781,8 @@ static inline int apply_region(pentry_t *ptables, void *start, __pinned_func static void set_stack_perms(struct k_thread *thread, pentry_t *ptables) { - LOG_DBG("update stack for thread %p's ptables at %p: %p (size %zu)", - thread, ptables, (void *)thread->stack_info.start, + LOG_DBG("update stack for thread %p's ptables at %p: 0x%" PRIxPTR " (size %zu)", + thread, ptables, thread->stack_info.start, thread->stack_info.size); apply_region(ptables, (void *)thread->stack_info.start, thread->stack_info.size, @@ -1929,8 +1929,8 @@ int arch_mem_domain_thread_add(struct k_thread *thread) } thread->arch.ptables = z_mem_phys_addr(domain->arch.ptables); - LOG_DBG("set thread %p page tables to %p", thread, - (void *)thread->arch.ptables); + LOG_DBG("set thread %p page tables to 0x%" PRIxPTR, thread, + thread->arch.ptables); /* Check if we're doing a migration from a different memory domain * and have to remove permissions from its old domain. From 58b81e4c82517161d0826d5c947ceca80bebe030 Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1006/1389] ci: codecov: Fix merged coverage report path This commit updates the codecov workflow to specify the full coverage report file path under `files` because codecov-action v4 does not correctly process the `directory` parameter. Signed-off-by: Stephanos Ioannidis --- .github/workflows/codecov.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 63812a85eb2916..0e16d6b6ab82fb 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -222,9 +222,8 @@ jobs: if: always() uses: codecov/codecov-action@v4 with: - directory: ./coverage/reports env_vars: OS,PYTHON fail_ci_if_error: false verbose: true token: ${{ secrets.CODECOV_TOKEN }} - files: merged.xml + files: coverage/reports/merged.xml From a9be47d6b0b6cb7e5a35d1659ecca24439eab8f9 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1007/1389] MAINTAINERS: cleanup x86/xtensa areas cleanup x86/xtensa areas and update maintainers. Signed-off-by: Anas Nashif --- MAINTAINERS.yml | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index ed368a990e9b2e..a95e3b9b37eb88 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -114,11 +114,7 @@ ACPI: status: maintained maintainers: - - jhedberg - najumon1980 - collaborators: - - finikorg - - tbursztyka files: - lib/acpi/ - include/zephyr/acpi/ @@ -1674,10 +1670,6 @@ Release Notes: status: maintained maintainers: - dcpleung - collaborators: - - jhedberg - - finikorg - - tbursztyka files: - drivers/pcie/ - include/zephyr/drivers/pcie/ @@ -3235,11 +3227,12 @@ SiLabs Platforms: Intel Platforms (X86): status: maintained maintainers: - - jhedberg + - edersondisouza collaborators: - - tbursztyka - - laurenmurphyx64 - najumon1980 + - teburd + - dcpleung + - ceolin files: - boards/intel/adl/ - boards/intel/ehl/ @@ -3248,16 +3241,18 @@ Intel Platforms (X86): - soc/intel/atom/ - soc/intel/lakemont/ - soc/intel/*_lake/ + - drivers/timer/Kconfig.x86 + - drivers/timer/hpet.c + - drivers/timer/apic* labels: - "platform: X86" Intel Platforms (Xtensa): status: maintained maintainers: - - nashif + - dcpleung collaborators: - andyross - - dcpleung - lyakh - lgirdwood - marc-hb @@ -3267,6 +3262,7 @@ Intel Platforms (Xtensa): - softwarecki - jxstelter - marcinszkudlinski + - nashif files: - boards/intel/adsp/ - soc/intel/intel_adsp/ @@ -3285,6 +3281,7 @@ Intel Platforms (ISH): collaborators: - teburd - likongintel + - nashif files: - boards/intel/ish/ - soc/intel/intel_ish/ @@ -4018,9 +4015,6 @@ West: status: maintained maintainers: - najumon1980 - - jhedberg - collaborators: - - tbursztyka files: - modules/acpica/ labels: @@ -4791,15 +4785,14 @@ Xtensa arch: x86 arch: status: maintained maintainers: - - jhedberg + - edersondisouza collaborators: - - tbursztyka - andyross - - nashif - dcpleung - ceolin - laurenmurphyx64 - najumon1980 + - nashif files: - arch/x86/ - include/zephyr/arch/x86/ From 2c941e35ee6f0448c5272999468d32ecf62dd26d Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1008/1389] sensor: sensor_shell: print something when trig command succeeds Print something to the shell when the `trig` command completed successfully. Signed-off-by: Yong Cong Sin --- drivers/sensor/sensor_shell.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 8b26b1fed8d85e..972f62c7fe3fe8 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -998,6 +998,7 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; int trigger; + bool trigger_enabled = false; int err; if (argc < 4) { @@ -1038,6 +1039,7 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) } err = sensor_trigger_set(dev, &sensor_trigger_table[trigger].trigger, sensor_trigger_table[trigger].handler); + trigger_enabled = true; } } else if (strcmp(argv[2], "off") == 0) { /* Clear the handler for the given trigger on this device */ @@ -1060,6 +1062,10 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) if (err) { shell_error(sh, "Error while setting trigger %d on device %s (%d)", trigger, argv[1], err); + } else { + shell_info(sh, "%s trigger idx=%d %s on device %s", + trigger_enabled ? "Enabled" : "Disabled", trigger, + sensor_trigger_table[trigger].name, argv[1]); } return err; From 9405c8312e8e5904cc463556db25d48483b975a7 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1009/1389] samples: sensor: sensor_shell: add fake sensor driver Add a simple fake sensor driver so that the sample is more fun for boards without real sensor. Signed-off-by: Yong Cong Sin --- samples/sensor/sensor_shell/CMakeLists.txt | 4 + samples/sensor/sensor_shell/Kconfig | 6 ++ samples/sensor/sensor_shell/README.rst | 8 ++ samples/sensor/sensor_shell/app.overlay | 26 +++++ .../sensor_shell/dts/bindings/vnd,sensor.yaml | 8 ++ samples/sensor/sensor_shell/src/fake_sensor.c | 94 +++++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 samples/sensor/sensor_shell/app.overlay create mode 100644 samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml create mode 100644 samples/sensor/sensor_shell/src/fake_sensor.c diff --git a/samples/sensor/sensor_shell/CMakeLists.txt b/samples/sensor/sensor_shell/CMakeLists.txt index 1f13027d26b908..597957beb61c04 100644 --- a/samples/sensor/sensor_shell/CMakeLists.txt +++ b/samples/sensor/sensor_shell/CMakeLists.txt @@ -7,4 +7,8 @@ project(sensor_shell) target_sources(app PRIVATE src/main.c) +target_sources_ifdef(CONFIG_SAMPLES_SENSOR_SHELL_FAKE_SENSOR app PRIVATE + src/fake_sensor.c +) + target_include_directories(app PRIVATE include) diff --git a/samples/sensor/sensor_shell/Kconfig b/samples/sensor/sensor_shell/Kconfig index 354385ee6cadcf..38fcdfa7eb6eba 100644 --- a/samples/sensor/sensor_shell/Kconfig +++ b/samples/sensor/sensor_shell/Kconfig @@ -1,4 +1,10 @@ # Copyright (c) 2023 Google LLC # SPDX-License-Identifier: Apache-2.0 +config SAMPLES_SENSOR_SHELL_FAKE_SENSOR + bool "Enable fake sensor" + help + On boards that do not have a sensor, enabling this will build a fake + sensor that can be interacted with via the sensor shell. + source "Kconfig.zephyr" diff --git a/samples/sensor/sensor_shell/README.rst b/samples/sensor/sensor_shell/README.rst index db9e3e2061f3b9..d3146e5201dd38 100644 --- a/samples/sensor/sensor_shell/README.rst +++ b/samples/sensor/sensor_shell/README.rst @@ -18,6 +18,14 @@ enabled, for example: :board: reel_board :goals: build flash +For boards that do not have a sensor, a simple fake sensor driver is provided, for example: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/sensor_shell + :board: qemu_riscv64 + :goals: run + :gen-args: -DCONFIG_SAMPLES_SENSOR_SHELL_FAKE_SENSOR=y + Shell Module Command Help ========================= diff --git a/samples/sensor/sensor_shell/app.overlay b/samples/sensor/sensor_shell/app.overlay new file mode 100644 index 00000000000000..79d50cb6b2b590 --- /dev/null +++ b/samples/sensor/sensor_shell/app.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + app { + #address-cells = <1>; + #size-cells = <0>; + + vsensor0: sensor@0 { + compatible = "vnd,fake-sensor"; + reg = <0>; + friendly-name = "Fake sensor 0"; + status = "okay"; + }; + + vsensor1: sensor@1 { + compatible = "vnd,fake-sensor"; + reg = <1>; + friendly-name = "Fake sensor 1"; + status = "okay"; + }; + }; +}; diff --git a/samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml b/samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml new file mode 100644 index 00000000000000..50c32f17dbac2e --- /dev/null +++ b/samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +description: Fake sensor + +include: sensor-device.yaml + +compatible: "vnd,fake-sensor" diff --git a/samples/sensor/sensor_shell/src/fake_sensor.c b/samples/sensor/sensor_shell/src/fake_sensor.c new file mode 100644 index 00000000000000..212ef5e0565560 --- /dev/null +++ b/samples/sensor/sensor_shell/src/fake_sensor.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT vnd_fake_sensor + +#include +#include +#include + +LOG_MODULE_REGISTER(fake_sensor); + +static int init(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 0; +} + +static int attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + const struct sensor_value *val) +{ + LOG_DBG("[%s] dev: %p, chan: %d, attr: %d, val1: %d, val2: %d", __func__, dev, chan, attr, + val->val1, val->val2); + + return 0; +} + +static int attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + struct sensor_value *val) +{ + LOG_DBG("[%s] dev: %p, chan: %d, attr: %d", __func__, dev, chan, attr); + + val->val1 = chan; + val->val2 = attr * 100000; + + return 0; +} + +static int sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + LOG_DBG("[%s] dev: %p, chan: %d", __func__, dev, chan); + + return 0; +} + +static int channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + LOG_DBG("[%s] dev: %p, chan: %d", __func__, dev, chan); + + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + __fallthrough; + case SENSOR_CHAN_GYRO_XYZ: + __fallthrough; + case SENSOR_CHAN_MAGN_XYZ: + for (int i = 0; i < 3; i++, val++) { + val->val1 = chan; + val->val2 = 1; + } + break; + default: + val->val1 = chan; + val->val2 = 1; + break; + } + + return 0; +} + +static int trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + LOG_DBG("[%s - %s] dev: %p, trig->chan: %d, trig->type: %d, handler: %p", __func__, + (handler == NULL) ? "off" : "on", dev, trig->chan, trig->type, handler); + + return 0; +} + +static const struct sensor_driver_api api = { + .attr_get = attr_get, + .attr_set = attr_set, + .sample_fetch = sample_fetch, + .channel_get = channel_get, + .trigger_set = trigger_set, +}; + +#define VND_SENSOR_INIT(n) \ + SENSOR_DEVICE_DT_INST_DEFINE(n, init, NULL, NULL, NULL, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &api); + +DT_INST_FOREACH_STATUS_OKAY(VND_SENSOR_INIT) From 6d977a4ccbaf4578c932f3dd8afac071424c33f1 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1010/1389] samples: sensor: sensor_shell: add pytest Use pytest to test the shell commands. Signed-off-by: Yong Cong Sin --- .../sensor_shell/pytest/test_sensor_shell.py | 70 +++++++++++++++++++ samples/sensor/sensor_shell/sample.yaml | 15 +++- 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 samples/sensor/sensor_shell/pytest/test_sensor_shell.py diff --git a/samples/sensor/sensor_shell/pytest/test_sensor_shell.py b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py new file mode 100644 index 00000000000000..c13f888a28507f --- /dev/null +++ b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py @@ -0,0 +1,70 @@ +# Copyright (c) 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +import logging + +from twister_harness import Shell + +logger = logging.getLogger(__name__) + + +def test_sensor_shell_info(shell: Shell): + logger.info('send "sensor info" command') + + lines = shell.exec_command('sensor info') + assert any(['device name: sensor@0' in line for line in lines]), 'expected response not found' + assert any(['device name: sensor@1' in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_get(shell: Shell): + logger.info('send "sensor get" command') + + lines = shell.exec_command('sensor get sensor@0 voltage') + assert any(['channel type=31(voltage)' in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor get sensor@1 53') + assert any(['channel type=53(gauge_time_to_empty)' in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_attr_get(shell: Shell): + logger.info('send "sensor attr_get" command') + + lines = shell.exec_command('sensor attr_get sensor@0 co2 sampling_frequency') + assert any(['sensor@0(channel=co2, attr=sampling_frequency)' in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor attr_get sensor@1 53 3') + assert any(['sensor@1(channel=gauge_time_to_empty, attr=slope_th)' in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_attr_set(shell: Shell): + logger.info('send "sensor attr_set" command') + + lines = shell.exec_command('sensor attr_set sensor@0 co2 sampling_frequency 1') + expected_line = 'sensor@0 channel=co2, attr=sampling_frequency set to value=1' + assert any([expected_line in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor attr_set sensor@1 53 3 1') + expected_line = 'sensor@1 channel=gauge_time_to_empty, attr=slope_th set to value=1' + assert any([expected_line in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_trig(shell: Shell): + logger.info('send "sensor trig" command') + + lines = shell.exec_command('sensor trig sensor@0 on data_ready') + expected_line = 'Enabled trigger idx=1 data_ready on device sensor@0' + assert any([expected_line in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor trig sensor@0 off data_ready') + expected_line = 'Disabled trigger idx=1 data_ready on device sensor@0' + assert any([expected_line in line for line in lines]), 'expected response not found' + + logger.info('response is valid') diff --git a/samples/sensor/sensor_shell/sample.yaml b/samples/sensor/sensor_shell/sample.yaml index d89dfebc21aae2..51f57b10f6c0ca 100644 --- a/samples/sensor/sensor_shell/sample.yaml +++ b/samples/sensor/sensor_shell/sample.yaml @@ -1,5 +1,10 @@ sample: name: Shell Sensor Module Sample +common: + tags: + - sensor + - shell + tests: sample.sensor.shell: integration_platforms: @@ -7,7 +12,15 @@ tests: # TODO Remove once #63414 is resolved platform_exclude: gd32l233r_eval filter: ( CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_INTERRUPT ) - tags: shell harness: keyboard min_ram: 20 min_flash: 33 + sample.sensor.shell.pytest: + filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart") + min_ram: 40 + harness: pytest + extra_configs: + - arch:posix:CONFIG_NATIVE_UART_0_ON_STDINOUT=y + - CONFIG_SAMPLES_SENSOR_SHELL_FAKE_SENSOR=y + integration_platforms: + - native_sim From f1502978dc2a0b69821ceb20f4e2994a28c2418c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:20 +0200 Subject: [PATCH 1011/1389] drivers: sensor: stm32_temp: use sensor_value_from_float() The temperature being computed using a float variable, use sensor_value_from_float() instead of sensor_value_from_double(). This saves some flash. Signed-off-by: Aurelien Jarno --- drivers/sensor/st/stm32_temp/stm32_temp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensor/st/stm32_temp/stm32_temp.c b/drivers/sensor/st/stm32_temp/stm32_temp.c index 5e594b0fe0ce2a..fedd111af04033 100644 --- a/drivers/sensor/st/stm32_temp/stm32_temp.c +++ b/drivers/sensor/st/stm32_temp/stm32_temp.c @@ -149,7 +149,7 @@ static int stm32_temp_channel_get(const struct device *dev, enum sensor_channel temp += 25; #endif - return sensor_value_from_double(val, temp); + return sensor_value_from_float(val, temp); } static const struct sensor_driver_api stm32_temp_driver_api = { From 3132f2846b075b25d02381bc30cf87e590ca7e58 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1012/1389] headers: arch/xtensa: Drop extern attr from functions Drop extern attribute from function signature. Signed-off-by: Flavio Ceolin --- include/zephyr/arch/xtensa/arch.h | 8 ++++---- include/zephyr/arch/xtensa/irq.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/zephyr/arch/xtensa/arch.h b/include/zephyr/arch/xtensa/arch.h index 0b29df511b7faf..b5638870b4ac6b 100644 --- a/include/zephyr/arch/xtensa/arch.h +++ b/include/zephyr/arch/xtensa/arch.h @@ -79,7 +79,7 @@ struct arch_mem_domain { * * @param reason_p Reason for exception. */ -extern void xtensa_arch_except(int reason_p); +void xtensa_arch_except(int reason_p); /** * @brief Generate kernel oops. @@ -89,7 +89,7 @@ extern void xtensa_arch_except(int reason_p); * @param reason_p Reason for exception. * @param ssf Stack pointer. */ -extern void xtensa_arch_kernel_oops(int reason_p, void *ssf); +void xtensa_arch_kernel_oops(int reason_p, void *ssf); #ifdef CONFIG_USERSPACE @@ -117,7 +117,7 @@ __syscall void xtensa_user_fault(unsigned int reason); #include /* internal routine documented in C file, needed by IRQ_CONNECT() macro */ -extern void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags); +void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags); #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ { \ @@ -237,7 +237,7 @@ static inline bool arch_mem_coherent(void *ptr) * @param is_core0 True if this is called while executing on * CPU core #0. */ -extern void arch_xtensa_mmu_post_init(bool is_core0); +void arch_xtensa_mmu_post_init(bool is_core0); #endif #ifdef __cplusplus diff --git a/include/zephyr/arch/xtensa/irq.h b/include/zephyr/arch/xtensa/irq.h index 938ab7b2303c2e..3df8639ac737ad 100644 --- a/include/zephyr/arch/xtensa/irq.h +++ b/include/zephyr/arch/xtensa/irq.h @@ -160,7 +160,7 @@ static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) * * @return True if interrupt is enabled, false otherwise. */ -extern int xtensa_irq_is_enabled(unsigned int irq); +int xtensa_irq_is_enabled(unsigned int irq); #include From ed991ab2bfc61cb1fcc6a64ef121767c1bf947f2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1013/1389] headers: arch/x86: Drop extern attr from functions Drop extern attribute from function signature. Signed-off-by: Flavio Ceolin --- include/zephyr/arch/x86/arch.h | 8 ++++---- include/zephyr/arch/x86/ia32/arch.h | 6 +++--- include/zephyr/arch/x86/multiboot.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/zephyr/arch/x86/arch.h b/include/zephyr/arch/x86/arch.h index d58411bb1b507f..61036288671c8b 100644 --- a/include/zephyr/arch/x86/arch.h +++ b/include/zephyr/arch/x86/arch.h @@ -244,10 +244,10 @@ extern "C" { #ifndef _ASMLANGUAGE -extern void arch_irq_enable(unsigned int irq); -extern void arch_irq_disable(unsigned int irq); +void arch_irq_enable(unsigned int irq); +void arch_irq_disable(unsigned int irq); -extern uint32_t sys_clock_cycle_get_32(void); +uint32_t sys_clock_cycle_get_32(void); __pinned_func static inline uint32_t arch_k_cycle_get_32(void) @@ -255,7 +255,7 @@ static inline uint32_t arch_k_cycle_get_32(void) return sys_clock_cycle_get_32(); } -extern uint64_t sys_clock_cycle_get_64(void); +uint64_t sys_clock_cycle_get_64(void); __pinned_func static inline uint64_t arch_k_cycle_get_64(void) diff --git a/include/zephyr/arch/x86/ia32/arch.h b/include/zephyr/arch/x86/ia32/arch.h index 8e85ccaea111f4..e39e6c0cd65653 100644 --- a/include/zephyr/arch/x86/ia32/arch.h +++ b/include/zephyr/arch/x86/ia32/arch.h @@ -266,8 +266,8 @@ static inline void arch_irq_direct_pm(void) * tracing/tracing.h cannot be included here due to circular dependency */ #if defined(CONFIG_TRACING) -extern void sys_trace_isr_enter(void); -extern void sys_trace_isr_exit(void); +void sys_trace_isr_enter(void); +void sys_trace_isr_exit(void); #endif static inline void arch_isr_direct_header(void) @@ -287,7 +287,7 @@ static inline void arch_isr_direct_header(void) * cannot be referenced from a public header, so we move it to an * external function. */ -extern void arch_isr_direct_footer_swap(unsigned int key); +void arch_isr_direct_footer_swap(unsigned int key); static inline void arch_isr_direct_footer(int swap) { diff --git a/include/zephyr/arch/x86/multiboot.h b/include/zephyr/arch/x86/multiboot.h index 9a951a0150f085..66c312e48e242e 100644 --- a/include/zephyr/arch/x86/multiboot.h +++ b/include/zephyr/arch/x86/multiboot.h @@ -40,7 +40,7 @@ extern struct multiboot_info multiboot_info; #ifdef CONFIG_MULTIBOOT_INFO -extern void z_multiboot_init(struct multiboot_info *info_pa); +void z_multiboot_init(struct multiboot_info *info_pa); #else From 3ed4cce8dc218102383a4b551c942dd808239527 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1014/1389] headers: memory_domain: Drop extern attr from functions Drop extern attribute from function signature. Signed-off-by: Flavio Ceolin --- include/zephyr/app_memory/mem_domain.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/zephyr/app_memory/mem_domain.h b/include/zephyr/app_memory/mem_domain.h index ece13e3bdc29e0..8fe75eb33d9314 100644 --- a/include/zephyr/app_memory/mem_domain.h +++ b/include/zephyr/app_memory/mem_domain.h @@ -126,7 +126,7 @@ struct k_mem_partition; * @retval -EINVAL if invalid parameters supplied * @retval -ENOMEM if insufficient memory */ -extern int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, +int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, struct k_mem_partition *parts[]); /** @@ -156,7 +156,7 @@ extern int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, * @retval -EINVAL if invalid parameters supplied * @retval -ENOSPC if no free partition slots available */ -extern int k_mem_domain_add_partition(struct k_mem_domain *domain, +int k_mem_domain_add_partition(struct k_mem_domain *domain, struct k_mem_partition *part); /** @@ -171,7 +171,7 @@ extern int k_mem_domain_add_partition(struct k_mem_domain *domain, * @retval -EINVAL if invalid parameters supplied * @retval -ENOENT if no matching partition found */ -extern int k_mem_domain_remove_partition(struct k_mem_domain *domain, +int k_mem_domain_remove_partition(struct k_mem_domain *domain, struct k_mem_partition *part); /** @@ -185,7 +185,7 @@ extern int k_mem_domain_remove_partition(struct k_mem_domain *domain, * * @return 0 if successful, fails otherwise. */ -extern int k_mem_domain_add_thread(struct k_mem_domain *domain, +int k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread); #ifdef __cplusplus From e66c9832dbf0a836e48f21841881ffcadbac1762 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1015/1389] drivers: loapic: Drop extern attr from functions Drop extern attribute from function signature. Signed-off-by: Flavio Ceolin --- include/zephyr/drivers/interrupt_controller/loapic.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/zephyr/drivers/interrupt_controller/loapic.h b/include/zephyr/drivers/interrupt_controller/loapic.h index 564355dfefa727..75a47955bc632a 100644 --- a/include/zephyr/drivers/interrupt_controller/loapic.h +++ b/include/zephyr/drivers/interrupt_controller/loapic.h @@ -60,11 +60,11 @@ extern "C" { DEVICE_MMIO_TOPLEVEL_DECLARE(LOAPIC_REGS_STR); -extern uint32_t z_loapic_irq_base(void); -extern void z_loapic_enable(unsigned char cpu_number); -extern void z_loapic_int_vec_set(unsigned int irq, unsigned int vector); -extern void z_loapic_irq_enable(unsigned int irq); -extern void z_loapic_irq_disable(unsigned int irq); +uint32_t z_loapic_irq_base(void); +void z_loapic_enable(unsigned char cpu_number); +void z_loapic_int_vec_set(unsigned int irq, unsigned int vector); +void z_loapic_irq_enable(unsigned int irq); +void z_loapic_irq_disable(unsigned int irq); /** * @brief Read 64-bit value from the local APIC in x2APIC mode. From e476002130af5b832969f3fa16c5cffbf54b0e6c Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1016/1389] drivers: system_timer: Drop extern attr from functions Drop extern attribute from function signature. Signed-off-by: Flavio Ceolin --- include/zephyr/drivers/timer/system_timer.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/zephyr/drivers/timer/system_timer.h b/include/zephyr/drivers/timer/system_timer.h index 654df3874599f5..55f99ad3e28bca 100644 --- a/include/zephyr/drivers/timer/system_timer.h +++ b/include/zephyr/drivers/timer/system_timer.h @@ -70,7 +70,7 @@ extern "C" { * @param idle Hint to the driver that the system is about to enter * the idle state immediately after setting the timeout */ -extern void sys_clock_set_timeout(int32_t ticks, bool idle); +void sys_clock_set_timeout(int32_t ticks, bool idle); /** * @brief Timer idle exit notification @@ -84,7 +84,7 @@ extern void sys_clock_set_timeout(int32_t ticks, bool idle); * This is allowed for compatibility, but not recommended. The kernel * will figure that out on its own. */ -extern void sys_clock_idle_exit(void); +void sys_clock_idle_exit(void); /** * @brief Announce time progress to the kernel @@ -97,7 +97,7 @@ extern void sys_clock_idle_exit(void); * * @param ticks Elapsed time, in ticks */ -extern void sys_clock_announce(int32_t ticks); +void sys_clock_announce(int32_t ticks); /** * @brief Ticks elapsed since last sys_clock_announce() call @@ -107,7 +107,7 @@ extern void sys_clock_announce(int32_t ticks); * this with appropriate locking, the driver needs only provide an * instantaneous answer. */ -extern uint32_t sys_clock_elapsed(void); +uint32_t sys_clock_elapsed(void); /** * @brief Disable system timer. @@ -116,7 +116,7 @@ extern uint32_t sys_clock_elapsed(void); * The config @kconfig{CONFIG_SYSTEM_TIMER_HAS_DISABLE_SUPPORT} can be used to * check if the system timer has the capability of being disabled. */ -extern void sys_clock_disable(void); +void sys_clock_disable(void); /** * @brief Hardware cycle counter From 3278afad186a0339679a7721c024734a36d67c58 Mon Sep 17 00:00:00 2001 From: Helmut Lord Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1017/1389] snippets: rtt console Adds a snippet to enable RTT as console backend. Signed-off-by: Helmut Lord --- snippets/rtt-console/README.rst | 21 +++++++++++++++++++++ snippets/rtt-console/rtt-console.conf | 3 +++ snippets/rtt-console/snippet.yml | 3 +++ 3 files changed, 27 insertions(+) create mode 100644 snippets/rtt-console/README.rst create mode 100644 snippets/rtt-console/rtt-console.conf create mode 100644 snippets/rtt-console/snippet.yml diff --git a/snippets/rtt-console/README.rst b/snippets/rtt-console/README.rst new file mode 100644 index 00000000000000..68a1f1baf5a03d --- /dev/null +++ b/snippets/rtt-console/README.rst @@ -0,0 +1,21 @@ +.. _snippet-rtt-console: + +RTT Console Snippet (rtt-console) +######################################### + +.. code-block:: console + + west build -S rtt-console [...] + +Overview +******** + +This snippet redirects serial console output to SEGGER RTT. + +Requirements +************ + +Hardware support for: + +- :kconfig:option:`CONFIG_HAS_SEGGER_RTT` +- :kconfig:option:`CONFIG_CONSOLE` diff --git a/snippets/rtt-console/rtt-console.conf b/snippets/rtt-console/rtt-console.conf new file mode 100644 index 00000000000000..3453f62ca38ea7 --- /dev/null +++ b/snippets/rtt-console/rtt-console.conf @@ -0,0 +1,3 @@ +CONFIG_USE_SEGGER_RTT=y +CONFIG_RTT_CONSOLE=y +CONFIG_UART_CONSOLE=n diff --git a/snippets/rtt-console/snippet.yml b/snippets/rtt-console/snippet.yml new file mode 100644 index 00000000000000..c773063490c04d --- /dev/null +++ b/snippets/rtt-console/snippet.yml @@ -0,0 +1,3 @@ +name: rtt-console +append: + EXTRA_CONF_FILE: rtt-console.conf From 234e09804d16377845c096436648121db4061786 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1018/1389] drivers: watchdog: Add support for Apollo3 SoCs watchdog This commit adds support for the watchdog which can be found in Apollo3 SoCs Signed-off-by: Hao Luo --- boards/ambiq/apollo3_evb/apollo3_evb.dts | 4 +++ boards/ambiq/apollo3_evb/apollo3_evb.yaml | 1 + boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 4 +++ boards/ambiq/apollo3p_evb/apollo3p_evb.yaml | 1 + drivers/watchdog/wdt_ambiq.c | 35 +++++++++++++++++++-- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index 97021e84f27176..fd961a550bef8a 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -91,6 +91,10 @@ status = "okay"; }; +&wdt0 { + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.yaml b/boards/ambiq/apollo3_evb/apollo3_evb.yaml index 1be99d9d92bdf7..a85086461c3ee5 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.yaml +++ b/boards/ambiq/apollo3_evb/apollo3_evb.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb supported: - uart + - watchdog - gpio testing: ignore_tags: diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index e510c52ad44b7b..2bccb1746d84f9 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -91,6 +91,10 @@ status = "okay"; }; +&wdt0 { + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml index fe17883861b225..d789a2519bcc0a 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb supported: - uart + - watchdog - gpio testing: ignore_tags: diff --git a/drivers/watchdog/wdt_ambiq.c b/drivers/watchdog/wdt_ambiq.c index 5e3cf663b8e185..91929c91e20fff 100644 --- a/drivers/watchdog/wdt_ambiq.c +++ b/drivers/watchdog/wdt_ambiq.c @@ -35,10 +35,13 @@ static void wdt_ambiq_isr(void *arg) const struct device *dev = (const struct device *)arg; struct wdt_ambiq_data *data = dev->data; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_wdt_int_clear(); +#else uint32_t status; - am_hal_wdt_interrupt_status_get(AM_HAL_WDT_MCU, &status, false); am_hal_wdt_interrupt_clear(AM_HAL_WDT_MCU, status); +#endif if (data->callback) { data->callback(dev, 0); @@ -51,6 +54,25 @@ static int wdt_ambiq_setup(const struct device *dev, uint8_t options) struct wdt_ambiq_data *data = dev->data; am_hal_wdt_config_t cfg; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t ui32ClockSource = AM_HAL_WDT_LFRC_CLK_DEFAULT; + + if (dev_cfg->clk_freq == 128) { + ui32ClockSource = AM_HAL_WDT_LFRC_CLK_128HZ; + } else if (dev_cfg->clk_freq == 16) { + ui32ClockSource = AM_HAL_WDT_LFRC_CLK_16HZ; + } else if (dev_cfg->clk_freq == 1) { + ui32ClockSource = AM_HAL_WDT_LFRC_CLK_1HZ; + } + cfg.ui32Config = ui32ClockSource | _VAL2FLD(WDT_CFG_RESEN, data->reset) | + AM_HAL_WDT_ENABLE_INTERRUPT; + cfg.ui16InterruptCount = data->timeout; + cfg.ui16ResetCount = data->timeout; + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0); + am_hal_wdt_init(&cfg); + am_hal_wdt_int_enable(); + am_hal_wdt_start(); +#else if (dev_cfg->clk_freq == 128) { cfg.eClockSource = AM_HAL_WDT_128HZ; } else if (dev_cfg->clk_freq == 16) { @@ -68,7 +90,7 @@ static int wdt_ambiq_setup(const struct device *dev, uint8_t options) am_hal_wdt_config(AM_HAL_WDT_MCU, &cfg); am_hal_wdt_interrupt_enable(AM_HAL_WDT_MCU, AM_HAL_WDT_INTERRUPT_MCU); am_hal_wdt_start(AM_HAL_WDT_MCU, false); - +#endif return 0; } @@ -76,8 +98,11 @@ static int wdt_ambiq_disable(const struct device *dev) { ARG_UNUSED(dev); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_wdt_halt(); +#else am_hal_wdt_stop(AM_HAL_WDT_MCU); - +#endif return 0; } @@ -114,7 +139,11 @@ static int wdt_ambiq_feed(const struct device *dev, int channel_id) ARG_UNUSED(dev); ARG_UNUSED(channel_id); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_wdt_restart(); +#else am_hal_wdt_restart(AM_HAL_WDT_MCU); +#endif LOG_DBG("Fed the watchdog"); return 0; From 1a595b549c681cc2685997a35cd2ca21e35b016b Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1019/1389] arch/xtensa: Automatically generate interrupt handlers (finally) The script to generate the _soc_inthandlers.h header has been run manually for years, only because I was a cmake novice at the time and unsure how to integrate it into the build. So every new platform has to find the script and template file and figure out how to generate the file. And in a few cases it looks like we've tried to EDIT the resulting files in the tree. Let's finally do this right. The file is now dropped (for every xtensa platform) as a "xtensa_handlers.h" file, and there is a Kconfig to control whether the original/manual file or the new one is used by the platform code. We can migrate the other platforms slowly as people have time to validate. Signed-off-by: Andy Ross --- arch/xtensa/Kconfig | 10 ++++++++++ arch/xtensa/core/CMakeLists.txt | 19 +++++++++++++++++++ arch/xtensa/core/vector_handlers.c | 7 ++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8aa3d0fa96cc68..82a44f820c58a6 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -22,6 +22,16 @@ config XTENSA_RESET_VECTOR This is always needed for the simulator. Real boards may already implement this in boot ROM. +config XTENSA_GEN_HANDLERS + bool "Automatically generate interrupt handlers" + default n + help + When set, an "xtensa_handlers.h" file is generated + containing definitions for the interrupt entry code of the + target Xtensa core, based automatically on the details in + the core-isa.h file. This replaces the previous scheme + where a _soc_inthandlers.h file would be generated offline. + config XTENSA_USE_CORE_CRT1 bool "Use crt1.S from core" default y diff --git a/arch/xtensa/core/CMakeLists.txt b/arch/xtensa/core/CMakeLists.txt index fab15a803dad8e..40906a0a3262b4 100644 --- a/arch/xtensa/core/CMakeLists.txt +++ b/arch/xtensa/core/CMakeLists.txt @@ -84,3 +84,22 @@ add_custom_target(zsr_h DEPENDS ${ZSR_H}) add_dependencies(zephyr_interface zsr_h) unset(MAY_NEED_SYSCALL_SCRATCH_REG) + +# Similar: auto-generate interrupt handlers +set(HANDLERS ${CMAKE_BINARY_DIR}/zephyr/include/generated/xtensa_handlers) + +add_custom_command( + OUTPUT ${HANDLERS}_tmp.c + COMMAND ${CMAKE_C_COMPILER} -E -U__XCC__ + -I${ZEPHYR_XTENSA_MODULE_DIR}/zephyr/soc/${CONFIG_SOC} + -o ${HANDLERS}_tmp.c + - < ${CMAKE_CURRENT_SOURCE_DIR}/xtensa_intgen.tmpl) + +add_custom_command( + OUTPUT ${HANDLERS}.h + DEPENDS ${HANDLERS}_tmp.c + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/xtensa_intgen.py + ${HANDLERS}_tmp.c > ${HANDLERS}.h) + +add_custom_target(xtensa_handlers_h DEPENDS ${HANDLERS}.h) +add_dependencies(zephyr_interface xtensa_handlers_h) diff --git a/arch/xtensa/core/vector_handlers.c b/arch/xtensa/core/vector_handlers.c index b8dca1c19679c9..ee0ec0fe9395db 100644 --- a/arch/xtensa/core/vector_handlers.c +++ b/arch/xtensa/core/vector_handlers.c @@ -10,13 +10,18 @@ #include #include #include -#include <_soc_inthandlers.h> #include #include #include #include #include +#ifdef CONFIG_XTENSA_GEN_HANDLERS +#include +#else +#include <_soc_inthandlers.h> +#endif + #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); From 43c9fe5807d9539b0a32793cb4e485955ffea5d6 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1020/1389] arch/xtensa: "NMILEVEL" is an optional feature Some oddballs cores can be generated without an "NMI" interrupt, in which case core-isa.h will not define XCHAL_NMILEVEL. This code is trying to unconditionally mask interrupts, so XCHAL_EXCM_LEVEL is the pedantically correct choice anyway (NMI's by definition, cannot be masked). Signed-off-by: Andy Ross --- arch/xtensa/core/vector_handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/core/vector_handlers.c b/arch/xtensa/core/vector_handlers.c index ee0ec0fe9395db..f0b0a9175ff2c6 100644 --- a/arch/xtensa/core/vector_handlers.c +++ b/arch/xtensa/core/vector_handlers.c @@ -364,7 +364,7 @@ void *xtensa_excint1_c(int *interrupted_stack) * thread. */ __asm__ volatile("rsil %0, %1" - : "=r" (ignore) : "i"(XCHAL_NMILEVEL)); + : "=r" (ignore) : "i"(XCHAL_EXCM_LEVEL)); _current_cpu->nested = 1; } From c4ff3b921b4780fcb734ff8d10443670ef9cd77c Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1021/1389] arch/xtensa: xtensa_intgen.py: Emit handlers for all levels The original code would (unsurprisingly) only emit handler functions for interrupt levels with interrupts associated with them. But it turns out that it's possible to configure an xtensa device with an empty-but-otherwise-real interrupt level (specifically mt8195 has a "Level 3" interrupt not associated with any input IRQS, it's one level above EXCM_LEVEL and one level below the DEBUG exception). This script is old, and not set up to parse the full core-isa.h directly, so modifying it to detect this condition is difficult. Instead, just emit all 15 possible interrupt handlers, even empty ones. The extra stubs are harmless as they'll be dropped if uncalled. Signed-off-by: Andy Ross --- arch/xtensa/core/xtensa_intgen.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/xtensa/core/xtensa_intgen.py b/arch/xtensa/core/xtensa_intgen.py index 6a7935d409cfd3..2770cb4662c8a1 100755 --- a/arch/xtensa/core/xtensa_intgen.py +++ b/arch/xtensa/core/xtensa_intgen.py @@ -105,13 +105,11 @@ def emit_int_handler(ints): cprint("#endif") cprint("") -# Populate empty levels just for sanity. The second-to-last interrupt -# level (usually "debug") typically doesn't have any associated -# vectors, but we don't have any way to know that a-prioi. -max = 0 -for lvl in ints_by_lvl: - if lvl > max: - max = lvl +# Populate all theoretical levels just in case. Odd cores have been +# seen in the wild with "empty" interrupt levels that exist in the +# hardware but without any interrupts associated with them. The +# unused handlers will be ignored if uncalled. +max = 15 for lvl in range(0, max+1): if not lvl in ints_by_lvl: From 39938b9e7bbc3e8d7ca6bee0c231c2786025a3f0 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1022/1389] soc/qemu_xtensa_dc233c: Use auto-generated interrupt handlers The script runs as part of the build now. Use that feature and remove the old static file from the manually-run script. Signed-off-by: Andy Ross --- soc/cdns/dc233c/Kconfig.defconfig | 3 + soc/cdns/dc233c/include/_soc_inthandlers.h | 279 --------------------- 2 files changed, 3 insertions(+), 279 deletions(-) delete mode 100644 soc/cdns/dc233c/include/_soc_inthandlers.h diff --git a/soc/cdns/dc233c/Kconfig.defconfig b/soc/cdns/dc233c/Kconfig.defconfig index c872936a0448ab..ff74226cce16f0 100644 --- a/soc/cdns/dc233c/Kconfig.defconfig +++ b/soc/cdns/dc233c/Kconfig.defconfig @@ -6,6 +6,9 @@ if SOC_XTENSA_DC233C +config SOC_XTENSA_DC233C + select XTENSA_GEN_HANDLERS + config XTENSA_MMU_NUM_L2_TABLES int default 48 if XTENSA_MMU diff --git a/soc/cdns/dc233c/include/_soc_inthandlers.h b/soc/cdns/dc233c/include/_soc_inthandlers.h deleted file mode 100644 index 96bdf2146f8621..00000000000000 --- a/soc/cdns/dc233c/include/_soc_inthandlers.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. - * - * Functions here are designed to produce efficient code to - * search an Xtensa bitmask of interrupts, inspecting only those bits - * declared to be associated with a given interrupt level. Each - * dispatcher will handle exactly one flagged interrupt, in numerical - * order (low bits first) and will return a mask of that bit that can - * then be cleared by the calling code. Unrecognized bits for the - * level will invoke an error handler. - */ - -#include -#include -#include - -#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 1 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 2 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 3 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 3 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 3 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT21_LEVEL) || XCHAL_INT21_LEVEL != 3 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 4 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 5 -#error core-isa.h interrupt level does not match dispatcher! -#endif -#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 7 -#error core-isa.h interrupt level does not match dispatcher! -#endif - -static inline int _xtensa_handle_one_int1(unsigned int mask) -{ - int irq; - - if (mask & 0x7f) { - if (mask & 0x7) { - if (mask & BIT(0)) { - mask = BIT(0); - irq = 0; - goto handle_irq; - } - if (mask & BIT(1)) { - mask = BIT(1); - irq = 1; - goto handle_irq; - } - if (mask & BIT(2)) { - mask = BIT(2); - irq = 2; - goto handle_irq; - } - } else { - if (mask & 0x18) { - if (mask & BIT(3)) { - mask = BIT(3); - irq = 3; - goto handle_irq; - } - if (mask & BIT(4)) { - mask = BIT(4); - irq = 4; - goto handle_irq; - } - } else { - if (mask & BIT(5)) { - mask = BIT(5); - irq = 5; - goto handle_irq; - } - if (mask & BIT(6)) { - mask = BIT(6); - irq = 6; - goto handle_irq; - } - } - } - } else { - if (mask & 0x18080) { - if (mask & BIT(7)) { - mask = BIT(7); - irq = 7; - goto handle_irq; - } - if (mask & BIT(15)) { - mask = BIT(15); - irq = 15; - goto handle_irq; - } - if (mask & BIT(16)) { - mask = BIT(16); - irq = 16; - goto handle_irq; - } - } else { - if (mask & 0x60000) { - if (mask & BIT(17)) { - mask = BIT(17); - irq = 17; - goto handle_irq; - } - if (mask & BIT(18)) { - mask = BIT(18); - irq = 18; - goto handle_irq; - } - } else { - if (mask & BIT(19)) { - mask = BIT(19); - irq = 19; - goto handle_irq; - } - if (mask & BIT(20)) { - mask = BIT(20); - irq = 20; - goto handle_irq; - } - } - } - } - return 0; -handle_irq: - _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); - return mask; -} - -static inline int _xtensa_handle_one_int2(unsigned int mask) -{ - int irq; - - if (mask & BIT(8)) { - mask = BIT(8); - irq = 8; - goto handle_irq; - } - return 0; -handle_irq: - _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); - return mask; -} - -static inline int _xtensa_handle_one_int3(unsigned int mask) -{ - int irq; - - if (mask & 0x600) { - if (mask & BIT(9)) { - mask = BIT(9); - irq = 9; - goto handle_irq; - } - if (mask & BIT(10)) { - mask = BIT(10); - irq = 10; - goto handle_irq; - } - } else { - if (mask & BIT(11)) { - mask = BIT(11); - irq = 11; - goto handle_irq; - } - if (mask & BIT(21)) { - mask = BIT(21); - irq = 21; - goto handle_irq; - } - } - return 0; -handle_irq: - _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); - return mask; -} - -static inline int _xtensa_handle_one_int4(unsigned int mask) -{ - int irq; - - if (mask & BIT(12)) { - mask = BIT(12); - irq = 12; - goto handle_irq; - } - return 0; -handle_irq: - _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); - return mask; -} - -static inline int _xtensa_handle_one_int5(unsigned int mask) -{ - int irq; - - if (mask & BIT(13)) { - mask = BIT(13); - irq = 13; - goto handle_irq; - } - return 0; -handle_irq: - _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); - return mask; -} - -static inline int _xtensa_handle_one_int7(unsigned int mask) -{ - int irq; - - if (mask & BIT(14)) { - mask = BIT(14); - irq = 14; - goto handle_irq; - } - return 0; -handle_irq: - _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); - return mask; -} - -static inline int _xtensa_handle_one_int0(unsigned int mask) -{ - return 0; -} -static inline int _xtensa_handle_one_int6(unsigned int mask) -{ - return 0; -} From b7130f450f011e0bb4f1ec72637ea38a33466d07 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1023/1389] arch: riscv: Add support for stack unwind without fp Add a stack unwind implementation that only uses `sp` Signed-off-by: Yong Cong Sin --- arch/riscv/Kconfig | 1 - arch/riscv/core/fatal.c | 69 +++++++++++++++----- tests/arch/common/stack_unwind/testcase.yaml | 13 +++- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 77d1c7aa53adc3..965ff4e3f8d3c8 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -50,7 +50,6 @@ config RISCV_ENABLE_FRAME_POINTER config RISCV_EXCEPTION_STACK_TRACE bool default y - depends on RISCV_ENABLE_FRAME_POINTER depends on EXCEPTION_STACK_TRACE imply THREAD_STACK_INFO help diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 07809c488aaaed..47abb7c0977017 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -28,6 +28,27 @@ static const struct z_exc_handle exceptions[] = { #define NO_REG " " #endif +static inline uintptr_t get_sp(const z_arch_esf_t *esf) +{ + /* + * Kernel stack pointer prior this exception i.e. before + * storing the exception stack frame. + */ + uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t); + +#ifdef CONFIG_USERSPACE + if ((esf->mstatus & MSTATUS_MPP) == PRV_U) { + /* + * Exception happened in user space: + * consider the saved user stack instead. + */ + sp = esf->sp; + } +#endif + + return sp; +} + #ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE #define MAX_STACK_FRAMES 8 @@ -75,6 +96,7 @@ static inline bool in_text_region(uintptr_t addr) return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end); } +#ifdef CONFIG_RISCV_ENABLE_FRAME_POINTER static void unwind_stack(const z_arch_esf_t *esf) { uintptr_t fp = esf->s0; @@ -103,6 +125,36 @@ static void unwind_stack(const z_arch_esf_t *esf) LOG_ERR(""); } +#else /* !CONFIG_RISCV_ENABLE_FRAME_POINTER */ +static void unwind_stack(const z_arch_esf_t *esf) +{ + uintptr_t sp = get_sp(esf); + uintptr_t ra; + uintptr_t *ksp = (uintptr_t *)sp; + + if (esf == NULL) { + return; + } + + LOG_ERR("call trace:"); + + for (int i = 0; + (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && in_stack_bound((uintptr_t)ksp); + ksp++) { + ra = *ksp; + if (in_text_region(ra)) { + LOG_ERR(" %2d: sp: " PR_REG " ra: " PR_REG, i, (uintptr_t)ksp, ra); + /* + * Increment the iterator only if `ra` is within the text region to get the + * most out of it + */ + i++; + } + } + + LOG_ERR(""); +} +#endif /* CONFIG_RISCV_ENABLE_FRAME_POINTER */ #endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason, @@ -116,12 +168,6 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { - /* - * Kernel stack pointer prior this exception i.e. before - * storing the exception stack frame. - */ - uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t); - LOG_ERR(" a0: " PR_REG " t0: " PR_REG, esf->a0, esf->t0); LOG_ERR(" a1: " PR_REG " t1: " PR_REG, esf->a1, esf->t1); LOG_ERR(" a2: " PR_REG " t2: " PR_REG, esf->a2, esf->t2); @@ -136,16 +182,7 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf LOG_ERR(" a6: " PR_REG " t6: " PR_REG, esf->a6, esf->t6); LOG_ERR(" a7: " PR_REG, esf->a7); #endif /* CONFIG_RISCV_ISA_RV32E */ -#ifdef CONFIG_USERSPACE - if ((esf->mstatus & MSTATUS_MPP) == 0) { - /* - * Exception happened in user space: - * consider the saved user stack instead. - */ - sp = esf->sp; - } -#endif - LOG_ERR(" sp: " PR_REG, sp); + LOG_ERR(" sp: " PR_REG, get_sp(esf)); LOG_ERR(" ra: " PR_REG, esf->ra); LOG_ERR(" mepc: " PR_REG, esf->mepc); LOG_ERR("mstatus: " PR_REG, esf->mstatus); diff --git a/tests/arch/common/stack_unwind/testcase.yaml b/tests/arch/common/stack_unwind/testcase.yaml index b935b5c596e1d3..9f29790f95cdf9 100644 --- a/tests/arch/common/stack_unwind/testcase.yaml +++ b/tests/arch/common/stack_unwind/testcase.yaml @@ -4,7 +4,7 @@ common: ignore_qemu_crash: true tags: kernel tests: - arch.common.stack_unwind.riscv: + arch.common.stack_unwind.riscv_fp: arch_allow: riscv integration_platforms: - qemu_riscv32 @@ -16,6 +16,17 @@ tests: - "E: call trace:" - "E: 0: fp: \\w+ ra: \\w+" - "E: 1: fp: \\w+ ra: \\w+" + arch.common.stack_unwind.riscv_sp: + arch_allow: riscv + integration_platforms: + - qemu_riscv32 + - qemu_riscv64 + harness_config: + type: multi_line + regex: + - "E: call trace:" + - "E: 0: sp: \\w+ ra: \\w+" + - "E: 1: sp: \\w+ ra: \\w+" arch.common.stack_unwind.x86: arch_allow: x86 extra_configs: From 9295b188218379eceb802b981ae413fb771f1d49 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1024/1389] arch: riscv: relocate stack unwinding code into a separate file Declutter `fatal.c` by moving the stack unwinding logic into `stacktrace.c` and guard its compilation with `CMakeLists.txt`. Signed-off-by: Yong Cong Sin --- arch/riscv/core/CMakeLists.txt | 1 + arch/riscv/core/fatal.c | 121 +++---------------------------- arch/riscv/core/stacktrace.c | 126 +++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 113 deletions(-) create mode 100644 arch/riscv/core/stacktrace.c diff --git a/arch/riscv/core/CMakeLists.txt b/arch/riscv/core/CMakeLists.txt index 1d8daac060c26b..7ffcffd65c83f2 100644 --- a/arch/riscv/core/CMakeLists.txt +++ b/arch/riscv/core/CMakeLists.txt @@ -25,4 +25,5 @@ zephyr_library_sources_ifdef(CONFIG_RISCV_PMP pmp.c pmp.S) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) +zephyr_library_sources_ifdef(CONFIG_RISCV_EXCEPTION_STACK_TRACE stacktrace.c) zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld) diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 47abb7c0977017..8efffd37371937 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -28,7 +28,10 @@ static const struct z_exc_handle exceptions[] = { #define NO_REG " " #endif -static inline uintptr_t get_sp(const z_arch_esf_t *esf) +/* Stack trace function */ +void z_riscv_unwind_stack(const z_arch_esf_t *esf); + +uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf) { /* * Kernel stack pointer prior this exception i.e. before @@ -49,114 +52,6 @@ static inline uintptr_t get_sp(const z_arch_esf_t *esf) return sp; } -#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE -#define MAX_STACK_FRAMES 8 - -struct stackframe { - uintptr_t fp; - uintptr_t ra; -}; - -static bool in_stack_bound(uintptr_t addr) -{ -#ifdef CONFIG_THREAD_STACK_INFO - uintptr_t start, end; - - if (_current == NULL || arch_is_in_isr()) { - /* We were servicing an interrupt */ - int cpu_id; - -#ifdef CONFIG_SMP - cpu_id = arch_curr_cpu()->id; -#else - cpu_id = 0; -#endif - - start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); - end = start + CONFIG_ISR_STACK_SIZE; -#ifdef CONFIG_USERSPACE - /* TODO: handle user threads */ -#endif - } else { - start = _current->stack_info.start; - end = Z_STACK_PTR_ALIGN(_current->stack_info.start + _current->stack_info.size); - } - - return (addr >= start) && (addr < end); -#else - ARG_UNUSED(addr); - return true; -#endif /* CONFIG_THREAD_STACK_INFO */ -} - -static inline bool in_text_region(uintptr_t addr) -{ - extern uintptr_t __text_region_start, __text_region_end; - - return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end); -} - -#ifdef CONFIG_RISCV_ENABLE_FRAME_POINTER -static void unwind_stack(const z_arch_esf_t *esf) -{ - uintptr_t fp = esf->s0; - uintptr_t ra; - struct stackframe *frame; - - if (esf == NULL) { - return; - } - - LOG_ERR("call trace:"); - - for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp);) { - frame = (struct stackframe *)fp - 1; - ra = frame->ra; - if (in_text_region(ra)) { - LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, fp, ra); - /* - * Increment the iterator only if `ra` is within the text region to get the - * most out of it - */ - i++; - } - fp = frame->fp; - } - - LOG_ERR(""); -} -#else /* !CONFIG_RISCV_ENABLE_FRAME_POINTER */ -static void unwind_stack(const z_arch_esf_t *esf) -{ - uintptr_t sp = get_sp(esf); - uintptr_t ra; - uintptr_t *ksp = (uintptr_t *)sp; - - if (esf == NULL) { - return; - } - - LOG_ERR("call trace:"); - - for (int i = 0; - (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && in_stack_bound((uintptr_t)ksp); - ksp++) { - ra = *ksp; - if (in_text_region(ra)) { - LOG_ERR(" %2d: sp: " PR_REG " ra: " PR_REG, i, (uintptr_t)ksp, ra); - /* - * Increment the iterator only if `ra` is within the text region to get the - * most out of it - */ - i++; - } - } - - LOG_ERR(""); -} -#endif /* CONFIG_RISCV_ENABLE_FRAME_POINTER */ -#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ - FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason, const z_arch_esf_t *esf) { @@ -182,7 +77,7 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf LOG_ERR(" a6: " PR_REG " t6: " PR_REG, esf->a6, esf->t6); LOG_ERR(" a7: " PR_REG, esf->a7); #endif /* CONFIG_RISCV_ISA_RV32E */ - LOG_ERR(" sp: " PR_REG, get_sp(esf)); + LOG_ERR(" sp: " PR_REG, z_riscv_get_sp_before_exc(esf)); LOG_ERR(" ra: " PR_REG, esf->ra); LOG_ERR(" mepc: " PR_REG, esf->mepc); LOG_ERR("mstatus: " PR_REG, esf->mstatus); @@ -204,9 +99,9 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf LOG_ERR(""); } -#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE - unwind_stack(esf); -#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ + if (IS_ENABLED(CONFIG_RISCV_EXCEPTION_STACK_TRACE)) { + z_riscv_unwind_stack(esf); + } #endif /* CONFIG_EXCEPTION_DEBUG */ z_fatal_error(reason, esf); diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c new file mode 100644 index 00000000000000..a85dcfbd82d84e --- /dev/null +++ b/arch/riscv/core/stacktrace.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); + +uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf); + +#if __riscv_xlen == 32 + #define PR_REG "%08" PRIxPTR +#elif __riscv_xlen == 64 + #define PR_REG "%016" PRIxPTR +#endif + +#define MAX_STACK_FRAMES 8 + +struct stackframe { + uintptr_t fp; + uintptr_t ra; +}; + +static bool in_stack_bound(uintptr_t addr) +{ +#ifdef CONFIG_THREAD_STACK_INFO + uintptr_t start, end; + + if (_current == NULL || arch_is_in_isr()) { + /* We were servicing an interrupt */ + int cpu_id; + +#ifdef CONFIG_SMP + cpu_id = arch_curr_cpu()->id; +#else + cpu_id = 0; +#endif + + start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); + end = start + CONFIG_ISR_STACK_SIZE; +#ifdef CONFIG_USERSPACE + /* TODO: handle user threads */ +#endif + } else { + start = _current->stack_info.start; + end = Z_STACK_PTR_ALIGN(_current->stack_info.start + _current->stack_info.size); + } + + return (addr >= start) && (addr < end); +#else + ARG_UNUSED(addr); + return true; +#endif /* CONFIG_THREAD_STACK_INFO */ +} + +static inline bool in_text_region(uintptr_t addr) +{ + extern uintptr_t __text_region_start, __text_region_end; + + return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end); +} + +#ifdef CONFIG_RISCV_ENABLE_FRAME_POINTER +void z_riscv_unwind_stack(const z_arch_esf_t *esf) +{ + uintptr_t fp = esf->s0; + uintptr_t ra; + struct stackframe *frame; + + if (esf == NULL) { + return; + } + + LOG_ERR("call trace:"); + + for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp);) { + frame = (struct stackframe *)fp - 1; + ra = frame->ra; + if (in_text_region(ra)) { + LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, fp, ra); + /* + * Increment the iterator only if `ra` is within the text region to get the + * most out of it + */ + i++; + } + fp = frame->fp; + } + + LOG_ERR(""); +} +#else /* !CONFIG_RISCV_ENABLE_FRAME_POINTER */ +void z_riscv_unwind_stack(const z_arch_esf_t *esf) +{ + uintptr_t sp = z_riscv_get_sp_before_exc(esf); + uintptr_t ra; + uintptr_t *ksp = (uintptr_t *)sp; + + if (esf == NULL) { + return; + } + + LOG_ERR("call trace:"); + + for (int i = 0; + (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && in_stack_bound((uintptr_t)ksp); + ksp++) { + ra = *ksp; + if (in_text_region(ra)) { + LOG_ERR(" %2d: sp: " PR_REG " ra: " PR_REG, i, (uintptr_t)ksp, ra); + /* + * Increment the iterator only if `ra` is within the text region to get the + * most out of it + */ + i++; + } + } + + LOG_ERR(""); +} +#endif /* CONFIG_RISCV_ENABLE_FRAME_POINTER */ From 85d8c3b918892c797e3d1dbc7e8a185317bbe8cc Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1025/1389] drivers: espi: npcx: update espi taf driver This CL updates the read, write, erase, and get_channel_status implementations of NPCX chip. Signed-off-by: Tom Chang --- drivers/espi/espi_npcx.c | 31 +--- drivers/espi/espi_taf_npcx.c | 221 +++++++++++++++++-------- soc/nuvoton/npcx/common/soc_espi_taf.h | 2 + 3 files changed, 165 insertions(+), 89 deletions(-) diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index d7cece4eb07d53..05d7b60e2eafd0 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -363,7 +363,7 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_pckt.len = (((uint16_t)taf_head.tag_hlen & 0xF) << 8) | taf_head.llen; taf_pckt.tag = taf_head.tag_hlen >> 4; - if ((taf_pckt.len == 0) && ((taf_pckt.type & 0xF) == NPCX_ESPI_TAF_REQ_READ)) { + if ((taf_pckt.len == 0) && (taf_pckt.type == NPCX_ESPI_TAF_REQ_READ)) { taf_pckt.len = KB(4); } @@ -372,7 +372,7 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_pckt.addr = sys_cpu_to_be32(taf_addr); /* Get written data if eSPI TAF write */ - if ((taf_pckt.type & 0xF) == NPCX_ESPI_TAF_REQ_WRITE) { + if (taf_pckt.type == NPCX_ESPI_TAF_REQ_WRITE) { roundsize = DIV_ROUND_UP(taf_pckt.len, sizeof(uint32_t)); for (i = 0; i < roundsize; i++) { taf_pckt.src[i] = inst->FLASHRXBUF[2 + i]; @@ -415,27 +415,7 @@ static void espi_bus_flash_rx_isr(const struct device *dev) #endif } } - -static void espi_bus_completion_sent_isr(const struct device *dev) -{ - struct espi_reg *const inst = HAL_INSTANCE(dev); - - /* check that ESPISTS.FLNACS is clear. */ - if (IS_BIT_SET(inst->ESPISTS, NPCX_ESPISTS_FLNACS)) { - LOG_ERR("ESPISTS_FLNACS not clear\r\n"); - } - - /* flash operation is done, Make sure the TAFS transmit buffer is empty */ - if (IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL)) { - LOG_ERR("FLASH_TX_AVAIL not clear\r\n"); - } - - /* In auto mode, release FLASH_NP_FREE here to get next SAF request.*/ - if (IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_SAF_AUTO_READ)) { - inst->FLASHCTL |= BIT(NPCX_FLASHCTL_FLASH_NP_FREE); - } -} -#endif +#endif /* CONFIG_ESPI_FLASH_CHANNEL */ const struct espi_bus_isr espi_bus_isr_tbl[] = { NPCX_ESPI_BUS_INT_ITEM(BERR, espi_bus_err_isr), @@ -447,7 +427,6 @@ const struct espi_bus_isr espi_bus_isr_tbl[] = { #endif #if defined(CONFIG_ESPI_FLASH_CHANNEL) NPCX_ESPI_BUS_INT_ITEM(FLASHRX, espi_bus_flash_rx_isr), - NPCX_ESPI_BUS_INT_ITEM(FLNACS, espi_bus_completion_sent_isr), #endif }; @@ -1416,6 +1395,10 @@ static int espi_npcx_init(const struct device *dev) /* Configure host sub-modules which HW blocks belong to core domain */ npcx_host_init_subs_core_domain(dev, &data->callbacks); +#if defined(CONFIG_ESPI_FLASH_CHANNEL) && defined(CONFIG_ESPI_SAF) + npcx_init_taf(dev, &data->callbacks); +#endif + /* eSPI Bus interrupt installation */ IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), diff --git a/drivers/espi/espi_taf_npcx.c b/drivers/espi/espi_taf_npcx.c index 722b26730e8cda..c1760f7adf9874 100644 --- a/drivers/espi/espi_taf_npcx.c +++ b/drivers/espi/espi_taf_npcx.c @@ -17,6 +17,14 @@ LOG_MODULE_REGISTER(espi_taf, CONFIG_ESPI_LOG_LEVEL); static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(taf_flash)); +enum ESPI_TAF_ERASE_LEN { + NPCX_ESPI_TAF_ERASE_LEN_4KB, + NPCX_ESPI_TAF_ERASE_LEN_32KB, + NPCX_ESPI_TAF_ERASE_LEN_64KB, + NPCX_ESPI_TAF_ERASE_LEN_128KB, + NPCX_ESPI_TAF_ERASE_LEN_MAX, +}; + struct espi_taf_npcx_config { uintptr_t base; uintptr_t mapped_addr; @@ -26,9 +34,19 @@ struct espi_taf_npcx_config { }; struct espi_taf_npcx_data { - sys_slist_t callbacks; + sys_slist_t *callbacks; + const struct device *host_dev; + uint8_t taf_type; + uint8_t taf_tag; + uint32_t address; + uint16_t length; + uint32_t src[16]; + struct k_work work; }; +static struct espi_taf_npcx_data npcx_espi_taf_data; +static struct espi_callback espi_taf_cb; + #define HAL_INSTANCE(dev) \ ((struct espi_reg *)((const struct espi_taf_npcx_config *) \ (dev)->config)->base) @@ -45,6 +63,24 @@ struct espi_taf_npcx_data { GET_FIELD(inst->FLASH_PRTR_HADDR[i], NPCX_FLASH_PRTR_HADDR) \ << GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR)) | 0xFFF; +static void espi_taf_get_pckt(const struct device *dev, struct espi_taf_npcx_data *pckt, + struct espi_event event) +{ + struct espi_taf_pckt *data_ptr; + + data_ptr = (struct espi_taf_pckt *)event.evt_data; + + pckt->taf_type = data_ptr->type; + pckt->length = data_ptr->len; + pckt->taf_tag = data_ptr->tag; + pckt->address = data_ptr->addr; + + if (data_ptr->type == NPCX_ESPI_TAF_REQ_WRITE) { + memcpy(pckt->src, data_ptr->src, sizeof(pckt->src)); + } +} + +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) /* Check access region of read request is protected or not */ static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, uint32_t len, uint8_t tag) @@ -73,6 +109,7 @@ static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, return false; } +#endif /* Check access region of write request is protected or not */ static bool espi_taf_check_write_protect(const struct device *dev, uint32_t addr, @@ -107,11 +144,16 @@ static int espi_taf_npcx_configure(const struct device *dev, const struct espi_s { struct espi_reg *const inst = HAL_INSTANCE(dev); + if (cfg->nflash_devices == 0U) { + return -EINVAL; + } + #if defined(CONFIG_ESPI_TAF_AUTO_MODE) inst->FLASHCTL |= BIT(NPCX_FLASHCTL_SAF_AUTO_READ); #else inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_SAF_AUTO_READ); #endif + return 0; } @@ -173,10 +215,17 @@ static int espi_taf_npcx_activate(const struct device *dev) static bool espi_taf_npcx_channel_ready(const struct device *dev) { struct espi_reg *const inst = HAL_INSTANCE(dev); + uint8_t ret = + GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLCAPA) & NPCX_FLASH_SHARING_CAP_SUPP_TAF; - if (!IS_BIT_SET(inst->ESPICFG, NPCX_ESPICFG_FLCHANMODE)) { + if (ret != NPCX_FLASH_SHARING_CAP_SUPP_TAF) { return false; } + + if (!device_is_ready(spi_dev)) { + return false; + } + return true; } @@ -214,52 +263,58 @@ static void taf_release_flash_np_free(const struct device *dev) inst->FLASHCTL = tmp; } -static int taf_npcx_completion_handler(const struct device *dev, uint32_t *buffer) +static int taf_npcx_completion_handler(const struct device *dev, uint8_t type, uint8_t tag, + uint16_t len, uint32_t *buffer) { - uint16_t size = DIV_ROUND_UP((uint8_t)(buffer[0]) + 1, sizeof(uint32_t)); struct espi_reg *const inst = HAL_INSTANCE(dev); - struct npcx_taf_head *head = (struct npcx_taf_head *)buffer; - uint8_t i; + struct npcx_taf_head taf_head; + uint16_t i, size; + uint32_t tx_buf[16]; + + taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN + len; + taf_head.type = type; + taf_head.tag_hlen = (tag << 4) | ((len & 0xF00) >> 8); + taf_head.llen = len & 0xFF; + + memcpy(&tx_buf[0], &taf_head, sizeof(struct npcx_taf_head)); + + if (type == CYC_SCS_CMP_WITH_DATA_ONLY || type == CYC_SCS_CMP_WITH_DATA_FIRST || + type == CYC_SCS_CMP_WITH_DATA_MIDDLE || type == CYC_SCS_CMP_WITH_DATA_LAST) { + memcpy(&tx_buf[1], buffer, (uint8_t)(len)); + } /* Check the Flash Access TX Queue is empty by polling * FLASH_TX_AVAIL. */ - if (WAIT_FOR(IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL), - NPCX_FLASH_CHK_TIMEOUT, NULL)) { + if (WAIT_FOR(!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL), + NPCX_FLASH_CHK_TIMEOUT, NULL) == false) { LOG_ERR("Check TX Queue Is Empty Timeout"); return -EBUSY; } - /* Check ESPISTS.FLNACS is clear (no slave completion is detected) */ - if (WAIT_FOR(IS_BIT_SET(inst->ESPISTS, NPCX_ESPISTS_FLNACS), - NPCX_FLASH_CHK_TIMEOUT, NULL)) { - LOG_ERR("Check Slave Completion Timeout"); - return -EBUSY; - } - /* Write packet to FLASHTXBUF */ + size = DIV_ROUND_UP((uint8_t)(tx_buf[0]) + 1, sizeof(uint32_t)); for (i = 0; i < size; i++) { - inst->FLASHTXBUF[i] = buffer[i]; + inst->FLASHTXBUF[i] = tx_buf[i]; } /* Set the FLASHCTL.FLASH_TX_AVAIL bit to 1 to enqueue the packet */ taf_set_flash_c_avail(dev); /* Release FLASH_NP_FREE here to ready get next TAF request */ - if ((head->type != CYC_SCS_CMP_WITH_DATA_FIRST) && - (head->type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) { + if ((type != CYC_SCS_CMP_WITH_DATA_FIRST) && (type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) { taf_release_flash_np_free(dev); } return 0; } +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_packet *pckt) { struct espi_reg *const inst = HAL_INSTANCE(dev); struct espi_taf_npcx_config *config = ((struct espi_taf_npcx_config *)(dev)->config); struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; uint8_t cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY; uint32_t total_len = pckt->len; uint32_t len = total_len; @@ -267,7 +322,7 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa uint8_t flash_req_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLASHREQSIZE); uint8_t target_max_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLREQSUP); uint16_t max_read_req = 32 << flash_req_size; - struct npcx_taf_head taf_head; + uint8_t read_buf[64]; int rc; if (flash_req_size > target_max_size) { @@ -297,21 +352,14 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa } do { - data_ptr = (uint8_t *)taf_data_ptr->data; - - taf_head.pkt_len = len + NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = cycle_type; - taf_head.tag_hlen = (taf_data_ptr->tag << 4) | ((len & 0xF00) >> 8); - taf_head.llen = len & 0xFF; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = flash_read(spi_dev, addr, data_ptr + 4, len); + rc = flash_read(spi_dev, addr, &read_buf[0], len); if (rc) { LOG_ERR("flash read fail 0x%x", rc); return -EIO; } - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, cycle_type, taf_data_ptr->tag, len, + (uint32_t *)&read_buf[0]); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -330,12 +378,12 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa return 0; } +#endif static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_packet *pckt) { struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; uint8_t *data_ptr = (uint8_t *)(taf_data_ptr->data); - struct npcx_taf_head taf_head; int rc; if (espi_taf_check_write_protect(dev, pckt->flash_addr, @@ -350,13 +398,8 @@ static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_p return -EIO; } - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_SCS_CMP_WITHOUT_DATA; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0, + NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -367,13 +410,19 @@ static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_p static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_packet *pckt) { + int erase_blk[] = {KB(4), KB(32), KB(64), KB(128)}; struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; uint32_t addr = pckt->flash_addr; - uint32_t len = pckt->len; - struct npcx_taf_head taf_head; + uint32_t len; int rc; + if ((pckt->len < 0) || (pckt->len >= NPCX_ESPI_TAF_ERASE_LEN_MAX)) { + LOG_ERR("Invalid erase block size"); + return -EINVAL; + } + + len = erase_blk[pckt->len]; + if (espi_taf_check_write_protect(dev, addr, len, taf_data_ptr->tag)) { LOG_ERR("Access protection region"); return -EINVAL; @@ -385,13 +434,8 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p return -EIO; } - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_SCS_CMP_WITHOUT_DATA; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0, + NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -402,19 +446,11 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_saf_packet *pckt) { - struct espi_taf_npcx_pckt *taf_data_ptr - = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; - struct npcx_taf_head taf_head; + struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; int rc; - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_UNSCS_CMP_WITHOUT_DATA_ONLY; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_UNSCS_CMP_WITHOUT_DATA_ONLY, taf_data_ptr->tag, + 0x0, NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -423,6 +459,67 @@ static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_s return 0; } +static void espi_taf_work(struct k_work *item) +{ + struct espi_taf_npcx_data *info = CONTAINER_OF(item, struct espi_taf_npcx_data, work); + int ret = 0; + + struct espi_taf_npcx_pckt taf_data; + struct espi_saf_packet pckt_taf; + + pckt_taf.flash_addr = info->address; + pckt_taf.len = info->length; + taf_data.tag = info->taf_tag; + if (info->taf_type == NPCX_ESPI_TAF_REQ_WRITE) { + taf_data.data = (uint8_t *)info->src; + } else { + taf_data.data = NULL; + } + pckt_taf.buf = (uint8_t *)&taf_data; + + switch (info->taf_type) { +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) + case NPCX_ESPI_TAF_REQ_READ: + ret = espi_taf_npcx_flash_read(info->host_dev, &pckt_taf); + break; +#endif + case NPCX_ESPI_TAF_REQ_ERASE: + ret = espi_taf_npcx_flash_erase(info->host_dev, &pckt_taf); + break; + case NPCX_ESPI_TAF_REQ_WRITE: + ret = espi_taf_npcx_flash_write(info->host_dev, &pckt_taf); + break; + } + + if (ret != 0) { + ret = espi_taf_npcx_flash_unsuccess(info->host_dev, &pckt_taf); + } +} + +static void espi_taf_event_handler(const struct device *dev, struct espi_callback *cb, + struct espi_event event) +{ + if ((event.evt_type != ESPI_BUS_SAF_NOTIFICATION) || + (event.evt_details != ESPI_CHANNEL_FLASH)) { + return; + } + + espi_taf_get_pckt(dev, &npcx_espi_taf_data, event); + k_work_submit(&npcx_espi_taf_data.work); +} + +int npcx_init_taf(const struct device *dev, sys_slist_t *callbacks) +{ + espi_init_callback(&espi_taf_cb, espi_taf_event_handler, ESPI_BUS_SAF_NOTIFICATION); + espi_add_callback(dev, &espi_taf_cb); + + npcx_espi_taf_data.host_dev = dev; + npcx_espi_taf_data.callbacks = callbacks; + k_work_init(&npcx_espi_taf_data.work, espi_taf_work); + + return 0; +} + static int espi_taf_npcx_init(const struct device *dev) { struct espi_reg *const inst = HAL_INSTANCE(dev); @@ -444,14 +541,8 @@ static const struct espi_saf_driver_api espi_taf_npcx_driver_api = { .set_protection_regions = espi_taf_npcx_set_pr, .activate = espi_taf_npcx_activate, .get_channel_status = espi_taf_npcx_channel_ready, - .flash_read = espi_taf_npcx_flash_read, - .flash_write = espi_taf_npcx_flash_write, - .flash_erase = espi_taf_npcx_flash_erase, - .flash_unsuccess = espi_taf_npcx_flash_unsuccess, }; -static struct espi_taf_npcx_data npcx_espi_taf_data; - static const struct espi_taf_npcx_config espi_taf_npcx_config = { .base = DT_INST_REG_ADDR(0), .mapped_addr = DT_INST_PROP(0, mapped_addr), diff --git a/soc/nuvoton/npcx/common/soc_espi_taf.h b/soc/nuvoton/npcx/common/soc_espi_taf.h index a8755e080f7594..90b98cbb62d31f 100644 --- a/soc/nuvoton/npcx/common/soc_espi_taf.h +++ b/soc/nuvoton/npcx/common/soc_espi_taf.h @@ -144,6 +144,8 @@ struct npcx_taf_head { uint8_t llen; }; +int npcx_init_taf(const struct device *dev, sys_slist_t *callbacks); + #ifdef __cplusplus } #endif From f91dfe0db7002a17a5071ac18c87d0b730e4e09a Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1026/1389] drivers: espi: npcx: select RING_BUFFER for p80 This CL adds automatic select CONFIG_RING_BUFFER for port 80 multi-byte. Signed-off-by: Tom Chang --- drivers/espi/Kconfig.npcx | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx index 0d0d1202f8e89b..884b5cdd4d9a13 100644 --- a/drivers/espi/Kconfig.npcx +++ b/drivers/espi/Kconfig.npcx @@ -46,6 +46,7 @@ config ESPI_NPCX_BYPASS_CH_ENABLE_FATAL_ERROR config ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE bool "Host can write 1/2/4 bytes of Port80 data in a eSPI transaction" depends on (SOC_SERIES_NPCX9 || SOC_SERIES_NPCX4) && ESPI_PERIPHERAL_DEBUG_PORT_80 + select RING_BUFFER help EC can accept 1/2/4 bytes of Port 80 data written from the Host in an eSPI transaction. From 88b4cc38e023930a11055fc64176186053c9dd10 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1027/1389] board: mimxrt1160_evk: linkserver support add linkserver support for mimxrt1160_evk Signed-off-by: Hake Huang --- boards/nxp/mimxrt1160_evk/board.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards/nxp/mimxrt1160_evk/board.cmake b/boards/nxp/mimxrt1160_evk/board.cmake index e9c7d7ea8c7e52..08c159f552a89f 100644 --- a/boards/nxp/mimxrt1160_evk/board.cmake +++ b/boards/nxp/mimxrt1160_evk/board.cmake @@ -7,6 +7,7 @@ if(CONFIG_SOC_MIMXRT1166_CM7 OR CONFIG_SECOND_CORE_MCUX) board_runner_args(pyocd "--target=mimxrt1160_cm7") board_runner_args(jlink "--device=MIMXRT1166xxx6_M7" "--reset-after-load") +board_runner_args(linkserver "--device=MIMXRT1166xxxxx:MIMXRT1160-EVK") elseif(CONFIG_SOC_MIMXRT1166_CM4) board_runner_args(pyocd "--target=mimxrt1160_cm4") # Note: Please use JLINK above V7.50 (Only support run cm4 image when debugging due to default boot core on board is cm7 core) @@ -14,4 +15,5 @@ board_runner_args(jlink "--device=MIMXRT1166xxx6_M4") endif() include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) From cfe1fcf46b2ae338848fc529b475c741363c78a5 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1028/1389] doc: mimxrt1160_evk: update board document for linkserver add linkserver in supported debugger Signed-off-by: Hake Huang --- boards/nxp/mimxrt1160_evk/doc/index.rst | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/boards/nxp/mimxrt1160_evk/doc/index.rst b/boards/nxp/mimxrt1160_evk/doc/index.rst index 861f0a3098a467..44362f44e204b8 100644 --- a/boards/nxp/mimxrt1160_evk/doc/index.rst +++ b/boards/nxp/mimxrt1160_evk/doc/index.rst @@ -267,10 +267,8 @@ however the :ref:`pyocd-debug-host-tools` do not yet support programming the external flashes on this board so you must reconfigure the board for one of the following debug probes instead. -.. _Using J-Link RT1160: - Using J-Link ---------------------------------- +------------ Install the :ref:`jlink-debug-host-tools` and make sure they are in your search path. @@ -279,6 +277,16 @@ There are two options: the onboard debug circuit can be updated with Segger J-Link firmware, or :ref:`jlink-external-debug-probe` can be attached to the EVK. See `Using J-Link with MIMXRT1160-EVK or MIMXRT1170-EVK`_ for more details. +Using LinkServer +---------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the default CMSIS-DAP firmware included in +the on-board debugger. + +Linkserver is the default runner. You may also se the ``-r linkserver`` option +with West to use the LinkServer runner. + Configuring a Console ===================== From 0c67c07635266aed1a4964260b8d42a3fbd51ef9 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Sun, 26 May 2024 22:39:21 +0200 Subject: [PATCH 1029/1389] mgmt: mcumgr: transport: Add missing net include file Adds a missing network include file which was causing an undefined function build failure, likely caused by a recent change affecting includes in other header files Signed-off-by: Jamie McCrae --- subsys/mgmt/mcumgr/transport/src/smp_udp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/mgmt/mcumgr/transport/src/smp_udp.c b/subsys/mgmt/mcumgr/transport/src/smp_udp.c index 7daedb861c3e3b..4e47ac8ab117b1 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_udp.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_udp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include From 68dd19e71c28ac1fe003839c05f1e41692c8d49d Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1030/1389] driver: watchdog: npcx: support longer watchdog timeout In the current driver, the longest time of the watchdog timeout is ~8 seconds because the pre-scalar is fixed at 32 (WDCP=5). This commit removes this limitation by dynamically calculating the pre-scalar according to the watchdog timeout setting from the API. Signed-off-by: Jun Lin Signed-off-by: Tom Chang --- drivers/watchdog/Kconfig.npcx | 11 +++++----- drivers/watchdog/wdt_npcx.c | 39 ++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/drivers/watchdog/Kconfig.npcx b/drivers/watchdog/Kconfig.npcx index 8d25067be8c224..864208b49fe082 100644 --- a/drivers/watchdog/Kconfig.npcx +++ b/drivers/watchdog/Kconfig.npcx @@ -12,12 +12,11 @@ config WDT_NPCX processors. Say y if you wish to use watchdog on NPCX MCU. -config WDT_NPCX_DELAY_CYCLES - int "Number of delay cycles before generating watchdog event/signal" +config WDT_NPCX_WARNING_LEADING_TIME_MS + int "Milliseconds before generating watchdog event/signal" depends on WDT_NPCX - range 1 255 - default 10 + default 500 help This option defines the window in which a watchdog event must be - handled, in units of 31ms. After this time window, the watchdog reset - triggers immediately. + handled. After this time window, the watchdog reset triggers + immediately. diff --git a/drivers/watchdog/wdt_npcx.c b/drivers/watchdog/wdt_npcx.c index 482bbd1c7334bf..31aadd86345a16 100644 --- a/drivers/watchdog/wdt_npcx.c +++ b/drivers/watchdog/wdt_npcx.c @@ -46,10 +46,13 @@ LOG_MODULE_REGISTER(wdt_npcx, CONFIG_WDT_LOG_LEVEL); #define NPCX_WDT_CLK LFCLK /* - * Maximum watchdog window time. Since the watchdog counter is 8-bits, maximum - * time supported by npcx watchdog is 256 * (32 * 32) / 32768 = 8 sec. + * Maximum watchdog window time. Keep the timer and watchdog clock prescaler + * (TWCP) to 0x5. Since the watchdog counter is 8-bits, maximum time supported + * by npcx watchdog is 256 * (32 * 32768) / 32768 = 8192 sec. + * The maximum time supported of T0OUT is 65536 * 32 / 32768 = 64 sec. + * Thus, the maximum time of watchdog set here is 64 sec. */ -#define NPCX_WDT_MAX_WND_TIME 8000UL +#define NPCX_WDT_MAX_WND_TIME 64000UL /* * Minimum watchdog window time. Ensure we have waited at least 3 watchdog @@ -139,7 +142,7 @@ static void wdt_t0out_isr(const struct device *dev, struct npcx_wui *wui) ARG_UNUSED(wui); LOG_DBG("WDT reset will issue after %d delay cycle! WUI(%d %d %d)", - CONFIG_WDT_NPCX_DELAY_CYCLES, wui->table, wui->group, wui->bit); + CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS, wui->table, wui->group, wui->bit); /* Handle watchdog event here. */ if (data->cb) { @@ -208,6 +211,9 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options) struct twd_reg *const inst = HAL_INSTANCE(dev); const struct wdt_npcx_config *const config = dev->config; struct wdt_npcx_data *const data = dev->data; + uint32_t wd_cnt, pre_scal; + uint8_t wdcp; + int rv; /* Disable irq of t0-out expired event first */ @@ -242,9 +248,24 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options) inst->TWDT0 = MAX(DIV_ROUND_UP(data->timeout * NPCX_WDT_CLK, 32 * 1000) - 1, 1); - /* Configure 8-bit watchdog counter */ - inst->WDCNT = MIN(DIV_ROUND_UP(data->timeout, 32) + - CONFIG_WDT_NPCX_DELAY_CYCLES, 0xff); + /* Configure 8-bit watchdog counter + * Change the prescaler of watchdog clock for larger timeout + */ + wd_cnt = DIV_ROUND_UP((data->timeout + CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS) * + NPCX_WDT_CLK, + 32 * 1000); + + pre_scal = DIV_ROUND_UP(wd_cnt, 255); + + /* + * Find the smallest power of 2 greater than or equal to the + * prescaler + */ + wdcp = LOG2(pre_scal - 1) + 1; + pre_scal = 1 << wdcp; + + inst->WDCP = wdcp; + inst->WDCNT = wd_cnt / pre_scal; LOG_DBG("WDT setup: TWDT0, WDCNT are %d, %d", inst->TWDT0, inst->WDCNT); @@ -265,12 +286,14 @@ static int wdt_npcx_disable(const struct device *dev) const struct wdt_npcx_config *const config = dev->config; struct wdt_npcx_data *const data = dev->data; struct twd_reg *const inst = HAL_INSTANCE(dev); + uint16_t min_wnd_t; /* * Ensure we have waited at least 3 watchdog ticks before * stopping watchdog */ - while (k_uptime_get() - data->last_watchdog_touch < NPCX_WDT_MIN_WND_TIME) { + min_wnd_t = DIV_ROUND_UP(3 * NPCX_WDT_CLK, 32 * (1 << inst->WDCP)); + while (k_uptime_get() - data->last_watchdog_touch < min_wnd_t) { continue; } From b1e33f27056134432f1717adbec2e25b31ea30e6 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1031/1389] doc: releases: Add npcx watchdog driver related notes Add release note and migration guide for npcx watchdog driver in 3.7 release. Signed-off-by: Jun Lin --- doc/releases/migration-guide-3.7.rst | 10 ++++++++++ doc/releases/release-notes-3.7.rst | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 3222d6ad9c04ac..280f28370c2104 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -286,6 +286,16 @@ regulator has been removed, users should remove this property from their devicetree if it is present. (:github:`70642`) +Watchdog +======== + +* The ``nuvoton,npcx-watchdog`` driver has been changed to extend the max timeout period. + The time of one watchdog count varies with the different pre-scalar settings. + Removed :kconfig:option:`CONFIG_WDT_NPCX_DELAY_CYCLES` because it is no longer suitable to + set the leading warning time. + Instead, added the :kconfig:option:`CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS` to set + the leading warning time in milliseconds. + Bluetooth ********* diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index b2b72c14c79690..b460b1c13bd6d8 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -274,6 +274,11 @@ Drivers and Sensors * W1 +* Watchdog + + * Added :kconfig:option:`CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS` to set the leading warning time + in milliseconds. Removed no longer used :kconfig:option:`CONFIG_WDT_NPCX_DELAY_CYCLES`. + * Wi-Fi * Added support for configuring RTS threshold. With this, users can set the RTS threshold value or From a204a39c41c7e06e6ebf96da39eeb737cfcf1922 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1032/1389] dts: infineon: port infineon CAT1A (psoc6) to HWMv2 port infineon CAT1A (psoc6) to HWMv2: 1. move dts\arm\cypress\** to dts\arm\infineon\cat1a\legacy 2. remove dts\arm\cypress\** 3. rename dts\arm\infineon\psoc6 to dts\arm\infineon\cat1a Signed-off-by: Nazar Palamar --- .../cat1a/legacy}/pinctrl_cypress_psoc6.h | 0 .../cat1a/legacy}/psoc6-pinctrl.dtsi | 0 .../cat1a/legacy}/psoc6.dtsi | 0 .../cat1a/legacy}/psoc6_cm0.dtsi | 2 +- .../cat1a/legacy}/psoc6_cm4.dtsi | 2 +- .../mpns/CY8C6016BZI_F04.dtsi | 0 .../mpns/CY8C6036BZI_F04.dtsi | 0 .../mpns/CY8C6116BZI_F54.dtsi | 0 .../mpns/CY8C6117BZI_F34.dtsi | 0 .../mpns/CY8C6117FDI_F02.dtsi | 0 .../{psoc6 => cat1a}/mpns/CY8C6117WI_F34.dtsi | 0 .../mpns/CY8C6136BZI_F14.dtsi | 0 .../mpns/CY8C6136BZI_F34.dtsi | 0 .../mpns/CY8C6136FDI_F42.dtsi | 0 .../mpns/CY8C6136FTI_F42.dtsi | 0 .../mpns/CY8C6137BZI_F14.dtsi | 0 .../mpns/CY8C6137BZI_F34.dtsi | 0 .../mpns/CY8C6137BZI_F54.dtsi | 0 .../mpns/CY8C6137FDI_F02.dtsi | 0 .../{psoc6 => cat1a}/mpns/CY8C6137WI_F54.dtsi | 0 .../mpns/CY8C6144AZI_S4F12.dtsi | 0 .../mpns/CY8C6144AZI_S4F62.dtsi | 0 .../mpns/CY8C6144AZI_S4F82.dtsi | 0 .../mpns/CY8C6144AZI_S4F83.dtsi | 0 .../mpns/CY8C6144AZI_S4F92.dtsi | 0 .../mpns/CY8C6144AZI_S4F93.dtsi | 0 .../mpns/CY8C6144LQI_S4F12.dtsi | 0 .../mpns/CY8C6144LQI_S4F62.dtsi | 0 .../mpns/CY8C6144LQI_S4F82.dtsi | 0 .../mpns/CY8C6144LQI_S4F92.dtsi | 0 .../mpns/CY8C6145AZI_S3F02.dtsi | 0 .../mpns/CY8C6145AZI_S3F12.dtsi | 0 .../mpns/CY8C6145AZI_S3F42.dtsi | 0 .../mpns/CY8C6145AZI_S3F62.dtsi | 0 .../mpns/CY8C6145AZI_S3F72.dtsi | 0 .../mpns/CY8C6145FNI_S3F11.dtsi | 0 .../mpns/CY8C6145FNI_S3F41.dtsi | 0 .../mpns/CY8C6145FNI_S3F71.dtsi | 0 .../mpns/CY8C6145LQI_S3F02.dtsi | 0 .../mpns/CY8C6145LQI_S3F12.dtsi | 0 .../mpns/CY8C6145LQI_S3F42.dtsi | 0 .../mpns/CY8C6145LQI_S3F62.dtsi | 0 .../mpns/CY8C6145LQI_S3F72.dtsi | 0 .../mpns/CY8C6148AZI_S2F44.dtsi | 0 .../mpns/CY8C6148BZI_S2F44.dtsi | 0 .../mpns/CY8C6148FNI_S2F43.dtsi | 0 .../mpns/CY8C6148LQI_S2F02.dtsi | 0 .../mpns/CY8C6148LQI_S2F42.dtsi | 0 .../mpns/CY8C614AAZI_S2F04.dtsi | 0 .../mpns/CY8C614AAZI_S2F14.dtsi | 0 .../mpns/CY8C614AAZI_S2F44.dtsi | 0 .../mpns/CY8C614ABZI_S2F04.dtsi | 0 .../mpns/CY8C614ABZI_S2F44.dtsi | 0 .../mpns/CY8C614AFNI_S2F03.dtsi | 0 .../mpns/CY8C614AFNI_S2F43.dtsi | 0 .../mpns/CY8C614ALQI_S2F02.dtsi | 0 .../mpns/CY8C614ALQI_S2F42.dtsi | 0 .../mpns/CY8C6244AZI_S4D12.dtsi | 0 .../mpns/CY8C6244AZI_S4D62.dtsi | 0 .../mpns/CY8C6244AZI_S4D82.dtsi | 0 .../mpns/CY8C6244AZI_S4D83.dtsi | 0 .../mpns/CY8C6244AZI_S4D92.dtsi | 0 .../mpns/CY8C6244AZI_S4D93.dtsi | 0 .../mpns/CY8C6244LQI_S4D12.dtsi | 0 .../mpns/CY8C6244LQI_S4D62.dtsi | 0 .../mpns/CY8C6244LQI_S4D82.dtsi | 0 .../mpns/CY8C6244LQI_S4D92.dtsi | 0 .../mpns/CY8C6245AZI_S3D02.dtsi | 0 .../mpns/CY8C6245AZI_S3D12.dtsi | 0 .../mpns/CY8C6245AZI_S3D42.dtsi | 0 .../mpns/CY8C6245AZI_S3D62.dtsi | 0 .../mpns/CY8C6245AZI_S3D72.dtsi | 0 .../mpns/CY8C6245FNI_S3D11.dtsi | 0 .../mpns/CY8C6245FNI_S3D41.dtsi | 0 .../mpns/CY8C6245FNI_S3D71.dtsi | 0 .../mpns/CY8C6245LQI_S3D02.dtsi | 0 .../mpns/CY8C6245LQI_S3D12.dtsi | 0 .../mpns/CY8C6245LQI_S3D42.dtsi | 0 .../mpns/CY8C6245LQI_S3D62.dtsi | 0 .../mpns/CY8C6245LQI_S3D72.dtsi | 0 .../mpns/CY8C6246BZI_D04.dtsi | 0 .../mpns/CY8C6247BFI_D54.dtsi | 0 .../mpns/CY8C6247BZI_AUD54.dtsi | 0 .../mpns/CY8C6247BZI_D34.dtsi | 0 .../mpns/CY8C6247BZI_D44.dtsi | 0 .../mpns/CY8C6247BZI_D54.dtsi | 0 .../mpns/CY8C6247FDI_D02.dtsi | 0 .../mpns/CY8C6247FDI_D32.dtsi | 0 .../mpns/CY8C6247FDI_D52.dtsi | 0 .../mpns/CY8C6247FTI_D52.dtsi | 0 .../{psoc6 => cat1a}/mpns/CY8C6247WI_D54.dtsi | 0 .../mpns/CY8C6248AZI_S2D14.dtsi | 0 .../mpns/CY8C6248AZI_S2D44.dtsi | 0 .../mpns/CY8C6248BZI_S2D44.dtsi | 0 .../mpns/CY8C6248FNI_S2D43.dtsi | 0 .../mpns/CY8C6248LQI_S2D02.dtsi | 0 .../mpns/CY8C6248LQI_S2D42.dtsi | 0 .../mpns/CY8C624AAZI_S2D14.dtsi | 0 .../mpns/CY8C624AAZI_S2D44.dtsi | 0 .../mpns/CY8C624ABZI_D44.dtsi | 0 .../mpns/CY8C624ABZI_S2D04.dtsi | 0 .../mpns/CY8C624ABZI_S2D14.dtsi | 0 .../mpns/CY8C624ABZI_S2D44.dtsi | 0 .../mpns/CY8C624ABZI_S2D44A0.dtsi | 0 .../mpns/CY8C624AFNI_S2D43.dtsi | 0 .../mpns/CY8C624ALQI_S2D02.dtsi | 0 .../mpns/CY8C624ALQI_S2D42.dtsi | 0 .../mpns/CY8C6316BZI_BLF03.dtsi | 0 .../mpns/CY8C6316BZI_BLF04.dtsi | 0 .../mpns/CY8C6316BZI_BLF53.dtsi | 0 .../mpns/CY8C6316BZI_BLF54.dtsi | 0 .../mpns/CY8C6336BZI_BLD13.dtsi | 0 .../mpns/CY8C6336BZI_BLD14.dtsi | 0 .../mpns/CY8C6336BZI_BLF03.dtsi | 0 .../mpns/CY8C6336BZI_BLF04.dtsi | 0 .../mpns/CY8C6336BZI_BUD13.dtsi | 0 .../mpns/CY8C6336LQI_BLF02.dtsi | 0 .../mpns/CY8C6336LQI_BLF42.dtsi | 0 .../mpns/CY8C6337BZI_BLF13.dtsi | 0 .../mpns/CY8C6347BZI_BLD33.dtsi | 0 .../mpns/CY8C6347BZI_BLD34.dtsi | 0 .../mpns/CY8C6347BZI_BLD43.dtsi | 0 .../mpns/CY8C6347BZI_BLD44.dtsi | 0 .../mpns/CY8C6347BZI_BLD53.dtsi | 0 .../mpns/CY8C6347BZI_BLD54.dtsi | 0 .../mpns/CY8C6347BZI_BUD33.dtsi | 0 .../mpns/CY8C6347BZI_BUD43.dtsi | 0 .../mpns/CY8C6347BZI_BUD53.dtsi | 0 .../mpns/CY8C6347FMI_BLD13.dtsi | 0 .../mpns/CY8C6347FMI_BLD33.dtsi | 0 .../mpns/CY8C6347FMI_BLD43.dtsi | 0 .../mpns/CY8C6347FMI_BLD53.dtsi | 0 .../mpns/CY8C6347FMI_BUD13.dtsi | 0 .../mpns/CY8C6347FMI_BUD33.dtsi | 0 .../mpns/CY8C6347FMI_BUD43.dtsi | 0 .../mpns/CY8C6347FMI_BUD53.dtsi | 0 .../mpns/CY8C6347LQI_BLD52.dtsi | 0 .../mpns/CYB06445LQI_S3D42.dtsi | 0 .../mpns/CYB06447BZI_BLD53.dtsi | 0 .../mpns/CYB06447BZI_BLD54.dtsi | 0 .../mpns/CYB06447BZI_D54.dtsi | 0 .../mpns/CYB0644ABZI_S2D44.dtsi | 0 .../mpns/CYBLE_416045_02.dtsi | 0 .../mpns/CYS0644ABZI_S2D44.dtsi | 0 .../psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi | 0 .../psoc6_01/psoc6_01.104-m-csp-ble.dtsi | 0 .../psoc6_01/psoc6_01.116-bga-ble.dtsi | 0 .../psoc6_01/psoc6_01.116-bga-usb.dtsi | 0 .../psoc6_01/psoc6_01.124-bga-sip.dtsi | 0 .../psoc6_01/psoc6_01.124-bga.dtsi | 0 .../psoc6_01/psoc6_01.43-smt.dtsi | 0 .../psoc6_01/psoc6_01.68-qfn-ble.dtsi | 0 .../psoc6_01/psoc6_01.80-wlcsp.dtsi | 0 .../{psoc6 => cat1a}/psoc6_01/psoc6_01.dtsi | 0 .../psoc6_02/psoc6_02.100-wlcsp.dtsi | 0 .../cat1a/psoc6_02/psoc6_02.124-bga.dtsi | 969 ++++++++++++++++++ .../psoc6_02/psoc6_02.128-tqfp.dtsi | 0 .../psoc6_02/psoc6_02.68-qfn.dtsi | 0 .../{psoc6 => cat1a}/psoc6_02/psoc6_02.dtsi | 0 .../psoc6_03/psoc6_03.100-tqfp.dtsi | 0 .../psoc6_03/psoc6_03.49-wlcsp.dtsi | 0 .../psoc6_03/psoc6_03.68-qfn.dtsi | 0 .../{psoc6 => cat1a}/psoc6_03/psoc6_03.dtsi | 0 .../psoc6_04/psoc6_04.64-tqfp-epad.dtsi | 0 .../psoc6_04/psoc6_04.68-qfn.dtsi | 0 .../psoc6_04/psoc6_04.80-tqfp.dtsi | 0 .../{psoc6 => cat1a}/psoc6_04/psoc6_04.dtsi | 0 .../{psoc6 => cat1a}/system_clocks.dtsi | 0 168 files changed, 971 insertions(+), 2 deletions(-) rename dts/arm/{cypress => infineon/cat1a/legacy}/pinctrl_cypress_psoc6.h (100%) rename dts/arm/{cypress => infineon/cat1a/legacy}/psoc6-pinctrl.dtsi (100%) rename dts/arm/{cypress => infineon/cat1a/legacy}/psoc6.dtsi (100%) rename dts/arm/{cypress => infineon/cat1a/legacy}/psoc6_cm0.dtsi (99%) rename dts/arm/{cypress => infineon/cat1a/legacy}/psoc6_cm4.dtsi (84%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6016BZI_F04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6036BZI_F04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6116BZI_F54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6117BZI_F34.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6117FDI_F02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6117WI_F34.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6136BZI_F14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6136BZI_F34.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6136FDI_F42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6136FTI_F42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6137BZI_F14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6137BZI_F34.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6137BZI_F54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6137FDI_F02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6137WI_F54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144AZI_S4F12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144AZI_S4F62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144AZI_S4F82.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144AZI_S4F83.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144AZI_S4F92.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144AZI_S4F93.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144LQI_S4F12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144LQI_S4F62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144LQI_S4F82.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6144LQI_S4F92.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145AZI_S3F02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145AZI_S3F12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145AZI_S3F42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145AZI_S3F62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145AZI_S3F72.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145FNI_S3F11.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145FNI_S3F41.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145FNI_S3F71.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145LQI_S3F02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145LQI_S3F12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145LQI_S3F42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145LQI_S3F62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6145LQI_S3F72.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6148AZI_S2F44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6148BZI_S2F44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6148FNI_S2F43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6148LQI_S2F02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6148LQI_S2F42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614AAZI_S2F04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614AAZI_S2F14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614AAZI_S2F44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614ABZI_S2F04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614ABZI_S2F44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614AFNI_S2F03.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614AFNI_S2F43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614ALQI_S2F02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C614ALQI_S2F42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244AZI_S4D12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244AZI_S4D62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244AZI_S4D82.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244AZI_S4D83.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244AZI_S4D92.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244AZI_S4D93.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244LQI_S4D12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244LQI_S4D62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244LQI_S4D82.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6244LQI_S4D92.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245AZI_S3D02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245AZI_S3D12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245AZI_S3D42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245AZI_S3D62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245AZI_S3D72.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245FNI_S3D11.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245FNI_S3D41.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245FNI_S3D71.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245LQI_S3D02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245LQI_S3D12.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245LQI_S3D42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245LQI_S3D62.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6245LQI_S3D72.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6246BZI_D04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247BFI_D54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247BZI_AUD54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247BZI_D34.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247BZI_D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247BZI_D54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247FDI_D02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247FDI_D32.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247FDI_D52.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247FTI_D52.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6247WI_D54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6248AZI_S2D14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6248AZI_S2D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6248BZI_S2D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6248FNI_S2D43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6248LQI_S2D02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6248LQI_S2D42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624AAZI_S2D14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624AAZI_S2D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ABZI_D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ABZI_S2D04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ABZI_S2D14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ABZI_S2D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ABZI_S2D44A0.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624AFNI_S2D43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ALQI_S2D02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C624ALQI_S2D42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6316BZI_BLF03.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6316BZI_BLF04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6316BZI_BLF53.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6316BZI_BLF54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336BZI_BLD13.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336BZI_BLD14.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336BZI_BLF03.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336BZI_BLF04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336BZI_BUD13.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336LQI_BLF02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6336LQI_BLF42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6337BZI_BLF13.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BLD33.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BLD34.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BLD43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BLD44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BLD53.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BLD54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BUD33.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BUD43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347BZI_BUD53.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BLD13.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BLD33.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BLD43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BLD53.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BUD13.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BUD33.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BUD43.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347FMI_BUD53.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CY8C6347LQI_BLD52.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYB06445LQI_S3D42.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYB06447BZI_BLD53.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYB06447BZI_BLD54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYB06447BZI_D54.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYB0644ABZI_S2D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYBLE_416045_02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/mpns/CYS0644ABZI_S2D44.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.104-m-csp-ble.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.116-bga-ble.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.116-bga-usb.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.124-bga-sip.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.124-bga.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.43-smt.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.68-qfn-ble.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.80-wlcsp.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_01/psoc6_01.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_02/psoc6_02.100-wlcsp.dtsi (100%) create mode 100644 dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_02/psoc6_02.128-tqfp.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_02/psoc6_02.68-qfn.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_02/psoc6_02.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_03/psoc6_03.100-tqfp.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_03/psoc6_03.49-wlcsp.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_03/psoc6_03.68-qfn.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_03/psoc6_03.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_04/psoc6_04.64-tqfp-epad.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_04/psoc6_04.68-qfn.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_04/psoc6_04.80-tqfp.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/psoc6_04/psoc6_04.dtsi (100%) rename dts/arm/infineon/{psoc6 => cat1a}/system_clocks.dtsi (100%) diff --git a/dts/arm/cypress/pinctrl_cypress_psoc6.h b/dts/arm/infineon/cat1a/legacy/pinctrl_cypress_psoc6.h similarity index 100% rename from dts/arm/cypress/pinctrl_cypress_psoc6.h rename to dts/arm/infineon/cat1a/legacy/pinctrl_cypress_psoc6.h diff --git a/dts/arm/cypress/psoc6-pinctrl.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi similarity index 100% rename from dts/arm/cypress/psoc6-pinctrl.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi diff --git a/dts/arm/cypress/psoc6.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6.dtsi similarity index 100% rename from dts/arm/cypress/psoc6.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6.dtsi diff --git a/dts/arm/cypress/psoc6_cm0.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6_cm0.dtsi similarity index 99% rename from dts/arm/cypress/psoc6_cm0.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6_cm0.dtsi index c4221dc1ad0bb7..7a9d44ab17e952 100644 --- a/dts/arm/cypress/psoc6_cm0.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6_cm0.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { cpus { diff --git a/dts/arm/cypress/psoc6_cm4.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6_cm4.dtsi similarity index 84% rename from dts/arm/cypress/psoc6_cm4.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6_cm4.dtsi index c2693b610095be..35e866413c610d 100644 --- a/dts/arm/cypress/psoc6_cm4.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6_cm4.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { cpus { diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6016BZI_F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6016BZI_F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6016BZI_F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6016BZI_F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6036BZI_F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6036BZI_F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6036BZI_F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6036BZI_F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6116BZI_F54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6116BZI_F54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6116BZI_F54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6116BZI_F54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6117BZI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6117BZI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6117BZI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6117BZI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6117FDI_F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6117FDI_F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6117FDI_F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6117FDI_F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6117WI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6117WI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6117WI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6117WI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136FDI_F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136FDI_F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136FDI_F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136FDI_F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136FTI_F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136FTI_F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136FTI_F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136FTI_F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137FDI_F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137FDI_F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137FDI_F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137FDI_F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137WI_F54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137WI_F54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137WI_F54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137WI_F54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F83.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F83.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F83.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F83.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F93.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F93.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F93.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F93.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F11.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F11.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F11.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F11.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F41.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F41.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F41.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F41.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F71.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F71.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F71.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F71.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148AZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148AZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148AZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148AZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148BZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148BZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148BZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148BZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148FNI_S2F43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148FNI_S2F43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148FNI_S2F43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148FNI_S2F43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F03.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F03.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F03.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D83.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D83.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D83.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D83.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D93.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D93.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D93.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D93.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D11.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D11.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D11.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D11.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D41.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D41.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D41.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D41.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D71.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D71.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D71.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D71.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6246BZI_D04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6246BZI_D04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6246BZI_D04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6246BZI_D04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BFI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BFI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BFI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BFI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_AUD54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_AUD54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_AUD54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_AUD54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D32.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D32.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D32.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D32.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D52.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D52.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D52.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D52.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FTI_D52.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FTI_D52.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FTI_D52.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FTI_D52.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247WI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247WI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247WI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247WI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248BZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248BZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248BZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248BZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248FNI_S2D43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248FNI_S2D43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248FNI_S2D43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248FNI_S2D43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44A0.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44A0.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44A0.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44A0.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624AFNI_S2D43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624AFNI_S2D43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624AFNI_S2D43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624AFNI_S2D43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF03.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF03.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF03.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF03.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF03.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF03.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BUD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BUD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BUD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BUD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6337BZI_BLF13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6337BZI_BLF13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6337BZI_BLF13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6337BZI_BLF13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347LQI_BLD52.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347LQI_BLD52.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347LQI_BLD52.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347LQI_BLD52.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06445LQI_S3D42.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06445LQI_S3D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06445LQI_S3D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06445LQI_S3D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD53.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD54.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD54.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06447BZI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06447BZI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06447BZI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06447BZI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB0644ABZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CYB0644ABZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB0644ABZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB0644ABZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYBLE_416045_02.dtsi b/dts/arm/infineon/cat1a/mpns/CYBLE_416045_02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYBLE_416045_02.dtsi rename to dts/arm/infineon/cat1a/mpns/CYBLE_416045_02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYS0644ABZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CYS0644ABZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYS0644ABZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CYS0644ABZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-ble.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-ble.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-ble.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-ble.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-usb.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-usb.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-usb.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-usb.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga-sip.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga-sip.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga-sip.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga-sip.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.43-smt.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.43-smt.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.43-smt.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.43-smt.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.68-qfn-ble.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.68-qfn-ble.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.68-qfn-ble.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.68-qfn-ble.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.80-wlcsp.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.80-wlcsp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.80-wlcsp.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.80-wlcsp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.100-wlcsp.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.100-wlcsp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.100-wlcsp.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.100-wlcsp.dtsi diff --git a/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi new file mode 100644 index 00000000000000..aa1cd9a0c93f71 --- /dev/null +++ b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "psoc6_02.dtsi" + +/ { + soc { + pinctrl: pinctrl@40300000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_i2c_scl: p1_0_scb7_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_scb1_i2c_scl: p2_0_scb1_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_scb9_i2c_scl: p2_4_scb9_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_i2c_scl: p3_0_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb7_i2c_scl: p4_0_scb7_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_i2c_scl: p5_0_scb5_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb10_i2c_scl: p5_4_scb10_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_i2c_scl: p6_0_scb3_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_i2c_scl: p6_0_scb8_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_i2c_scl: p6_4_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_i2c_scl: p6_4_scb8_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_i2c_scl: p7_0_scb4_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_i2c_scl: p8_0_scb4_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb11_i2c_scl: p8_4_scb11_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_i2c_scl: p9_0_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_i2c_scl: p10_0_scb1_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_i2c_scl: p11_0_scb5_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_i2c_scl: p12_0_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_i2c_scl: p13_0_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_scb12_i2c_scl: p13_4_scb12_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_i2c_sda: p1_1_scb7_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_scb1_i2c_sda: p2_1_scb1_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_scb9_i2c_sda: p2_5_scb9_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_i2c_sda: p3_1_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb7_i2c_sda: p4_1_scb7_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_i2c_sda: p5_1_scb5_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb10_i2c_sda: p5_5_scb10_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_i2c_sda: p6_1_scb3_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_i2c_sda: p6_1_scb8_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_i2c_sda: p6_5_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_i2c_sda: p6_5_scb8_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_i2c_sda: p7_1_scb4_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_i2c_sda: p8_1_scb4_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb11_i2c_sda: p8_5_scb11_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_i2c_sda: p9_1_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_i2c_sda: p10_1_scb1_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_i2c_sda: p11_1_scb5_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_i2c_sda: p12_1_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_i2c_sda: p13_1_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_scb12_i2c_sda: p13_5_scb12_i2c_sda { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p0_5_scb0_uart_cts: p0_5_scb0_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb7_uart_cts: p1_3_scb7_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p2_3_scb1_uart_cts: p2_3_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p2_7_scb9_uart_cts: p2_7_scb9_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_cts: p3_3_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_uart_cts: p5_3_scb5_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_scb10_uart_cts: p5_7_scb10_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_uart_cts: p6_3_scb3_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_uart_cts: p6_7_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_uart_cts: p7_3_scb4_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_uart_cts: p8_3_scb4_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_scb11_uart_cts: p8_7_scb11_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_uart_cts: p9_3_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_uart_cts: p10_3_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_uart_cts: p11_3_scb5_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_uart_cts: p12_3_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p13_3_scb6_uart_cts: p13_3_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p13_7_scb12_uart_cts: p13_7_scb12_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p0_4_scb0_uart_rts: p0_4_scb0_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb7_uart_rts: p1_2_scb7_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p2_2_scb1_uart_rts: p2_2_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p2_6_scb9_uart_rts: p2_6_scb9_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rts: p3_2_scb2_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_scb5_uart_rts: p5_2_scb5_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p5_6_scb10_uart_rts: p5_6_scb10_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_uart_rts: p6_2_scb3_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_uart_rts: p6_6_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_uart_rts: p7_2_scb4_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_uart_rts: p8_2_scb4_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_scb11_uart_rts: p8_6_scb11_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_uart_rts: p9_2_scb2_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_uart_rts: p10_2_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_uart_rts: p11_2_scb5_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_uart_rts: p12_2_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p13_2_scb6_uart_rts: p13_2_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p13_6_scb12_uart_rts: p13_6_scb12_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p0_2_scb0_uart_rx: p0_2_scb0_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_uart_rx: p1_0_scb7_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_scb1_uart_rx: p2_0_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_scb9_uart_rx: p2_4_scb9_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_uart_rx: p3_0_scb2_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb7_uart_rx: p4_0_scb7_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_uart_rx: p5_0_scb5_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb10_uart_rx: p5_4_scb10_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_uart_rx: p6_0_scb3_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_uart_rx: p6_4_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_uart_rx: p7_0_scb4_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_uart_rx: p8_0_scb4_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb11_uart_rx: p8_4_scb11_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_uart_rx: p9_0_scb2_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_uart_rx: p10_0_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_uart_rx: p11_0_scb5_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_uart_rx: p12_0_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_uart_rx: p13_0_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_scb12_uart_rx: p13_4_scb12_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p0_3_scb0_uart_tx: p0_3_scb0_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_uart_tx: p1_1_scb7_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_scb1_uart_tx: p2_1_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_scb9_uart_tx: p2_5_scb9_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_tx: p3_1_scb2_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb7_uart_tx: p4_1_scb7_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_uart_tx: p5_1_scb5_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb10_uart_tx: p5_5_scb10_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_uart_tx: p6_1_scb3_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_uart_tx: p6_5_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_uart_tx: p7_1_scb4_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_uart_tx: p8_1_scb4_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb11_uart_tx: p8_5_scb11_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_uart_tx: p9_1_scb2_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_uart_tx: p10_1_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_uart_tx: p11_1_scb5_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_uart_tx: p12_1_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_uart_tx: p13_1_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_scb12_uart_tx: p13_5_scb12_uart_tx { + pinmux = ; + }; + + /* tcpwm_line */ + /omit-if-no-ref/ p0_0_tcpwm0_line: p0_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_0_tcpwm1_line: p0_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_2_tcpwm0_line: p0_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_2_tcpwm1_line: p0_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_tcpwm0_line: p0_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_tcpwm1_line: p0_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_tcpwm0_line: p1_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_tcpwm1_line: p1_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_tcpwm0_line: p1_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_tcpwm1_line: p1_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_4_tcpwm0_line: p1_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_4_tcpwm1_line: p1_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_tcpwm0_line: p2_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_tcpwm1_line: p2_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_2_tcpwm0_line: p2_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_2_tcpwm1_line: p2_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_tcpwm0_line: p2_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_tcpwm1_line: p2_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_6_tcpwm0_line: p2_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_6_tcpwm1_line: p2_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_tcpwm0_line: p3_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_tcpwm1_line: p3_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_tcpwm0_line: p3_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_tcpwm1_line: p3_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_tcpwm0_line: p3_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_tcpwm1_line: p3_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_tcpwm0_line: p4_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_tcpwm1_line: p4_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_tcpwm0_line: p5_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_tcpwm1_line: p5_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_tcpwm0_line: p5_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_tcpwm1_line: p5_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_tcpwm0_line: p5_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_tcpwm1_line: p5_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_6_tcpwm0_line: p5_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_6_tcpwm1_line: p5_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_tcpwm0_line: p6_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_tcpwm1_line: p6_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_tcpwm0_line: p6_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_tcpwm1_line: p6_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_tcpwm0_line: p6_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_tcpwm1_line: p6_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_tcpwm0_line: p6_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_tcpwm1_line: p6_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_tcpwm0_line: p7_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_tcpwm1_line: p7_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_tcpwm0_line: p7_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_tcpwm1_line: p7_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_tcpwm0_line: p7_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_tcpwm1_line: p7_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_tcpwm0_line: p7_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_tcpwm1_line: p7_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_tcpwm0_line: p8_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_tcpwm1_line: p8_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_tcpwm0_line: p8_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_tcpwm1_line: p8_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_tcpwm0_line: p8_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_tcpwm1_line: p8_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_tcpwm0_line: p8_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_tcpwm1_line: p8_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_tcpwm0_line: p9_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_tcpwm1_line: p9_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_tcpwm0_line: p9_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_tcpwm1_line: p9_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_4_tcpwm0_line: p9_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_4_tcpwm1_line: p9_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_6_tcpwm0_line: p9_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_6_tcpwm1_line: p9_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_tcpwm0_line: p10_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_tcpwm1_line: p10_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_tcpwm0_line: p10_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_tcpwm1_line: p10_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_tcpwm0_line: p10_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_tcpwm1_line: p10_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_tcpwm0_line: p10_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_tcpwm1_line: p10_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_tcpwm0_line: p11_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_tcpwm1_line: p11_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_tcpwm0_line: p11_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_tcpwm1_line: p11_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_tcpwm0_line: p11_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_tcpwm1_line: p11_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_tcpwm0_line: p12_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_tcpwm1_line: p12_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_tcpwm0_line: p12_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_tcpwm1_line: p12_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_tcpwm0_line: p12_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_tcpwm1_line: p12_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_6_tcpwm0_line: p12_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_6_tcpwm1_line: p12_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_tcpwm0_line: p13_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_tcpwm1_line: p13_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_2_tcpwm0_line: p13_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_2_tcpwm1_line: p13_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_tcpwm0_line: p13_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_tcpwm1_line: p13_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_6_tcpwm0_line: p13_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_6_tcpwm1_line: p13_6_tcpwm1_line { + pinmux = ; + }; + + /* tcpwm_line_compl */ + /omit-if-no-ref/ p0_1_tcpwm0_line_compl: p0_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_1_tcpwm1_line_compl: p0_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_3_tcpwm0_line_compl: p0_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_3_tcpwm1_line_compl: p0_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_tcpwm0_line_compl: p0_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_tcpwm1_line_compl: p0_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_tcpwm0_line_compl: p1_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_tcpwm1_line_compl: p1_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_tcpwm0_line_compl: p1_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_tcpwm1_line_compl: p1_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_5_tcpwm0_line_compl: p1_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_5_tcpwm1_line_compl: p1_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_tcpwm0_line_compl: p2_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_tcpwm1_line_compl: p2_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_3_tcpwm0_line_compl: p2_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_3_tcpwm1_line_compl: p2_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_tcpwm0_line_compl: p2_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_tcpwm1_line_compl: p2_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_7_tcpwm0_line_compl: p2_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_7_tcpwm1_line_compl: p2_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_tcpwm0_line_compl: p3_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_tcpwm1_line_compl: p3_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_tcpwm0_line_compl: p3_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_tcpwm1_line_compl: p3_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_tcpwm0_line_compl: p3_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_tcpwm1_line_compl: p3_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_tcpwm0_line_compl: p4_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_tcpwm1_line_compl: p4_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_tcpwm0_line_compl: p5_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_tcpwm1_line_compl: p5_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_tcpwm0_line_compl: p5_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_tcpwm1_line_compl: p5_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_tcpwm0_line_compl: p5_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_tcpwm1_line_compl: p5_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_tcpwm0_line_compl: p5_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_tcpwm1_line_compl: p5_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_tcpwm0_line_compl: p6_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_tcpwm1_line_compl: p6_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_tcpwm0_line_compl: p6_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_tcpwm1_line_compl: p6_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_tcpwm0_line_compl: p6_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_tcpwm1_line_compl: p6_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_tcpwm0_line_compl: p6_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_tcpwm1_line_compl: p6_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_tcpwm0_line_compl: p7_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_tcpwm1_line_compl: p7_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_tcpwm0_line_compl: p7_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_tcpwm1_line_compl: p7_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_tcpwm0_line_compl: p7_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_tcpwm1_line_compl: p7_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_tcpwm0_line_compl: p7_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_tcpwm1_line_compl: p7_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_tcpwm0_line_compl: p8_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_tcpwm1_line_compl: p8_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_tcpwm0_line_compl: p8_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_tcpwm1_line_compl: p8_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_tcpwm0_line_compl: p8_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_tcpwm1_line_compl: p8_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_tcpwm0_line_compl: p8_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_tcpwm1_line_compl: p8_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_tcpwm0_line_compl: p9_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_tcpwm1_line_compl: p9_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_tcpwm0_line_compl: p9_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_tcpwm1_line_compl: p9_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_5_tcpwm0_line_compl: p9_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_5_tcpwm1_line_compl: p9_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_7_tcpwm0_line_compl: p9_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_7_tcpwm1_line_compl: p9_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_tcpwm0_line_compl: p10_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_tcpwm1_line_compl: p10_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_tcpwm0_line_compl: p10_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_tcpwm1_line_compl: p10_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_tcpwm0_line_compl: p10_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_tcpwm1_line_compl: p10_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_7_tcpwm0_line_compl: p10_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_7_tcpwm1_line_compl: p10_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_tcpwm0_line_compl: p11_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_tcpwm1_line_compl: p11_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_tcpwm0_line_compl: p11_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_tcpwm1_line_compl: p11_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_tcpwm0_line_compl: p11_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_tcpwm1_line_compl: p11_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_tcpwm0_line_compl: p12_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_tcpwm1_line_compl: p12_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_tcpwm0_line_compl: p12_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_tcpwm1_line_compl: p12_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_5_tcpwm0_line_compl: p12_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_5_tcpwm1_line_compl: p12_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_7_tcpwm0_line_compl: p12_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_7_tcpwm1_line_compl: p12_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_tcpwm0_line_compl: p13_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_tcpwm1_line_compl: p13_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_3_tcpwm0_line_compl: p13_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_3_tcpwm1_line_compl: p13_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_tcpwm0_line_compl: p13_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_tcpwm1_line_compl: p13_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_7_tcpwm0_line_compl: p13_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_7_tcpwm1_line_compl: p13_7_tcpwm1_line_compl { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.128-tqfp.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.128-tqfp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.128-tqfp.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.128-tqfp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.68-qfn.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.68-qfn.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.68-qfn.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.68-qfn.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.100-tqfp.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.100-tqfp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.100-tqfp.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.100-tqfp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.49-wlcsp.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.49-wlcsp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.49-wlcsp.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.49-wlcsp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.68-qfn.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.68-qfn.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.68-qfn.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.68-qfn.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.64-tqfp-epad.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.64-tqfp-epad.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.64-tqfp-epad.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.64-tqfp-epad.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.68-qfn.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.68-qfn.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.68-qfn.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.68-qfn.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.80-tqfp.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.80-tqfp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.80-tqfp.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.80-tqfp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.dtsi diff --git a/dts/arm/infineon/psoc6/system_clocks.dtsi b/dts/arm/infineon/cat1a/system_clocks.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/system_clocks.dtsi rename to dts/arm/infineon/cat1a/system_clocks.dtsi From acffb95c733d25b33e4188e64bc97c3e68d69c2f Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1033/1389] dts: infineon: move xmc4*** to cat3\xmc\* - move dts\arm\infineon\xmc4*** files to dts\arm\infineon\cat3\xmc\* Signed-off-by: Nazar Palamar --- dts/arm/infineon/{ => cat3/xmc}/xmc4500_F100x1024-intc.dtsi | 0 dts/arm/infineon/{ => cat3/xmc}/xmc4500_F100x1024-pinctrl.dtsi | 2 +- dts/arm/infineon/{ => cat3/xmc}/xmc4500_F100x1024.dtsi | 2 +- dts/arm/infineon/{ => cat3/xmc}/xmc4700_F144x2048-intc.dtsi | 0 dts/arm/infineon/{ => cat3/xmc}/xmc4700_F144x2048-pinctrl.dtsi | 2 +- dts/arm/infineon/{ => cat3/xmc}/xmc4700_F144x2048.dtsi | 2 +- dts/arm/infineon/{ => cat3/xmc}/xmc4xxx.dtsi | 0 7 files changed, 4 insertions(+), 4 deletions(-) rename dts/arm/infineon/{ => cat3/xmc}/xmc4500_F100x1024-intc.dtsi (100%) rename dts/arm/infineon/{ => cat3/xmc}/xmc4500_F100x1024-pinctrl.dtsi (99%) rename dts/arm/infineon/{ => cat3/xmc}/xmc4500_F100x1024.dtsi (97%) rename dts/arm/infineon/{ => cat3/xmc}/xmc4700_F144x2048-intc.dtsi (100%) rename dts/arm/infineon/{ => cat3/xmc}/xmc4700_F144x2048-pinctrl.dtsi (99%) rename dts/arm/infineon/{ => cat3/xmc}/xmc4700_F144x2048.dtsi (98%) rename dts/arm/infineon/{ => cat3/xmc}/xmc4xxx.dtsi (100%) diff --git a/dts/arm/infineon/xmc4500_F100x1024-intc.dtsi b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-intc.dtsi similarity index 100% rename from dts/arm/infineon/xmc4500_F100x1024-intc.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-intc.dtsi diff --git a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-pinctrl.dtsi similarity index 99% rename from dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-pinctrl.dtsi index 4506e0c995fc9c..d5eb1ba0039f96 100644 --- a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include &pinctrl { diff --git a/dts/arm/infineon/xmc4500_F100x1024.dtsi b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024.dtsi similarity index 97% rename from dts/arm/infineon/xmc4500_F100x1024.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4500_F100x1024.dtsi index d368e397ea3c37..ff64b9bd9c19d2 100644 --- a/dts/arm/infineon/xmc4500_F100x1024.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include / { psram1: memory@10000000 { diff --git a/dts/arm/infineon/xmc4700_F144x2048-intc.dtsi b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-intc.dtsi similarity index 100% rename from dts/arm/infineon/xmc4700_F144x2048-intc.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-intc.dtsi diff --git a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-pinctrl.dtsi similarity index 99% rename from dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-pinctrl.dtsi index e6bab488049d05..b40ba24a8a5c73 100644 --- a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include &pinctrl { diff --git a/dts/arm/infineon/xmc4700_F144x2048.dtsi b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048.dtsi similarity index 98% rename from dts/arm/infineon/xmc4700_F144x2048.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4700_F144x2048.dtsi index ad8e1ea641357f..7a1d6f4db6e69b 100644 --- a/dts/arm/infineon/xmc4700_F144x2048.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { psram1: memory@1ffe8000 { diff --git a/dts/arm/infineon/xmc4xxx.dtsi b/dts/arm/infineon/cat3/xmc/xmc4xxx.dtsi similarity index 100% rename from dts/arm/infineon/xmc4xxx.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4xxx.dtsi From a9f931c4f909ad7a70ead7deebb3382abf0ae0bf Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1034/1389] soc: infineon: port Infineon SOC to HWMv2 Port Infineon SOC to HWMv2. Signed-off-by: Nazar Palamar --- MAINTAINERS.yml | 2 - drivers/hwinfo/Kconfig | 2 +- modules/hal_infineon/CMakeLists.txt | 6 +- modules/hal_infineon/Kconfig | 5 +- .../hal_infineon/mtb-hal-cat1/CMakeLists.txt | 2 - .../hal_infineon/mtb-pdl-cat1/CMakeLists.txt | 10 +- soc/cypress/CMakeLists.txt | 8 - soc/cypress/Kconfig | 9 - soc/cypress/Kconfig.defconfig | 8 - soc/cypress/Kconfig.soc | 17 - soc/cypress/psoc6/CMakeLists.txt | 32 - soc/cypress/psoc6/Kconfig | 58 - soc/cypress/psoc6/Kconfig.defconfig | 30 - soc/cypress/psoc6/Kconfig.soc | 1074 ----------------- .../psoc6/old/Kconfig.defconfig.psoc6_m0 | 10 - .../psoc6/old/Kconfig.defconfig.psoc6_m4 | 10 - soc/cypress/psoc6/old/common/CMakeLists.txt | 6 - soc/infineon/cat1a/CMakeLists.txt | 30 + soc/infineon/cat1a/Kconfig | 62 + soc/infineon/cat1a/Kconfig.defconfig | 10 + soc/infineon/cat1a/Kconfig.soc | 61 + .../new => infineon/cat1a/common}/noinit.ld | 0 .../cat1a}/common/pinctrl_soc.h | 0 .../cat1a/common}/ram_cm0image.ld | 0 .../new => infineon/cat1a/common}/ram_func.ld | 0 .../new => infineon/cat1a/common}/rom.ld | 0 .../cat1a/common}/rom_cm0image.ld | 0 .../psoc6/new => infineon/cat1a/common}/soc.c | 0 .../psoc6/new => infineon/cat1a/common}/soc.h | 0 .../cat1a/psoc6_01/Kconfig.defconfig} | 5 +- soc/infineon/cat1a/psoc6_01/Kconfig.soc | 483 ++++++++ .../cat1a/psoc6_02/Kconfig.defconfig} | 7 +- soc/infineon/cat1a/psoc6_02/Kconfig.soc | 254 ++++ soc/infineon/cat1a/psoc6_03/Kconfig.defconfig | 18 + soc/infineon/cat1a/psoc6_03/Kconfig.soc | 209 ++++ .../cat1a/psoc6_04/Kconfig.defconfig} | 8 +- soc/infineon/cat1a/psoc6_04/Kconfig.soc | 275 +++++ .../cat1a/psoc6_legacy/Kconfig.defconfig | 18 + soc/infineon/cat1a/psoc6_legacy/Kconfig.soc | 42 + .../cat1a/psoc6_legacy}/cypress_psoc6_dt.h | 0 .../cat1a/psoc6_legacy}/noinit.ld | 0 .../cat1a/psoc6_legacy}/rwdata.ld | 0 .../old => infineon/cat1a/psoc6_legacy}/soc.c | 0 .../old => infineon/cat1a/psoc6_legacy}/soc.h | 4 +- .../cat1a/psoc6_legacy}/soc_gpio.c | 0 .../cat1a/psoc6_legacy}/soc_gpio.h | 0 soc/{cypress => infineon/cat1a}/soc.yml | 26 +- soc/infineon/{xmc => cat3}/CMakeLists.txt | 2 + soc/infineon/{xmc => cat3}/Kconfig | 0 soc/infineon/{xmc => cat3}/Kconfig.defconfig | 0 soc/infineon/{xmc => cat3}/Kconfig.soc | 0 soc/infineon/{xmc => cat3}/soc.yml | 0 .../{xmc => cat3}/xmc4xxx/CMakeLists.txt | 0 soc/infineon/{xmc => cat3}/xmc4xxx/Kconfig | 0 .../{xmc => cat3}/xmc4xxx/Kconfig.defconfig | 0 .../xmc4xxx/Kconfig.defconfig.xmc4500 | 0 .../xmc4xxx/Kconfig.defconfig.xmc4700 | 0 .../{xmc => cat3}/xmc4xxx/Kconfig.soc | 0 soc/infineon/{xmc => cat3}/xmc4xxx/noinit.ld | 0 .../{xmc => cat3}/xmc4xxx/pinctrl_soc.h | 0 soc/infineon/{xmc => cat3}/xmc4xxx/soc.c | 0 soc/infineon/{xmc => cat3}/xmc4xxx/soc.h | 0 62 files changed, 1505 insertions(+), 1298 deletions(-) delete mode 100644 soc/cypress/CMakeLists.txt delete mode 100644 soc/cypress/Kconfig delete mode 100644 soc/cypress/Kconfig.defconfig delete mode 100644 soc/cypress/Kconfig.soc delete mode 100644 soc/cypress/psoc6/CMakeLists.txt delete mode 100644 soc/cypress/psoc6/Kconfig delete mode 100644 soc/cypress/psoc6/Kconfig.defconfig delete mode 100644 soc/cypress/psoc6/Kconfig.soc delete mode 100644 soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m0 delete mode 100644 soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m4 delete mode 100644 soc/cypress/psoc6/old/common/CMakeLists.txt create mode 100644 soc/infineon/cat1a/CMakeLists.txt create mode 100644 soc/infineon/cat1a/Kconfig create mode 100644 soc/infineon/cat1a/Kconfig.defconfig create mode 100644 soc/infineon/cat1a/Kconfig.soc rename soc/{cypress/psoc6/new => infineon/cat1a/common}/noinit.ld (100%) rename soc/{cypress/psoc6/new => infineon/cat1a}/common/pinctrl_soc.h (100%) rename soc/{cypress/psoc6/new => infineon/cat1a/common}/ram_cm0image.ld (100%) rename soc/{cypress/psoc6/new => infineon/cat1a/common}/ram_func.ld (100%) rename soc/{cypress/psoc6/new => infineon/cat1a/common}/rom.ld (100%) rename soc/{cypress/psoc6/new => infineon/cat1a/common}/rom_cm0image.ld (100%) rename soc/{cypress/psoc6/new => infineon/cat1a/common}/soc.c (100%) rename soc/{cypress/psoc6/new => infineon/cat1a/common}/soc.h (100%) rename soc/{cypress/psoc6/new/Kconfig.defconfig.psoc6_01 => infineon/cat1a/psoc6_01/Kconfig.defconfig} (73%) create mode 100644 soc/infineon/cat1a/psoc6_01/Kconfig.soc rename soc/{cypress/psoc6/new/Kconfig.defconfig.psoc6_02 => infineon/cat1a/psoc6_02/Kconfig.defconfig} (65%) create mode 100644 soc/infineon/cat1a/psoc6_02/Kconfig.soc create mode 100644 soc/infineon/cat1a/psoc6_03/Kconfig.defconfig create mode 100644 soc/infineon/cat1a/psoc6_03/Kconfig.soc rename soc/{cypress/psoc6/new/Kconfig.defconfig.psoc6_04 => infineon/cat1a/psoc6_04/Kconfig.defconfig} (64%) create mode 100644 soc/infineon/cat1a/psoc6_04/Kconfig.soc create mode 100644 soc/infineon/cat1a/psoc6_legacy/Kconfig.defconfig create mode 100644 soc/infineon/cat1a/psoc6_legacy/Kconfig.soc rename soc/{cypress/psoc6/old/common => infineon/cat1a/psoc6_legacy}/cypress_psoc6_dt.h (100%) rename soc/{cypress/psoc6/old => infineon/cat1a/psoc6_legacy}/noinit.ld (100%) rename soc/{cypress/psoc6/old => infineon/cat1a/psoc6_legacy}/rwdata.ld (100%) rename soc/{cypress/psoc6/old => infineon/cat1a/psoc6_legacy}/soc.c (100%) rename soc/{cypress/psoc6/old => infineon/cat1a/psoc6_legacy}/soc.h (85%) rename soc/{cypress/psoc6/old/common => infineon/cat1a/psoc6_legacy}/soc_gpio.c (100%) rename soc/{cypress/psoc6/old/common => infineon/cat1a/psoc6_legacy}/soc_gpio.h (100%) rename soc/{cypress => infineon/cat1a}/soc.yml (97%) rename soc/infineon/{xmc => cat3}/CMakeLists.txt (65%) rename soc/infineon/{xmc => cat3}/Kconfig (100%) rename soc/infineon/{xmc => cat3}/Kconfig.defconfig (100%) rename soc/infineon/{xmc => cat3}/Kconfig.soc (100%) rename soc/infineon/{xmc => cat3}/soc.yml (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/CMakeLists.txt (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/Kconfig (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/Kconfig.defconfig (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/Kconfig.defconfig.xmc4500 (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/Kconfig.defconfig.xmc4700 (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/Kconfig.soc (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/noinit.ld (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/pinctrl_soc.h (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/soc.c (100%) rename soc/infineon/{xmc => cat3}/xmc4xxx/soc.h (100%) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index a95e3b9b37eb88..e905666fb69330 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3706,8 +3706,6 @@ Infineon Platforms: - drivers/*/*xmc* - drivers/sensor/infineon/ - dts/arm/infineon/ - - dts/arm/cypress/ - - soc/cypress/ - dts/bindings/*/*infineon* - soc/infineon/ labels: diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index b3bab9c82afb0c..0d3f6b991f9869 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -173,7 +173,7 @@ config HWINFO_LITEX config HWINFO_PSOC6 bool "Cypress PSoC-6 unique device ID" default y - depends on SOC_FAMILY_PSOC6 + depends on SOC_FAMILY_PSOC6_LEGACY help Enable Cypress PSoC-6 hwinfo driver. diff --git a/modules/hal_infineon/CMakeLists.txt b/modules/hal_infineon/CMakeLists.txt index 99d925b1396a0c..c6d9d95aa246e7 100644 --- a/modules/hal_infineon/CMakeLists.txt +++ b/modules/hal_infineon/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright (c) 2022 Cypress Semiconductor Corporation. # SPDX-License-Identifier: Apache-2.0 -if(CONFIG_HAS_XMCLIB OR CONFIG_SOC_FAMILY_PSOC6 OR CONFIG_SOC_FAMILY_INFINEON_CAT1) +if(CONFIG_HAS_XMCLIB OR CONFIG_SOC_FAMILY_PSOC6_LEGACY OR CONFIG_SOC_FAMILY_INFINEON_CAT1) zephyr_library_named(modules_hal_infineon) zephyr_library_compile_options(-Wno-array-bounds) endif() @@ -12,7 +12,7 @@ if (CONFIG_HAS_XMCLIB) add_subdirectory(${ZEPHYR_HAL_INFINEON_MODULE_DIR}/XMCLib XMCLib) endif() -if (CONFIG_SOC_FAMILY_INFINEON_CAT1A OR CONFIG_SOC_FAMILY_PSOC6) +if (CONFIG_SOC_FAMILY_INFINEON_CAT1 OR CONFIG_SOC_FAMILY_PSOC6_LEGACY) ## Add core-lib sources for CAT1 devices add_subdirectory(core-lib) @@ -23,7 +23,7 @@ if (CONFIG_SOC_FAMILY_INFINEON_CAT1A OR CONFIG_SOC_FAMILY_PSOC6) add_subdirectory(mtb-template-cat1) endif() -if (CONFIG_SOC_FAMILY_INFINEON_CAT1A) +if (CONFIG_SOC_FAMILY_INFINEON_CAT1 AND NOT CONFIG_SOC_FAMILY_PSOC6_LEGACY) ## Add mtb-hal-cat1 sources for CAT1 devices add_subdirectory(mtb-hal-cat1) diff --git a/modules/hal_infineon/Kconfig b/modules/hal_infineon/Kconfig index 723579c5d5b923..fb1431faed20b5 100644 --- a/modules/hal_infineon/Kconfig +++ b/modules/hal_infineon/Kconfig @@ -4,7 +4,7 @@ config ZEPHYR_HAL_INFINEON_MODULE bool -if SOC_FAMILY_PSOC6 || SOC_FAMILY_INFINEON_CAT1 +if SOC_FAMILY_INFINEON_CAT1 || SOC_FAMILY_PSOC6_LEGACY config USE_INFINEON_ADC bool @@ -77,8 +77,7 @@ config USE_INFINEON_FLASH help Enable Flash HAL module driver for Infineon devices -endif # SOC_FAMILY_PSOC6 - +endif # SOC_FAMILY_INFINEON_CAT1 || SOC_FAMILY_PSOC6_LEGACY config USE_INFINEON_ABSTRACTION_RTOS bool "Abstraction RTOS component (Zephyr support)" help diff --git a/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt index c94bd1db60c345..e3d468cd764122 100644 --- a/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt @@ -29,8 +29,6 @@ zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_124_BGA ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_124_bga.c) zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_124_BGA_SIP ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_124_bga_sip.c) -zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_43_SMT - ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_43_smt.c) zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_68_QFN_BLE ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_68_qfn_ble.c) zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_80_WLCSP diff --git a/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt index f71e0b2b3a9529..f7461673961f88 100644 --- a/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt @@ -7,8 +7,13 @@ set(pdl_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1) set(pdl_drv_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/drivers) set(pdl_dev_cat1a_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/devices/COMPONENT_CAT1A) + +# Generate PDL specific SOC defines zephyr_compile_definitions(${CONFIG_SOC_PART_NUMBER}) -zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 ${CONFIG_SOC}) +zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 $) + +# Generate PDL specific define (w. *_device) for SOC module (e.g: CYBLE_416045_02) +zephyr_compile_definitions_ifdef(CONFIG_SOC_CYBLE_416045_02 CYBLE_416045_02_device) # Add mtb-pdl-cat1 zephyr_include_directories(${pdl_drv_dir}/include) @@ -19,11 +24,12 @@ zephyr_library_sources(${pdl_dev_cat1a_dir}/source/cy_device.c) zephyr_library_sources(${pdl_drv_dir}/source/TOOLCHAIN_GCC_ARM/cy_syslib_ext.S) # Peripheral drivers -zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 ${pdl_drv_dir}/source/cy_sysint.c) +zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6_LEGACY ${pdl_drv_dir}/source/cy_sysint.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_ADC ${pdl_drv_dir}/source/cy_sar.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_I2C ${pdl_drv_dir}/source/cy_scb_i2c.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_LPTIMER ${pdl_drv_dir}/source/cy_mcwdt.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_PWM ${pdl_drv_dir}/source/cy_tcpwm_pwm.c) +zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_RTC ${pdl_drv_dir}/source/cy_rtc.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_SDIO ${pdl_drv_dir}/source/cy_sd_host.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_SPI ${pdl_drv_dir}/source/cy_scb_spi.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_TIMER ${pdl_drv_dir}/source/cy_tcpwm_counter.c) diff --git a/soc/cypress/CMakeLists.txt b/soc/cypress/CMakeLists.txt deleted file mode 100644 index e55e313974031e..00000000000000 --- a/soc/cypress/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2018, Cypress -# Copyright (c) 2021, ATL Electronics -# -# SPDX-License-Identifier: Apache-2.0 -# - -add_subdirectory(psoc6) diff --git a/soc/cypress/Kconfig b/soc/cypress/Kconfig deleted file mode 100644 index 8c645cb1d7bb67..00000000000000 --- a/soc/cypress/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2018, Cypress -# Copyright (c) 2020, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -if SOC_FAMILY_PSOC6 || SOC_FAMILY_INFINEON_CAT1 - -rsource "*/Kconfig" - -endif # SOC_FAMILY_PSOC6 || SOC_FAMILY_INFINEON_CAT1 diff --git a/soc/cypress/Kconfig.defconfig b/soc/cypress/Kconfig.defconfig deleted file mode 100644 index 1e382579c5f5fc..00000000000000 --- a/soc/cypress/Kconfig.defconfig +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2018, Cypress -# SPDX-License-Identifier: Apache-2.0 - -if SOC_FAMILY_PSOC6 || SOC_FAMILY_INFINEON_CAT1 - -rsource "*/Kconfig.defconfig" - -endif # SOC_FAMILY_PSOC6 || SOC_FAMILY_INFINEON_CAT1 diff --git a/soc/cypress/Kconfig.soc b/soc/cypress/Kconfig.soc deleted file mode 100644 index 140274c4e26094..00000000000000 --- a/soc/cypress/Kconfig.soc +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2018, Cypress -# SPDX-License-Identifier: Apache-2.0 - -config SOC_FAMILY_PSOC6 - bool - -config SOC_FAMILY_INFINEON_CAT1 - bool - -config SOC_FAMILY_INFINEON_CAT1A - bool - -config SOC_FAMILY - default "psoc6" if SOC_FAMILY_PSOC6 - default "infineon_cat1" if SOC_FAMILY_INFINEON_CAT1 - -rsource "*/Kconfig.soc" diff --git a/soc/cypress/psoc6/CMakeLists.txt b/soc/cypress/psoc6/CMakeLists.txt deleted file mode 100644 index f7a4bd016ad9b4..00000000000000 --- a/soc/cypress/psoc6/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2018, Cypress -# Copyright (c) 2020, ATL Electronics -# -# SPDX-License-Identifier: Apache-2.0 -# - -if(CONFIG_SOC_SERIES_PSOC62 OR CONFIG_SOC_SERIES_PSOC63) - add_subdirectory(old/common) - zephyr_include_directories(old) - zephyr_sources(old/soc.c) - - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 NOINIT old/noinit.ld) - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 RWDATA old/rwdata.ld) -else() - zephyr_include_directories(new) - zephyr_include_directories(new/common) - zephyr_sources(new/soc.c) - - # Add sections - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 NOINIT new/noinit.ld) - - # Add section for cm0p image ROM - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ROM_START SORT_KEY 0x0cm0p new/rom_cm0image.ld) - - # Add section for cm0p image RAM - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A RAM_SECTIONS SORT_KEY 0 new/ram_cm0image.ld) - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A RAMFUNC_SECTION SORT_KEY 0 new/ram_func.ld) - zephyr_linker_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 RODATA SORT_KEY 0 new/rom.ld) -endif() - -set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/cypress/psoc6/Kconfig b/soc/cypress/psoc6/Kconfig deleted file mode 100644 index 78c412cc3ef755..00000000000000 --- a/soc/cypress/psoc6/Kconfig +++ /dev/null @@ -1,58 +0,0 @@ -# Cypress Semiconductor PSoC6 series configuration options -# Copyright (c) 2018, Cypress -# Copyright (c) 2020, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_PSOC62_PSOC63 - bool - select ARM - select HAS_CYPRESS_DRIVERS - select CPU_CORTEX_M0PLUS if SOC_CY8C6247_M0 || SOC_CY8C6347_M0 - select CPU_CORTEX_M_HAS_SYSTICK if SOC_CY8C6247_M0 || SOC_CY8C6347_M0 - select CPU_CORTEX_M_HAS_VTOR if SOC_CY8C6247_M0 || SOC_CY8C6347_M0 - select CPU_HAS_ARM_MPU if SOC_CY8C6247_M0 || SOC_CY8C6347_M0 - select CPU_CORTEX_M4 if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - select CPU_CORTEX_M_HAS_DWT if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - select CPU_CORTEX_M_HAS_SYSTICK if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - select CPU_HAS_ARM_MPU if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - select CPU_HAS_FPU if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - -config SOC_SERIES_PSOC62 - select SOC_SERIES_PSOC62_PSOC63 - -config SOC_SERIES_PSOC63 - select SOC_SERIES_PSOC62_PSOC63 - -config SOC_PSOC6_M0_ENABLES_M4 - bool "Dual-core support [activate Cortex-M4]" - depends on SOC_CY8C6247_M0 || SOC_CY8C6347_M0 - help - Cortex-M0 CPU should boot Cortex-M4 - -config SOC_DIE_PSOC6 - select ARM - select CPU_CORTEX_M4 - select CPU_HAS_ARM_MPU - select DYNAMIC_INTERRUPTS - select CPU_HAS_FPU - -if SOC_FAMILY_INFINEON_CAT1A - -## PSoC™ 6 Cortex M0+ prebuilt images -choice - prompt "PSoC™ 6 Cortex M0+ prebuilt images" - help - Choose the prebuilt application image to be executed on the Cortex-M0+ core of the PSoC™ 6 - dual-core MCU. The image is responsible for booting the Cortex-M4 on the device. - -config SOC_PSOC6_CM0P_IMAGE_SLEEP - bool "DeepSleep" - help - DeepSleep prebuilt application image is executed on the Cortex-M0+ core of the PSoC™ 6 BLE - dual-core MCU.The image is provided as C array ready to be compiled as part of the Cortex-M4 - application. The Cortex-M0+ application code is placed to internal flash by the Cortex-M4 - linker script. - -endchoice - -endif # SOC_FAMILY_INFINEON_CAT1A diff --git a/soc/cypress/psoc6/Kconfig.defconfig b/soc/cypress/psoc6/Kconfig.defconfig deleted file mode 100644 index a5995c61a0c44f..00000000000000 --- a/soc/cypress/psoc6/Kconfig.defconfig +++ /dev/null @@ -1,30 +0,0 @@ -# Cypress Semiconductor PSoC6 series configuration options -# Copyright (c) 2018, Cypress -# Copyright (c) 2020, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_PSOC62 || SOC_SERIES_PSOC63 - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default 50000000 - -rsource "old/Kconfig.defconfig.psoc*" - -endif # SOC_SERIES_PSOC62 || SOC_SERIES_PSOC63 - -if SOC_FAMILY_INFINEON_CAT1 - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default 100000000 - -config SOC_PSOC6_CM0P_IMAGE_ROM_SIZE - hex - default 0x2000 if SOC_PSOC6_CM0P_IMAGE_SLEEP - -config SOC_PSOC6_CM0P_IMAGE_RAM_SIZE - hex - default 0x2000 if SOC_PSOC6_CM0P_IMAGE_SLEEP - -rsource "new/Kconfig.defconfig.psoc6*" - -endif # SOC_FAMILY_INFINEON_CAT1 diff --git a/soc/cypress/psoc6/Kconfig.soc b/soc/cypress/psoc6/Kconfig.soc deleted file mode 100644 index b644b123a073d4..00000000000000 --- a/soc/cypress/psoc6/Kconfig.soc +++ /dev/null @@ -1,1074 +0,0 @@ -# Cypress Semiconductor PSoC6 series configuration options -# Copyright (c) 2018, Cypress -# Copyright (c) 2020, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_PSOC6 - bool - select SOC_FAMILY_INFINEON_CAT1 - -config SOC_SERIES_PSOC62 - bool - select SOC_FAMILY_PSOC6 - help - Enable support for Cypress PSoC6 MCU series - -config SOC_SERIES_PSOC63 - bool - select SOC_FAMILY_PSOC6 - help - Enable support for Cypress PSoC6-BLE MCU series - -# Cypress PSoC™ 6 MCU lines -config SOC_SERIES_PSOC_60 - bool - select SOC_SERIES_PSOC6 - help - Enable support for Infineon PSoC™ 60 MCU series - -config SOC_SERIES_PSOC_61 - bool - select SOC_SERIES_PSOC6 - help - Enable support for Infineon PSoC™ 61 MCU series - -config SOC_SERIES_PSOC_62 - bool - select SOC_SERIES_PSOC6 - help - Enable support for Infineon PSoC™ 62 MCU series - -config SOC_SERIES_PSOC_63 - bool - select SOC_SERIES_PSOC6 - help - Enable support for Infineon PSoC™ 63 MCU series - -config SOC_SERIES_PSOC_64 - bool - select SOC_SERIES_PSOC6 - help - Enable support for Infineon PSoC™ 64 MCU series - -config SOC_CY8C6247_M0 - bool - select SOC_SERIES_PSOC62 - -config SOC_CY8C6247_M4 - bool - select SOC_SERIES_PSOC62 - -config SOC_CY8C6347_M0 - bool - select SOC_SERIES_PSOC63 - -config SOC_CY8C6347_M4 - bool - select SOC_SERIES_PSOC63 - -config SOC_PART_NUMBER_CY8C6247BZI_D54 - bool - depends on SOC_SERIES_PSOC62 - help - CY8C6247BZI_D54 - -config SOC_PART_NUMBER_CY8C6347BZI_BLD53 - bool - depends on SOC_SERIES_PSOC63 - help - CY8C6347BZI_BLD53 - -# Infineon PSoC6 die -config SOC_DIE_PSOC6 - bool - select SOC_FAMILY_INFINEON_CAT1A - -# Infineon PSoC6_01 die -config SOC_DIE_PSOC6_01 - bool - select SOC_DIE_PSOC6 - -# Infineon PSoC6_02 die -config SOC_DIE_PSOC6_02 - bool - select SOC_DIE_PSOC6 - -# Infineon PSoC6_03 die -config SOC_DIE_PSOC6_03 - bool - select SOC_DIE_PSOC6 - -# Infineon PSoC6_04 die -config SOC_DIE_PSOC6_04 - bool - select SOC_DIE_PSOC6 - -# Infineon soc packages -config SOC_PACKAGE_PSOC6_01_124_BGA - bool - -config SOC_PACKAGE_PSOC6_01_116_BGA_BLE - bool - -config SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE - bool - -config SOC_PACKAGE_PSOC6_01_80_WLCSP - bool - -config SOC_PACKAGE_PSOC6_01_116_BGA_USB - bool - -config SOC_PACKAGE_PSOC6_01_124_BGA_SIP - bool - -config SOC_PACKAGE_PSOC6_01_43_SMT - bool - -config SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB - bool - -config SOC_PACKAGE_PSOC6_01_68_QFN_BLE - bool - -config SOC_PACKAGE_PSOC6_02_124_BGA - bool - -config SOC_PACKAGE_PSOC6_02_128_TQFP - bool - -config SOC_PACKAGE_PSOC6_02_100_WLCSP - bool - -config SOC_PACKAGE_PSOC6_02_68_QFN - bool - -config SOC_PACKAGE_PSOC6_03_100_TQFP - bool - -config SOC_PACKAGE_PSOC6_03_68_QFN - bool - -config SOC_PACKAGE_PSOC6_03_49_WLCSP - bool - -config SOC_PACKAGE_PSOC6_04_64_TQFP - bool - -config SOC_PACKAGE_PSOC6_04_68_QFN - bool - -config SOC_PACKAGE_PSOC6_04_80_TQFP - bool - -# Infineon PSoC6_01 series MCUs -config SOC_CY8C6036BZI_F04 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_60 - -config SOC_CY8C6016BZI_F04 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_60 - -config SOC_CY8C6116BZI_F54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6136BZI_F14 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6136BZI_F34 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6137BZI_F14 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6137BZI_F34 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6137BZI_F54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6117BZI_F34 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6246BZI_D04 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6247BZI_D44 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6247BZI_D34 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6247BZI_D54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6336BZI_BLF03 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6316BZI_BLF03 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6316BZI_BLF53 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6336BZI_BLD13 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BLD43 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BLD33 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BLD53 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BLD13 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BLD43 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BLD33 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BLD53 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6137FDI_F02 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6117FDI_F02 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6247FDI_D02 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6247FDI_D32 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6336BZI_BUD13 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BUD43 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BUD33 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BUD53 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6337BZI_BLF13 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6136FDI_F42 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6247FDI_D52 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6136FTI_F42 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6247FTI_D52 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_80_WLCSP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6247BZI_AUD54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6336BZI_BLF04 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6316BZI_BLF04 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6316BZI_BLF54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6336BZI_BLD14 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BLD44 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BLD34 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347BZI_BLD54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6247BFI_D54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CYBLE_416045_02 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BUD53 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BUD13 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BUD43 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347FMI_BUD33 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6137WI_F54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6117WI_F34 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6247WI_D54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6336LQI_BLF02 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_68_QFN_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6336LQI_BLF42 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_68_QFN_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CY8C6347LQI_BLD52 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_68_QFN_BLE - select SOC_SERIES_PSOC_63 - -config SOC_CYB06447BZI_BLD54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA_SIP - select SOC_SERIES_PSOC_64 - -config SOC_CYB06447BZI_BLD53 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_116_BGA_BLE - select SOC_SERIES_PSOC_64 - -config SOC_CYB06447BZI_D54 - bool - select SOC_DIE_PSOC6_01 - select SOC_PACKAGE_PSOC6_01_124_BGA - select SOC_SERIES_PSOC_64 - -# Infineon PSoC6_02 series MCUs -config SOC_CYB0644ABZI_S2D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_64 - -config SOC_CYS0644ABZI_S2D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_64 - -config SOC_CY8C624ABZI_S2D44A0 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624ABZI_S2D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624AAZI_S2D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624AFNI_S2D43 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_100_WLCSP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624ABZI_S2D04 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624ABZI_S2D14 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624AAZI_S2D14 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6248AZI_S2D14 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6248BZI_S2D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6248AZI_S2D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6248FNI_S2D43 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_100_WLCSP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C614ABZI_S2F04 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614AAZI_S2F04 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614AFNI_S2F03 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_100_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614AAZI_S2F14 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614ABZI_S2F44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614AAZI_S2F44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614AFNI_S2F43 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_100_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6148BZI_S2F44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6148AZI_S2F44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_128_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6148FNI_S2F43 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_100_WLCSP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C624ABZI_D44 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_124_BGA - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624ALQI_S2D42 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C624ALQI_S2D02 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6248LQI_S2D42 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6248LQI_S2D02 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C614ALQI_S2F42 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_CY8C614ALQI_S2F02 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6148LQI_S2F42 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6148LQI_S2F02 - bool - select SOC_DIE_PSOC6_02 - select SOC_PACKAGE_PSOC6_02_68_QFN - select SOC_SERIES_PSOC_61 - -# Infineon PSoC6_04 series MCUs -config SOC_CY8C6244AZI_S4D92 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244LQI_S4D92 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244AZI_S4D93 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_80_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244AZI_S4D82 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244LQI_S4D82 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244AZI_S4D83 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_80_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244AZI_S4D62 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244LQI_S4D62 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244AZI_S4D12 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6244LQI_S4D12 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_62 - -config SOC_CY8C6144AZI_S4F92 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144LQI_S4F92 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144AZI_S4F93 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_80_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144AZI_S4F82 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144LQI_S4F82 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144AZI_S4F83 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_80_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144AZI_S4F62 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144LQI_S4F62 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144AZI_S4F12 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_64_TQFP - select SOC_SERIES_PSOC_61 - -config SOC_CY8C6144LQI_S4F12 - bool - select SOC_DIE_PSOC6_04 - select SOC_PACKAGE_PSOC6_04_68_QFN - select SOC_SERIES_PSOC_61 - -config SOC_SERIES - default "psoc62" if SOC_SERIES_PSOC62 - default "psoc63" if SOC_SERIES_PSOC63 - default "psoc6" if SOC_SERIES_PSOC6 - -config SOC - default "cy8c6247" if SOC_CY8C6247_M0 || SOC_CY8C6247_M4 - default "cy8c6347" if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - default "cy8c6036bzi_f04" if SOC_CY8C6036BZI_F04 - default "cy8c6016bzi_f04" if SOC_CY8C6016BZI_F04 - default "cy8c6116bzi_f54" if SOC_CY8C6116BZI_F54 - default "cy8c6136bzi_f14" if SOC_CY8C6136BZI_F14 - default "cy8c6136bzi_f34" if SOC_CY8C6136BZI_F34 - default "cy8c6137bzi_f14" if SOC_CY8C6137BZI_F14 - default "cy8c6137bzi_f34" if SOC_CY8C6137BZI_F34 - default "cy8c6137bzi_f54" if SOC_CY8C6137BZI_F54 - default "cy8c6117bzi_f34" if SOC_CY8C6117BZI_F34 - default "cy8c6246bzi_d04" if SOC_CY8C6246BZI_D04 - default "cy8c6247bzi_d44" if SOC_CY8C6247BZI_D44 - default "cy8c6247bzi_d34" if SOC_CY8C6247BZI_D34 - default "cy8c6247bzi_d54" if SOC_CY8C6247BZI_D54 - default "cy8c6336bzi_blf03" if SOC_CY8C6336BZI_BLF03 - default "cy8c6316bzi_blf03" if SOC_CY8C6316BZI_BLF03 - default "cy8c6316bzi_blf53" if SOC_CY8C6316BZI_BLF53 - default "cy8c6336bzi_bld13" if SOC_CY8C6336BZI_BLD13 - default "cy8c6347bzi_bld43" if SOC_CY8C6347BZI_BLD43 - default "cy8c6347bzi_bld33" if SOC_CY8C6347BZI_BLD33 - default "cy8c6347bzi_bld53" if SOC_CY8C6347BZI_BLD53 - default "cy8c6347fmi_bld13" if SOC_CY8C6347FMI_BLD13 - default "cy8c6347fmi_bld43" if SOC_CY8C6347FMI_BLD43 - default "cy8c6347fmi_bld33" if SOC_CY8C6347FMI_BLD33 - default "cy8c6347fmi_bld53" if SOC_CY8C6347FMI_BLD53 - default "cy8c6137fdi_f02" if SOC_CY8C6137FDI_F02 - default "cy8c6117fdi_f02" if SOC_CY8C6117FDI_F02 - default "cy8c6247fdi_d02" if SOC_CY8C6247FDI_D02 - default "cy8c6247fdi_d32" if SOC_CY8C6247FDI_D32 - default "cy8c6336bzi_bud13" if SOC_CY8C6336BZI_BUD13 - default "cy8c6347bzi_bud43" if SOC_CY8C6347BZI_BUD43 - default "cy8c6347bzi_bud33" if SOC_CY8C6347BZI_BUD33 - default "cy8c6347bzi_bud53" if SOC_CY8C6347BZI_BUD53 - default "cy8c6337bzi_blf13" if SOC_CY8C6337BZI_BLF13 - default "cy8c6136fdi_f42" if SOC_CY8C6136FDI_F42 - default "cy8c6247fdi_d52" if SOC_CY8C6247FDI_D52 - default "cy8c6136fti_f42" if SOC_CY8C6136FTI_F42 - default "cy8c6247fti_d52" if SOC_CY8C6247FTI_D52 - default "cy8c6247bzi_aud54" if SOC_CY8C6247BZI_AUD54 - default "cy8c6336bzi_blf04" if SOC_CY8C6336BZI_BLF04 - default "cy8c6316bzi_blf04" if SOC_CY8C6316BZI_BLF04 - default "cy8c6316bzi_blf54" if SOC_CY8C6316BZI_BLF54 - default "cy8c6336bzi_bld14" if SOC_CY8C6336BZI_BLD14 - default "cy8c6347bzi_bld44" if SOC_CY8C6347BZI_BLD44 - default "cy8c6347bzi_bld34" if SOC_CY8C6347BZI_BLD34 - default "cy8c6347bzi_bld54" if SOC_CY8C6347BZI_BLD54 - default "cy8c6247bfi_d54" if SOC_CY8C6247BFI_D54 - default "cyble_416045_02" if SOC_CYBLE_416045_02 - default "cy8c6347fmi_bud53" if SOC_CY8C6347FMI_BUD53 - default "cy8c6347fmi_bud13" if SOC_CY8C6347FMI_BUD13 - default "cy8c6347fmi_bud43" if SOC_CY8C6347FMI_BUD43 - default "cy8c6347fmi_bud33" if SOC_CY8C6347FMI_BUD33 - default "cy8c6137wi_f54" if SOC_CY8C6137WI_F54 - default "cy8c6117wi_f34" if SOC_CY8C6117WI_F34 - default "cy8c6247wi_d54" if SOC_CY8C6247WI_D54 - default "cy8c6336lqi_blf02" if SOC_CY8C6336LQI_BLF02 - default "cy8c6336lqi_blf42" if SOC_CY8C6336LQI_BLF42 - default "cy8c6347lqi_bld52" if SOC_CY8C6347LQI_BLD52 - default "cyb06447bzi_bld54" if SOC_CYB06447BZI_BLD54 - default "cyb06447bzi_bld53" if SOC_CYB06447BZI_BLD53 - default "cyb06447bzi_d54" if SOC_CYB06447BZI_D54 - default "cyb0644abzi_s2d44" if SOC_CYB0644ABZI_S2D44 - default "cys0644abzi_s2d44" if SOC_CYS0644ABZI_S2D44 - default "cy8c624abzi_s2d44a0" if SOC_CY8C624ABZI_S2D44A0 - default "cy8c624abzi_s2d44" if SOC_CY8C624ABZI_S2D44 - default "cy8c624aazi_s2d44" if SOC_CY8C624AAZI_S2D44 - default "cy8c624afni_s2d43" if SOC_CY8C624AFNI_S2D43 - default "cy8c624abzi_s2d04" if SOC_CY8C624ABZI_S2D04 - default "cy8c624abzi_s2d14" if SOC_CY8C624ABZI_S2D14 - default "cy8c624aazi_s2d14" if SOC_CY8C624AAZI_S2D14 - default "cy8c6248azi_s2d14" if SOC_CY8C6248AZI_S2D14 - default "cy8c6248bzi_s2d44" if SOC_CY8C6248BZI_S2D44 - default "cy8c6248azi_s2d44" if SOC_CY8C6248AZI_S2D44 - default "cy8c6248fni_s2d43" if SOC_CY8C6248FNI_S2D43 - default "cy8c614abzi_s2f04" if SOC_CY8C614ABZI_S2F04 - default "cy8c614aazi_s2f04" if SOC_CY8C614AAZI_S2F04 - default "cy8c614afni_s2f03" if SOC_CY8C614AFNI_S2F03 - default "cy8c614aazi_s2f14" if SOC_CY8C614AAZI_S2F14 - default "cy8c614abzi_s2f44" if SOC_CY8C614ABZI_S2F44 - default "cy8c614aazi_s2f44" if SOC_CY8C614AAZI_S2F44 - default "cy8c614afni_s2f43" if SOC_CY8C614AFNI_S2F43 - default "cy8c6148bzi_s2f44" if SOC_CY8C6148BZI_S2F44 - default "cy8c6148azi_s2f44" if SOC_CY8C6148AZI_S2F44 - default "cy8c6148fni_s2f43" if SOC_CY8C6148FNI_S2F43 - default "cy8c624abzi_d44" if SOC_CY8C624ABZI_D44 - default "cy8c624alqi_s2d42" if SOC_CY8C624ALQI_S2D42 - default "cy8c624alqi_s2d02" if SOC_CY8C624ALQI_S2D02 - default "cy8c6248lqi_s2d42" if SOC_CY8C6248LQI_S2D42 - default "cy8c6248lqi_s2d02" if SOC_CY8C6248LQI_S2D02 - default "cy8c614alqi_s2f42" if SOC_CY8C614ALQI_S2F42 - default "cy8c614alqi_s2f02" if SOC_CY8C614ALQI_S2F02 - default "cy8c6148lqi_s2f42" if SOC_CY8C6148LQI_S2F42 - default "cy8c6148lqi_s2f02" if SOC_CY8C6148LQI_S2F02 - default "cy8c6244azi_s4d92" if SOC_CY8C6244AZI_S4D92 - default "cy8c6244lqi_s4d92" if SOC_CY8C6244LQI_S4D92 - default "cy8c6244azi_s4d93" if SOC_CY8C6244AZI_S4D93 - default "cy8c6244azi_s4d82" if SOC_CY8C6244AZI_S4D82 - default "cy8c6244lqi_s4d82" if SOC_CY8C6244LQI_S4D82 - default "cy8c6244azi_s4d83" if SOC_CY8C6244AZI_S4D83 - default "cy8c6244azi_s4d62" if SOC_CY8C6244AZI_S4D62 - default "cy8c6244lqi_s4d62" if SOC_CY8C6244LQI_S4D62 - default "cy8c6244azi_s4d12" if SOC_CY8C6244AZI_S4D12 - default "cy8c6244lqi_s4d12" if SOC_CY8C6244LQI_S4D12 - default "cy8c6144azi_s4f92" if SOC_CY8C6144AZI_S4F92 - default "cy8c6144lqi_s4f92" if SOC_CY8C6144LQI_S4F92 - default "cy8c6144azi_s4f93" if SOC_CY8C6144AZI_S4F93 - default "cy8c6144azi_s4f82" if SOC_CY8C6144AZI_S4F82 - default "cy8c6144lqi_s4f82" if SOC_CY8C6144LQI_S4F82 - default "cy8c6144azi_s4f83" if SOC_CY8C6144AZI_S4F83 - default "cy8c6144azi_s4f62" if SOC_CY8C6144AZI_S4F62 - default "cy8c6144lqi_s4f62" if SOC_CY8C6144LQI_S4F62 - default "cy8c6144azi_s4f12" if SOC_CY8C6144AZI_S4F12 - default "cy8c6144lqi_s4f12" if SOC_CY8C6144LQI_S4F12 - -config SOC_PART_NUMBER - default "CY8C6247BZI_D54" if SOC_PART_NUMBER_CY8C6247BZI_D54 - default "CY8C6347BZI_BLD53" if SOC_PART_NUMBER_CY8C6347BZI_BLD53 - default "CY8C6036BZI_F04" if SOC_CY8C6036BZI_F04 - default "CY8C6016BZI_F04" if SOC_CY8C6016BZI_F04 - default "CY8C6116BZI_F54" if SOC_CY8C6116BZI_F54 - default "CY8C6136BZI_F14" if SOC_CY8C6136BZI_F14 - default "CY8C6136BZI_F34" if SOC_CY8C6136BZI_F34 - default "CY8C6137BZI_F14" if SOC_CY8C6137BZI_F14 - default "CY8C6137BZI_F34" if SOC_CY8C6137BZI_F34 - default "CY8C6137BZI_F54" if SOC_CY8C6137BZI_F54 - default "CY8C6117BZI_F34" if SOC_CY8C6117BZI_F34 - default "CY8C6246BZI_D04" if SOC_CY8C6246BZI_D04 - default "CY8C6247BZI_D44" if SOC_CY8C6247BZI_D44 - default "CY8C6247BZI_D34" if SOC_CY8C6247BZI_D34 - default "CY8C6247BZI_D54" if SOC_CY8C6247BZI_D54 - default "CY8C6336BZI_BLF03" if SOC_CY8C6336BZI_BLF03 - default "CY8C6316BZI_BLF03" if SOC_CY8C6316BZI_BLF03 - default "CY8C6316BZI_BLF53" if SOC_CY8C6316BZI_BLF53 - default "CY8C6336BZI_BLD13" if SOC_CY8C6336BZI_BLD13 - default "CY8C6347BZI_BLD43" if SOC_CY8C6347BZI_BLD43 - default "CY8C6347BZI_BLD33" if SOC_CY8C6347BZI_BLD33 - default "CY8C6347BZI_BLD53" if SOC_CY8C6347BZI_BLD53 - default "CY8C6347FMI_BLD13" if SOC_CY8C6347FMI_BLD13 - default "CY8C6347FMI_BLD43" if SOC_CY8C6347FMI_BLD43 - default "CY8C6347FMI_BLD33" if SOC_CY8C6347FMI_BLD33 - default "CY8C6347FMI_BLD53" if SOC_CY8C6347FMI_BLD53 - default "CY8C6137FDI_F02" if SOC_CY8C6137FDI_F02 - default "CY8C6117FDI_F02" if SOC_CY8C6117FDI_F02 - default "CY8C6247FDI_D02" if SOC_CY8C6247FDI_D02 - default "CY8C6247FDI_D32" if SOC_CY8C6247FDI_D32 - default "CY8C6336BZI_BUD13" if SOC_CY8C6336BZI_BUD13 - default "CY8C6347BZI_BUD43" if SOC_CY8C6347BZI_BUD43 - default "CY8C6347BZI_BUD33" if SOC_CY8C6347BZI_BUD33 - default "CY8C6347BZI_BUD53" if SOC_CY8C6347BZI_BUD53 - default "CY8C6337BZI_BLF13" if SOC_CY8C6337BZI_BLF13 - default "CY8C6136FDI_F42" if SOC_CY8C6136FDI_F42 - default "CY8C6247FDI_D52" if SOC_CY8C6247FDI_D52 - default "CY8C6136FTI_F42" if SOC_CY8C6136FTI_F42 - default "CY8C6247FTI_D52" if SOC_CY8C6247FTI_D52 - default "CY8C6247BZI_AUD54" if SOC_CY8C6247BZI_AUD54 - default "CY8C6336BZI_BLF04" if SOC_CY8C6336BZI_BLF04 - default "CY8C6316BZI_BLF04" if SOC_CY8C6316BZI_BLF04 - default "CY8C6316BZI_BLF54" if SOC_CY8C6316BZI_BLF54 - default "CY8C6336BZI_BLD14" if SOC_CY8C6336BZI_BLD14 - default "CY8C6347BZI_BLD44" if SOC_CY8C6347BZI_BLD44 - default "CY8C6347BZI_BLD34" if SOC_CY8C6347BZI_BLD34 - default "CY8C6347BZI_BLD54" if SOC_CY8C6347BZI_BLD54 - default "CY8C6247BFI_D54" if SOC_CY8C6247BFI_D54 - default "CYBLE_416045_02_device" if SOC_CYBLE_416045_02 - default "CY8C6347FMI_BUD53" if SOC_CY8C6347FMI_BUD53 - default "CY8C6347FMI_BUD13" if SOC_CY8C6347FMI_BUD13 - default "CY8C6347FMI_BUD43" if SOC_CY8C6347FMI_BUD43 - default "CY8C6347FMI_BUD33" if SOC_CY8C6347FMI_BUD33 - default "CY8C6137WI_F54" if SOC_CY8C6137WI_F54 - default "CY8C6117WI_F34" if SOC_CY8C6117WI_F34 - default "CY8C6247WI_D54" if SOC_CY8C6247WI_D54 - default "CY8C6336LQI_BLF02" if SOC_CY8C6336LQI_BLF02 - default "CY8C6336LQI_BLF42" if SOC_CY8C6336LQI_BLF42 - default "CY8C6347LQI_BLD52" if SOC_CY8C6347LQI_BLD52 - default "CYB06447BZI_BLD54" if SOC_CYB06447BZI_BLD54 - default "CYB06447BZI_BLD53" if SOC_CYB06447BZI_BLD53 - default "CYB06447BZI_D54" if SOC_CYB06447BZI_D54 - default "CYB0644ABZI_S2D44" if SOC_CYB0644ABZI_S2D44 - default "CYS0644ABZI_S2D44" if SOC_CYS0644ABZI_S2D44 - default "CY8C624ABZI_S2D44A0" if SOC_CY8C624ABZI_S2D44A0 - default "CY8C624ABZI_S2D44" if SOC_CY8C624ABZI_S2D44 - default "CY8C624AAZI_S2D44" if SOC_CY8C624AAZI_S2D44 - default "CY8C624AFNI_S2D43" if SOC_CY8C624AFNI_S2D43 - default "CY8C624ABZI_S2D04" if SOC_CY8C624ABZI_S2D04 - default "CY8C624ABZI_S2D14" if SOC_CY8C624ABZI_S2D14 - default "CY8C624AAZI_S2D14" if SOC_CY8C624AAZI_S2D14 - default "CY8C6248AZI_S2D14" if SOC_CY8C6248AZI_S2D14 - default "CY8C6248BZI_S2D44" if SOC_CY8C6248BZI_S2D44 - default "CY8C6248AZI_S2D44" if SOC_CY8C6248AZI_S2D44 - default "CY8C6248FNI_S2D43" if SOC_CY8C6248FNI_S2D43 - default "CY8C614ABZI_S2F04" if SOC_CY8C614ABZI_S2F04 - default "CY8C614AAZI_S2F04" if SOC_CY8C614AAZI_S2F04 - default "CY8C614AFNI_S2F03" if SOC_CY8C614AFNI_S2F03 - default "CY8C614AAZI_S2F14" if SOC_CY8C614AAZI_S2F14 - default "CY8C614ABZI_S2F44" if SOC_CY8C614ABZI_S2F44 - default "CY8C614AAZI_S2F44" if SOC_CY8C614AAZI_S2F44 - default "CY8C614AFNI_S2F43" if SOC_CY8C614AFNI_S2F43 - default "CY8C6148BZI_S2F44" if SOC_CY8C6148BZI_S2F44 - default "CY8C6148AZI_S2F44" if SOC_CY8C6148AZI_S2F44 - default "CY8C6148FNI_S2F43" if SOC_CY8C6148FNI_S2F43 - default "CY8C624ABZI_D44" if SOC_CY8C624ABZI_D44 - default "CY8C624ALQI_S2D42" if SOC_CY8C624ALQI_S2D42 - default "CY8C624ALQI_S2D02" if SOC_CY8C624ALQI_S2D02 - default "CY8C6248LQI_S2D42" if SOC_CY8C6248LQI_S2D42 - default "CY8C6248LQI_S2D02" if SOC_CY8C6248LQI_S2D02 - default "CY8C614ALQI_S2F42" if SOC_CY8C614ALQI_S2F42 - default "CY8C614ALQI_S2F02" if SOC_CY8C614ALQI_S2F02 - default "CY8C6148LQI_S2F42" if SOC_CY8C6148LQI_S2F42 - default "CY8C6148LQI_S2F02" if SOC_CY8C6148LQI_S2F02 - default "CY8C6244AZI_S4D92" if SOC_CY8C6244AZI_S4D92 - default "CY8C6244LQI_S4D92" if SOC_CY8C6244LQI_S4D92 - default "CY8C6244AZI_S4D93" if SOC_CY8C6244AZI_S4D93 - default "CY8C6244AZI_S4D82" if SOC_CY8C6244AZI_S4D82 - default "CY8C6244LQI_S4D82" if SOC_CY8C6244LQI_S4D82 - default "CY8C6244AZI_S4D83" if SOC_CY8C6244AZI_S4D83 - default "CY8C6244AZI_S4D62" if SOC_CY8C6244AZI_S4D62 - default "CY8C6244LQI_S4D62" if SOC_CY8C6244LQI_S4D62 - default "CY8C6244AZI_S4D12" if SOC_CY8C6244AZI_S4D12 - default "CY8C6244LQI_S4D12" if SOC_CY8C6244LQI_S4D12 - default "CY8C6144AZI_S4F92" if SOC_CY8C6144AZI_S4F92 - default "CY8C6144LQI_S4F92" if SOC_CY8C6144LQI_S4F92 - default "CY8C6144AZI_S4F93" if SOC_CY8C6144AZI_S4F93 - default "CY8C6144AZI_S4F82" if SOC_CY8C6144AZI_S4F82 - default "CY8C6144LQI_S4F82" if SOC_CY8C6144LQI_S4F82 - default "CY8C6144AZI_S4F83" if SOC_CY8C6144AZI_S4F83 - default "CY8C6144AZI_S4F62" if SOC_CY8C6144AZI_S4F62 - default "CY8C6144LQI_S4F62" if SOC_CY8C6144LQI_S4F62 - default "CY8C6144AZI_S4F12" if SOC_CY8C6144AZI_S4F12 - default "CY8C6144LQI_S4F12" if SOC_CY8C6144LQI_S4F12 diff --git a/soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m0 b/soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m0 deleted file mode 100644 index df5e232dc0f0f3..00000000000000 --- a/soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m0 +++ /dev/null @@ -1,10 +0,0 @@ -# Cypress PSoC6 CM0 platform configuration options -# Copyright (c) 2018, Cypress -# SPDX-License-Identifier: Apache-2.0 - -if SOC_CY8C6247_M0 || SOC_CY8C6347_M0 - -config NUM_IRQS - default 32 - -endif # SOC_CY8C6247_M0 || SOC_CY8C6347_M0 diff --git a/soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m4 b/soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m4 deleted file mode 100644 index 975ea4fa7fb617..00000000000000 --- a/soc/cypress/psoc6/old/Kconfig.defconfig.psoc6_m4 +++ /dev/null @@ -1,10 +0,0 @@ -# Cypress PSoC6 CM4 platform configuration options -# Copyright (c) 2018, Cypress -# SPDX-License-Identifier: Apache-2.0 - -if SOC_CY8C6247_M4 || SOC_CY8C6347_M4 - -config NUM_IRQS - default 147 - -endif # SOC_CY8C6247_M4 || SOC_CY8C6347_M4 diff --git a/soc/cypress/psoc6/old/common/CMakeLists.txt b/soc/cypress/psoc6/old/common/CMakeLists.txt deleted file mode 100644 index aad2f32b66684d..00000000000000 --- a/soc/cypress/psoc6/old/common/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2021 ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -zephyr_include_directories(.) - -zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 soc_gpio.c) diff --git a/soc/infineon/cat1a/CMakeLists.txt b/soc/infineon/cat1a/CMakeLists.txt new file mode 100644 index 00000000000000..c08c13ac0cc9e4 --- /dev/null +++ b/soc/infineon/cat1a/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_FAMILY_PSOC6) + zephyr_include_directories(common) + zephyr_sources(common/soc.c) + + # Add sections + zephyr_linker_sources(NOINIT common/noinit.ld) + + # Add section for cm0p image ROM + zephyr_linker_sources(ROM_START SORT_KEY 0x0cm0p common/rom_cm0image.ld) + + # Add section for cm0p image RAM + zephyr_linker_sources(RAM_SECTIONS SORT_KEY 0 common/ram_cm0image.ld) + zephyr_linker_sources(RAMFUNC_SECTION SORT_KEY 0 common/ram_func.ld) + zephyr_linker_sources(RODATA SORT_KEY 0 common/rom.ld) + +endif() + +if(CONFIG_SOC_FAMILY_PSOC6_LEGACY) + zephyr_include_directories(psoc6_legacy) + zephyr_sources(psoc6_legacy/soc.c) + zephyr_sources(psoc6_legacy/soc_gpio.c) + + zephyr_linker_sources(NOINIT psoc6_legacy/noinit.ld) + zephyr_linker_sources(RWDATA psoc6_legacy/rwdata.ld) +endif() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/infineon/cat1a/Kconfig b/soc/infineon/cat1a/Kconfig new file mode 100644 index 00000000000000..f7e3e0b49b4777 --- /dev/null +++ b/soc/infineon/cat1a/Kconfig @@ -0,0 +1,62 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon CAT1A devices + +# Family definitions +config SOC_FAMILY_PSOC6 + select ARM + select CPU_CORTEX_M4 + select CPU_HAS_ARM_MPU + select DYNAMIC_INTERRUPTS + select CPU_HAS_FPU + select SOC_FAMILY_INFINEON_CAT1 + +config SOC_FAMILY_PSOC6_LEGACY + select ARM + select HAS_CYPRESS_DRIVERS + select CPU_CORTEX_M_HAS_SYSTICK + select CPU_HAS_ARM_MPU + +config SOC_FAMILY_PSOC6_LEGACY_M4 + select CPU_CORTEX_M4 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_FPU + +config SOC_FAMILY_PSOC6_LEGACY_M0 + select CPU_CORTEX_M0PLUS + select CPU_CORTEX_M_HAS_VTOR + +config SOC_PSOC6_M0_ENABLES_M4 + bool "Dual-core support [activate Cortex-M4]" + depends on SOC_FAMILY_PSOC6_LEGACY_M0 + help + Cortex-M0 CPU should boot Cortex-M4 + +if SOC_FAMILY_PSOC6 +## PSoC™ 6 Cortex M0+ prebuilt images +choice + prompt "PSoC™ 6 Cortex M0+ prebuilt images" + help + Choose the prebuilt application image to be executed on the Cortex-M0+ core of the PSoC™ 6 + dual-core MCU. The image is responsible for booting the Cortex-M4 on the device. + +config SOC_PSOC6_CM0P_IMAGE_SLEEP + bool "DeepSleep" + help + DeepSleep prebuilt application image is executed on the Cortex-M0+ core of the PSoC™ 6 BLE + dual-core MCU.The image is provided as C array ready to be compiled as part of the Cortex-M4 + application. The Cortex-M0+ application code is placed to internal flash by the Cortex-M4 + linker script. +endchoice + +config SOC_PSOC6_CM0P_IMAGE_ROM_SIZE + hex + default 0x2000 if SOC_PSOC6_CM0P_IMAGE_SLEEP + +config SOC_PSOC6_CM0P_IMAGE_RAM_SIZE + hex + default 0x2000 if SOC_PSOC6_CM0P_IMAGE_SLEEP + +endif # SOC_FAMILY_PSOC6 diff --git a/soc/infineon/cat1a/Kconfig.defconfig b/soc/infineon/cat1a/Kconfig.defconfig new file mode 100644 index 00000000000000..57e358eff8bc46 --- /dev/null +++ b/soc/infineon/cat1a/Kconfig.defconfig @@ -0,0 +1,10 @@ +# PSOC CAT1A Configuration + +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_INFINEON_CAT1A + +rsource "*/Kconfig.defconfig" + +endif # SOC_FAMILY_INFINEON_CAT1A diff --git a/soc/infineon/cat1a/Kconfig.soc b/soc/infineon/cat1a/Kconfig.soc new file mode 100644 index 00000000000000..a70e341dd410ab --- /dev/null +++ b/soc/infineon/cat1a/Kconfig.soc @@ -0,0 +1,61 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# MPNs definitions +rsource "*/Kconfig.soc" + +# Infineon CAT1A devices + +# Category definitions +config SOC_FAMILY_INFINEON_CAT1 + bool + +config SOC_FAMILY_INFINEON_CAT1A + bool + +# Family definitions +config SOC_FAMILY_PSOC6 + bool + +config SOC_FAMILY_PSOC6_LEGACY + bool + +config SOC_FAMILY_PSOC6_LEGACY_M4 + bool + +config SOC_FAMILY_PSOC6_LEGACY_M0 + bool + +# Cypress PSoC™ 6 MCU lines +config SOC_SERIES_PSOC6_60 + bool + select SOC_FAMILY_PSOC6 if !SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_INFINEON_CAT1A + +config SOC_SERIES_PSOC6_61 + bool + select SOC_FAMILY_PSOC6 if !SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_INFINEON_CAT1A + +config SOC_SERIES_PSOC6_62 + bool + select SOC_FAMILY_PSOC6 if !SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_INFINEON_CAT1A + +config SOC_SERIES_PSOC6_63 + bool + select SOC_FAMILY_PSOC6 if !SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_INFINEON_CAT1A + +config SOC_SERIES_PSOC6_64 + bool + select SOC_FAMILY_PSOC6 if !SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_INFINEON_CAT1A + +config SOC_SERIES + default "psoc6_60" if SOC_SERIES_PSOC6_60 + default "psoc6_61" if SOC_SERIES_PSOC6_61 + default "psoc6_62" if SOC_SERIES_PSOC6_62 + default "psoc6_63" if SOC_SERIES_PSOC6_63 + default "psoc6_64" if SOC_SERIES_PSOC6_64 diff --git a/soc/cypress/psoc6/new/noinit.ld b/soc/infineon/cat1a/common/noinit.ld similarity index 100% rename from soc/cypress/psoc6/new/noinit.ld rename to soc/infineon/cat1a/common/noinit.ld diff --git a/soc/cypress/psoc6/new/common/pinctrl_soc.h b/soc/infineon/cat1a/common/pinctrl_soc.h similarity index 100% rename from soc/cypress/psoc6/new/common/pinctrl_soc.h rename to soc/infineon/cat1a/common/pinctrl_soc.h diff --git a/soc/cypress/psoc6/new/ram_cm0image.ld b/soc/infineon/cat1a/common/ram_cm0image.ld similarity index 100% rename from soc/cypress/psoc6/new/ram_cm0image.ld rename to soc/infineon/cat1a/common/ram_cm0image.ld diff --git a/soc/cypress/psoc6/new/ram_func.ld b/soc/infineon/cat1a/common/ram_func.ld similarity index 100% rename from soc/cypress/psoc6/new/ram_func.ld rename to soc/infineon/cat1a/common/ram_func.ld diff --git a/soc/cypress/psoc6/new/rom.ld b/soc/infineon/cat1a/common/rom.ld similarity index 100% rename from soc/cypress/psoc6/new/rom.ld rename to soc/infineon/cat1a/common/rom.ld diff --git a/soc/cypress/psoc6/new/rom_cm0image.ld b/soc/infineon/cat1a/common/rom_cm0image.ld similarity index 100% rename from soc/cypress/psoc6/new/rom_cm0image.ld rename to soc/infineon/cat1a/common/rom_cm0image.ld diff --git a/soc/cypress/psoc6/new/soc.c b/soc/infineon/cat1a/common/soc.c similarity index 100% rename from soc/cypress/psoc6/new/soc.c rename to soc/infineon/cat1a/common/soc.c diff --git a/soc/cypress/psoc6/new/soc.h b/soc/infineon/cat1a/common/soc.h similarity index 100% rename from soc/cypress/psoc6/new/soc.h rename to soc/infineon/cat1a/common/soc.h diff --git a/soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_01 b/soc/infineon/cat1a/psoc6_01/Kconfig.defconfig similarity index 73% rename from soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_01 rename to soc/infineon/cat1a/psoc6_01/Kconfig.defconfig index 3120bfdded237d..aec3e32650c800 100644 --- a/soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_01 +++ b/soc/infineon/cat1a/psoc6_01/Kconfig.defconfig @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or # an affiliate of Cypress Semiconductor Corporation # SPDX-License-Identifier: Apache-2.0 @@ -10,6 +10,9 @@ config NUM_IRQS default 32 if CPU_CORTEX_M0PLUS default 147 if CPU_CORTEX_M4 +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 100000000 + # add additional die specific params endif # SOC_DIE_PSOC6_01 diff --git a/soc/infineon/cat1a/psoc6_01/Kconfig.soc b/soc/infineon/cat1a/psoc6_01/Kconfig.soc new file mode 100644 index 00000000000000..3380db75d79d63 --- /dev/null +++ b/soc/infineon/cat1a/psoc6_01/Kconfig.soc @@ -0,0 +1,483 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# SOC die +config SOC_DIE_PSOC6_01 + bool + +# SOC packages +config SOC_PACKAGE_PSOC6_01_124_BGA + bool + +config SOC_PACKAGE_PSOC6_01_116_BGA_BLE + bool + +config SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE + bool + +config SOC_PACKAGE_PSOC6_01_80_WLCSP + bool + +config SOC_PACKAGE_PSOC6_01_116_BGA_USB + bool + +config SOC_PACKAGE_PSOC6_01_124_BGA_SIP + bool + +config SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB + bool + +config SOC_PACKAGE_PSOC6_01_68_QFN_BLE + bool + +# Infineon PSoC6_01 series MCUs +config SOC_CY8C6036BZI_F04 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_60 + +config SOC_CY8C6016BZI_F04 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_60 + +config SOC_CY8C6116BZI_F54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6136BZI_F14 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6136BZI_F34 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6137BZI_F14 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6137BZI_F34 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6137BZI_F54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6117BZI_F34 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6246BZI_D04 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6247BZI_D44 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6247BZI_D34 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6247BZI_D54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6336BZI_BLF03 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6316BZI_BLF03 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6316BZI_BLF53 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6336BZI_BLD13 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BLD43 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BLD33 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BLD53 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BLD13 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BLD43 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BLD33 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BLD53 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6137FDI_F02 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6117FDI_F02 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6247FDI_D02 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6247FDI_D32 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6336BZI_BUD13 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BUD43 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BUD33 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BUD53 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6337BZI_BLF13 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6136FDI_F42 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6247FDI_D52 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6136FTI_F42 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6247FTI_D52 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_80_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6247BZI_AUD54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6336BZI_BLF04 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6316BZI_BLF04 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6316BZI_BLF54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6336BZI_BLD14 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BLD44 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BLD34 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347BZI_BLD54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6247BFI_D54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6347FMI_BUD53 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BUD13 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BUD43 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347FMI_BUD33 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE_USB + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6137WI_F54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6117WI_F34 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6247WI_D54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6336LQI_BLF02 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_68_QFN_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6336LQI_BLF42 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_68_QFN_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6347LQI_BLD52 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_68_QFN_BLE + select SOC_SERIES_PSOC6_63 + +config SOC_CY8C6247BTI_D54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6246BTI_D54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6147BTI_F54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6146BTI_F54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CYB06447BZI_BLD54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA_SIP + select SOC_SERIES_PSOC6_64 + +config SOC_CYB06447BZI_BLD53 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_64 + +config SOC_CYB06447BZI_D54 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_124_BGA + select SOC_SERIES_PSOC6_64 + +config SOC_CYBLE_416045_02 + bool + select SOC_DIE_PSOC6_01 + select SOC_PACKAGE_PSOC6_01_116_BGA_BLE + select SOC_SERIES_PSOC6_63 + +config SOC + default "cy8c6036bzi_f04" if SOC_CY8C6036BZI_F04 + default "cy8c6016bzi_f04" if SOC_CY8C6016BZI_F04 + default "cy8c6116bzi_f54" if SOC_CY8C6116BZI_F54 + default "cy8c6136bzi_f14" if SOC_CY8C6136BZI_F14 + default "cy8c6136bzi_f34" if SOC_CY8C6136BZI_F34 + default "cy8c6137bzi_f14" if SOC_CY8C6137BZI_F14 + default "cy8c6137bzi_f34" if SOC_CY8C6137BZI_F34 + default "cy8c6137bzi_f54" if SOC_CY8C6137BZI_F54 + default "cy8c6117bzi_f34" if SOC_CY8C6117BZI_F34 + default "cy8c6246bzi_d04" if SOC_CY8C6246BZI_D04 + default "cy8c6247bzi_d44" if SOC_CY8C6247BZI_D44 + default "cy8c6247bzi_d34" if SOC_CY8C6247BZI_D34 + default "cy8c6247bzi_d54" if SOC_CY8C6247BZI_D54 + default "cy8c6336bzi_blf03" if SOC_CY8C6336BZI_BLF03 + default "cy8c6316bzi_blf03" if SOC_CY8C6316BZI_BLF03 + default "cy8c6316bzi_blf53" if SOC_CY8C6316BZI_BLF53 + default "cy8c6336bzi_bld13" if SOC_CY8C6336BZI_BLD13 + default "cy8c6347bzi_bld43" if SOC_CY8C6347BZI_BLD43 + default "cy8c6347bzi_bld33" if SOC_CY8C6347BZI_BLD33 + default "cy8c6347bzi_bld53" if SOC_CY8C6347BZI_BLD53 + default "cy8c6347fmi_bld13" if SOC_CY8C6347FMI_BLD13 + default "cy8c6347fmi_bld43" if SOC_CY8C6347FMI_BLD43 + default "cy8c6347fmi_bld33" if SOC_CY8C6347FMI_BLD33 + default "cy8c6347fmi_bld53" if SOC_CY8C6347FMI_BLD53 + default "cy8c6137fdi_f02" if SOC_CY8C6137FDI_F02 + default "cy8c6117fdi_f02" if SOC_CY8C6117FDI_F02 + default "cy8c6247fdi_d02" if SOC_CY8C6247FDI_D02 + default "cy8c6247fdi_d32" if SOC_CY8C6247FDI_D32 + default "cy8c6336bzi_bud13" if SOC_CY8C6336BZI_BUD13 + default "cy8c6347bzi_bud43" if SOC_CY8C6347BZI_BUD43 + default "cy8c6347bzi_bud33" if SOC_CY8C6347BZI_BUD33 + default "cy8c6347bzi_bud53" if SOC_CY8C6347BZI_BUD53 + default "cy8c6337bzi_blf13" if SOC_CY8C6337BZI_BLF13 + default "cy8c6136fdi_f42" if SOC_CY8C6136FDI_F42 + default "cy8c6247fdi_d52" if SOC_CY8C6247FDI_D52 + default "cy8c6136fti_f42" if SOC_CY8C6136FTI_F42 + default "cy8c6247fti_d52" if SOC_CY8C6247FTI_D52 + default "cy8c6247bzi_aud54" if SOC_CY8C6247BZI_AUD54 + default "cy8c6336bzi_blf04" if SOC_CY8C6336BZI_BLF04 + default "cy8c6316bzi_blf04" if SOC_CY8C6316BZI_BLF04 + default "cy8c6316bzi_blf54" if SOC_CY8C6316BZI_BLF54 + default "cy8c6336bzi_bld14" if SOC_CY8C6336BZI_BLD14 + default "cy8c6347bzi_bld44" if SOC_CY8C6347BZI_BLD44 + default "cy8c6347bzi_bld34" if SOC_CY8C6347BZI_BLD34 + default "cy8c6347bzi_bld54" if SOC_CY8C6347BZI_BLD54 + default "cy8c6247bfi_d54" if SOC_CY8C6247BFI_D54 + default "cy8c6347fmi_bud53" if SOC_CY8C6347FMI_BUD53 + default "cy8c6347fmi_bud13" if SOC_CY8C6347FMI_BUD13 + default "cy8c6347fmi_bud43" if SOC_CY8C6347FMI_BUD43 + default "cy8c6347fmi_bud33" if SOC_CY8C6347FMI_BUD33 + default "cy8c6137wi_f54" if SOC_CY8C6137WI_F54 + default "cy8c6117wi_f34" if SOC_CY8C6117WI_F34 + default "cy8c6247wi_d54" if SOC_CY8C6247WI_D54 + default "cy8c6336lqi_blf02" if SOC_CY8C6336LQI_BLF02 + default "cy8c6336lqi_blf42" if SOC_CY8C6336LQI_BLF42 + default "cy8c6347lqi_bld52" if SOC_CY8C6347LQI_BLD52 + default "cy8c6247bti_d54" if SOC_CY8C6247BTI_D54 + default "cy8c6246bti_d54" if SOC_CY8C6246BTI_D54 + default "cy8c6147bti_f54" if SOC_CY8C6147BTI_F54 + default "cy8c6146bti_f54" if SOC_CY8C6146BTI_F54 + default "cyb06447bzi_bld54" if SOC_CYB06447BZI_BLD54 + default "cyb06447bzi_bld53" if SOC_CYB06447BZI_BLD53 + default "cyb06447bzi_d54" if SOC_CYB06447BZI_D54 + default "cyble_416045_02" if SOC_CYBLE_416045_02 diff --git a/soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_02 b/soc/infineon/cat1a/psoc6_02/Kconfig.defconfig similarity index 65% rename from soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_02 rename to soc/infineon/cat1a/psoc6_02/Kconfig.defconfig index b50a91cff1efeb..65c86f0b831b68 100644 --- a/soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_02 +++ b/soc/infineon/cat1a/psoc6_02/Kconfig.defconfig @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or # an affiliate of Cypress Semiconductor Corporation # SPDX-License-Identifier: Apache-2.0 @@ -7,9 +7,12 @@ if SOC_DIE_PSOC6_02 config NUM_IRQS - default 32 if CPU_CORTEX_M0PLUS + default 16 if CPU_CORTEX_M0PLUS default 168 if CPU_CORTEX_M4 +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 100000000 + # add additional die specific params endif # SOC_DIE_PSOC6_02 diff --git a/soc/infineon/cat1a/psoc6_02/Kconfig.soc b/soc/infineon/cat1a/psoc6_02/Kconfig.soc new file mode 100644 index 00000000000000..1a3d7e054673e5 --- /dev/null +++ b/soc/infineon/cat1a/psoc6_02/Kconfig.soc @@ -0,0 +1,254 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# SOC die +config SOC_DIE_PSOC6_02 + bool + +# SOC packages +config SOC_PACKAGE_PSOC6_02_124_BGA + bool + +config SOC_PACKAGE_PSOC6_02_100_WLCSP + bool + +config SOC_PACKAGE_PSOC6_02_128_TQFP + bool + +config SOC_PACKAGE_PSOC6_02_68_QFN + bool + +# Infineon PSoC6_02 series MCUs +config SOC_CYB0644ABZI_S2D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_64 + +config SOC_CYS0644ABZI_S2D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_64 + +config SOC_CYS0644AFNI_S2D43 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_100_WLCSP + select SOC_SERIES_PSOC6_64 + +config SOC_CY8C624ABZI_S2D44A0 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624ABZI_S2D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624AAZI_S2D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624AFNI_S2D43 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_100_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624ABZI_S2D04 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624ABZI_S2D14 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624AAZI_S2D14 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6248AZI_S2D14 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6248BZI_S2D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6248AZI_S2D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6248FNI_S2D43 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_100_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C614ABZI_S2F04 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614AAZI_S2F04 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614AFNI_S2F03 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_100_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614AAZI_S2F14 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614ABZI_S2F44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614AAZI_S2F44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614AFNI_S2F43 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_100_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6148BZI_S2F44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6148AZI_S2F44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_128_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6148FNI_S2F43 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_100_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C624ABZI_D44 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_124_BGA + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624ALQI_S2D42 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C624ALQI_S2D02 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6248LQI_S2D42 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6248LQI_S2D02 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C614ALQI_S2F42 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C614ALQI_S2F02 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6148LQI_S2F42 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6148LQI_S2F02 + bool + select SOC_DIE_PSOC6_02 + select SOC_PACKAGE_PSOC6_02_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC + default "cyb0644abzi_s2d44" if SOC_CYB0644ABZI_S2D44 + default "cys0644abzi_s2d44" if SOC_CYS0644ABZI_S2D44 + default "cys0644afni_s2d43" if SOC_CYS0644AFNI_S2D43 + default "cy8c624abzi_s2d44a0" if SOC_CY8C624ABZI_S2D44A0 + default "cy8c624abzi_s2d44" if SOC_CY8C624ABZI_S2D44 + default "cy8c624aazi_s2d44" if SOC_CY8C624AAZI_S2D44 + default "cy8c624afni_s2d43" if SOC_CY8C624AFNI_S2D43 + default "cy8c624abzi_s2d04" if SOC_CY8C624ABZI_S2D04 + default "cy8c624abzi_s2d14" if SOC_CY8C624ABZI_S2D14 + default "cy8c624aazi_s2d14" if SOC_CY8C624AAZI_S2D14 + default "cy8c6248azi_s2d14" if SOC_CY8C6248AZI_S2D14 + default "cy8c6248bzi_s2d44" if SOC_CY8C6248BZI_S2D44 + default "cy8c6248azi_s2d44" if SOC_CY8C6248AZI_S2D44 + default "cy8c6248fni_s2d43" if SOC_CY8C6248FNI_S2D43 + default "cy8c614abzi_s2f04" if SOC_CY8C614ABZI_S2F04 + default "cy8c614aazi_s2f04" if SOC_CY8C614AAZI_S2F04 + default "cy8c614afni_s2f03" if SOC_CY8C614AFNI_S2F03 + default "cy8c614aazi_s2f14" if SOC_CY8C614AAZI_S2F14 + default "cy8c614abzi_s2f44" if SOC_CY8C614ABZI_S2F44 + default "cy8c614aazi_s2f44" if SOC_CY8C614AAZI_S2F44 + default "cy8c614afni_s2f43" if SOC_CY8C614AFNI_S2F43 + default "cy8c6148bzi_s2f44" if SOC_CY8C6148BZI_S2F44 + default "cy8c6148azi_s2f44" if SOC_CY8C6148AZI_S2F44 + default "cy8c6148fni_s2f43" if SOC_CY8C6148FNI_S2F43 + default "cy8c624abzi_d44" if SOC_CY8C624ABZI_D44 + default "cy8c624alqi_s2d42" if SOC_CY8C624ALQI_S2D42 + default "cy8c624alqi_s2d02" if SOC_CY8C624ALQI_S2D02 + default "cy8c6248lqi_s2d42" if SOC_CY8C6248LQI_S2D42 + default "cy8c6248lqi_s2d02" if SOC_CY8C6248LQI_S2D02 + default "cy8c614alqi_s2f42" if SOC_CY8C614ALQI_S2F42 + default "cy8c614alqi_s2f02" if SOC_CY8C614ALQI_S2F02 + default "cy8c6148lqi_s2f42" if SOC_CY8C6148LQI_S2F42 + default "cy8c6148lqi_s2f02" if SOC_CY8C6148LQI_S2F02 diff --git a/soc/infineon/cat1a/psoc6_03/Kconfig.defconfig b/soc/infineon/cat1a/psoc6_03/Kconfig.defconfig new file mode 100644 index 00000000000000..9986f512d3ea8e --- /dev/null +++ b/soc/infineon/cat1a/psoc6_03/Kconfig.defconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon PSoC6_03 based MCU default configuration + +if SOC_DIE_PSOC6_03 + +config NUM_IRQS + default 16 if CPU_CORTEX_M0PLUS + default 174 if CPU_CORTEX_M4 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 100000000 + +# add additional die specific params + +endif # SOC_DIE_PSOC6_03 diff --git a/soc/infineon/cat1a/psoc6_03/Kconfig.soc b/soc/infineon/cat1a/psoc6_03/Kconfig.soc new file mode 100644 index 00000000000000..1863a4fd22988c --- /dev/null +++ b/soc/infineon/cat1a/psoc6_03/Kconfig.soc @@ -0,0 +1,209 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# SOC die +config SOC_DIE_PSOC6_03 + bool + +# SOC packages +config SOC_PACKAGE_PSOC6_03_100_TQFP + bool + +config SOC_PACKAGE_PSOC6_03_68_QFN + bool + +config SOC_PACKAGE_PSOC6_03_49_WLCSP + bool + +# Infineon PSoC6_03 series MCUs +config SOC_CY8C6245AZI_S3D72 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245LQI_S3D72 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245FNI_S3D71 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_49_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245AZI_S3D62 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245LQI_S3D62 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245AZI_S3D42 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245LQI_S3D42 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CYB06445LQI_S3D42 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_64 + +config SOC_CY8C6245FNI_S3D41 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_49_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245AZI_S3D12 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245LQI_S3D12 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245FNI_S3D11 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_49_WLCSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245AZI_S3D02 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6245LQI_S3D02 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6145AZI_S3F72 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145LQI_S3F72 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145FNI_S3F71 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_49_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145AZI_S3F62 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145LQI_S3F62 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145AZI_S3F42 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145LQI_S3F42 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145FNI_S3F41 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_49_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145AZI_S3F12 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145LQI_S3F12 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145FNI_S3F11 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_49_WLCSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145AZI_S3F02 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_100_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6145LQI_S3F02 + bool + select SOC_DIE_PSOC6_03 + select SOC_PACKAGE_PSOC6_03_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC + default "cy8c6245azi_s3d72" if SOC_CY8C6245AZI_S3D72 + default "cy8c6245lqi_s3d72" if SOC_CY8C6245LQI_S3D72 + default "cy8c6245fni_s3d71" if SOC_CY8C6245FNI_S3D71 + default "cy8c6245azi_s3d62" if SOC_CY8C6245AZI_S3D62 + default "cy8c6245lqi_s3d62" if SOC_CY8C6245LQI_S3D62 + default "cy8c6245azi_s3d42" if SOC_CY8C6245AZI_S3D42 + default "cy8c6245lqi_s3d42" if SOC_CY8C6245LQI_S3D42 + default "cyb06445lqi_s3d42" if SOC_CYB06445LQI_S3D42 + default "cy8c6245fni_s3d41" if SOC_CY8C6245FNI_S3D41 + default "cy8c6245azi_s3d12" if SOC_CY8C6245AZI_S3D12 + default "cy8c6245lqi_s3d12" if SOC_CY8C6245LQI_S3D12 + default "cy8c6245fni_s3d11" if SOC_CY8C6245FNI_S3D11 + default "cy8c6245azi_s3d02" if SOC_CY8C6245AZI_S3D02 + default "cy8c6245lqi_s3d02" if SOC_CY8C6245LQI_S3D02 + default "cy8c6145azi_s3f72" if SOC_CY8C6145AZI_S3F72 + default "cy8c6145lqi_s3f72" if SOC_CY8C6145LQI_S3F72 + default "cy8c6145fni_s3f71" if SOC_CY8C6145FNI_S3F71 + default "cy8c6145azi_s3f62" if SOC_CY8C6145AZI_S3F62 + default "cy8c6145lqi_s3f62" if SOC_CY8C6145LQI_S3F62 + default "cy8c6145azi_s3f42" if SOC_CY8C6145AZI_S3F42 + default "cy8c6145lqi_s3f42" if SOC_CY8C6145LQI_S3F42 + default "cy8c6145fni_s3f41" if SOC_CY8C6145FNI_S3F41 + default "cy8c6145azi_s3f12" if SOC_CY8C6145AZI_S3F12 + default "cy8c6145lqi_s3f12" if SOC_CY8C6145LQI_S3F12 + default "cy8c6145fni_s3f11" if SOC_CY8C6145FNI_S3F11 + default "cy8c6145azi_s3f02" if SOC_CY8C6145AZI_S3F02 + default "cy8c6145lqi_s3f02" if SOC_CY8C6145LQI_S3F02 diff --git a/soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_04 b/soc/infineon/cat1a/psoc6_04/Kconfig.defconfig similarity index 64% rename from soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_04 rename to soc/infineon/cat1a/psoc6_04/Kconfig.defconfig index 30908b188a729d..77de960a053b64 100644 --- a/soc/cypress/psoc6/new/Kconfig.defconfig.psoc6_04 +++ b/soc/infineon/cat1a/psoc6_04/Kconfig.defconfig @@ -1,6 +1,5 @@ -# Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or # an affiliate of Cypress Semiconductor Corporation -# Copyright (c) David Ullmann # SPDX-License-Identifier: Apache-2.0 # Infineon PSoC6_04 based MCU default configuration @@ -11,4 +10,9 @@ config NUM_IRQS default 16 if CPU_CORTEX_M0PLUS default 175 if CPU_CORTEX_M4 +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 100000000 + +# add additional die specific params + endif # SOC_DIE_PSOC6_04 diff --git a/soc/infineon/cat1a/psoc6_04/Kconfig.soc b/soc/infineon/cat1a/psoc6_04/Kconfig.soc new file mode 100644 index 00000000000000..b70ed63313cb52 --- /dev/null +++ b/soc/infineon/cat1a/psoc6_04/Kconfig.soc @@ -0,0 +1,275 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# SOC die +config SOC_DIE_PSOC6_04 + bool + +# SOC packages +config SOC_PACKAGE_PSOC6_04_64_TQFP + bool + +config SOC_PACKAGE_PSOC6_04_68_QFN + bool + +config SOC_PACKAGE_PSOC6_04_80_TQFP + bool + +config SOC_PACKAGE_PSOC6_04_80_M_CSP + bool + +# Infineon PSoC6_04 series MCUs +config SOC_CY8C6244AZI_S4D92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244LQI_S4D92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244AZI_S4D93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244AZI_S4D82 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244LQI_S4D82 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244AZI_S4D83 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244AZI_S4D62 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244LQI_S4D62 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244AZI_S4D12 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244LQI_S4D12 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6144AZI_S4F92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144LQI_S4F92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144AZI_S4F93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144AZI_S4F82 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144LQI_S4F82 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144AZI_S4F83 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144AZI_S4F62 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144LQI_S4F62 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144AZI_S4F12 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144LQI_S4F12 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6244AZQ_S4D92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244LQQ_S4D92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244AZQ_S4D93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_TQFP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6144AZQ_S4F92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_64_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144LQQ_S4F92 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_68_QFN + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144AZQ_S4F93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_TQFP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6244FMI_S4D93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244FMI_S4D73 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244FMI_S4D53 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244FMI_S4D03 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6244FMQ_S4D93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_62 + +config SOC_CY8C6144FMI_S4F93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144FMI_S4F73 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144FMI_S4F53 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144FMI_S4F03 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_61 + +config SOC_CY8C6144FMQ_S4F93 + bool + select SOC_DIE_PSOC6_04 + select SOC_PACKAGE_PSOC6_04_80_M_CSP + select SOC_SERIES_PSOC6_61 + +config SOC + default "cy8c6244azi_s4d92" if SOC_CY8C6244AZI_S4D92 + default "cy8c6244lqi_s4d92" if SOC_CY8C6244LQI_S4D92 + default "cy8c6244azi_s4d93" if SOC_CY8C6244AZI_S4D93 + default "cy8c6244azi_s4d82" if SOC_CY8C6244AZI_S4D82 + default "cy8c6244lqi_s4d82" if SOC_CY8C6244LQI_S4D82 + default "cy8c6244azi_s4d83" if SOC_CY8C6244AZI_S4D83 + default "cy8c6244azi_s4d62" if SOC_CY8C6244AZI_S4D62 + default "cy8c6244lqi_s4d62" if SOC_CY8C6244LQI_S4D62 + default "cy8c6244azi_s4d12" if SOC_CY8C6244AZI_S4D12 + default "cy8c6244lqi_s4d12" if SOC_CY8C6244LQI_S4D12 + default "cy8c6144azi_s4f92" if SOC_CY8C6144AZI_S4F92 + default "cy8c6144lqi_s4f92" if SOC_CY8C6144LQI_S4F92 + default "cy8c6144azi_s4f93" if SOC_CY8C6144AZI_S4F93 + default "cy8c6144azi_s4f82" if SOC_CY8C6144AZI_S4F82 + default "cy8c6144lqi_s4f82" if SOC_CY8C6144LQI_S4F82 + default "cy8c6144azi_s4f83" if SOC_CY8C6144AZI_S4F83 + default "cy8c6144azi_s4f62" if SOC_CY8C6144AZI_S4F62 + default "cy8c6144lqi_s4f62" if SOC_CY8C6144LQI_S4F62 + default "cy8c6144azi_s4f12" if SOC_CY8C6144AZI_S4F12 + default "cy8c6144lqi_s4f12" if SOC_CY8C6144LQI_S4F12 + default "cy8c6244azq_s4d92" if SOC_CY8C6244AZQ_S4D92 + default "cy8c6244lqq_s4d92" if SOC_CY8C6244LQQ_S4D92 + default "cy8c6244azq_s4d93" if SOC_CY8C6244AZQ_S4D93 + default "cy8c6144azq_s4f92" if SOC_CY8C6144AZQ_S4F92 + default "cy8c6144lqq_s4f92" if SOC_CY8C6144LQQ_S4F92 + default "cy8c6144azq_s4f93" if SOC_CY8C6144AZQ_S4F93 + default "cy8c6244fmi_s4d93" if SOC_CY8C6244FMI_S4D93 + default "cy8c6244fmi_s4d73" if SOC_CY8C6244FMI_S4D73 + default "cy8c6244fmi_s4d53" if SOC_CY8C6244FMI_S4D53 + default "cy8c6244fmi_s4d03" if SOC_CY8C6244FMI_S4D03 + default "cy8c6244fmq_s4d93" if SOC_CY8C6244FMQ_S4D93 + default "cy8c6144fmi_s4f93" if SOC_CY8C6144FMI_S4F93 + default "cy8c6144fmi_s4f73" if SOC_CY8C6144FMI_S4F73 + default "cy8c6144fmi_s4f53" if SOC_CY8C6144FMI_S4F53 + default "cy8c6144fmi_s4f03" if SOC_CY8C6144FMI_S4F03 + default "cy8c6144fmq_s4f93" if SOC_CY8C6144FMQ_S4F93 diff --git a/soc/infineon/cat1a/psoc6_legacy/Kconfig.defconfig b/soc/infineon/cat1a/psoc6_legacy/Kconfig.defconfig new file mode 100644 index 00000000000000..c6da791fa963f4 --- /dev/null +++ b/soc/infineon/cat1a/psoc6_legacy/Kconfig.defconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon PSoC6 (Legacy) based MCU default configuration + +if SOC_FAMILY_PSOC6_LEGACY + +config NUM_IRQS + default 32 if CPU_CORTEX_M0PLUS + default 147 if CPU_CORTEX_M4 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 50000000 + +# add additional die specific params + +endif # SOC_FAMILY_PSOC6_LEGACY diff --git a/soc/infineon/cat1a/psoc6_legacy/Kconfig.soc b/soc/infineon/cat1a/psoc6_legacy/Kconfig.soc new file mode 100644 index 00000000000000..7cb8f8acde994d --- /dev/null +++ b/soc/infineon/cat1a/psoc6_legacy/Kconfig.soc @@ -0,0 +1,42 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon PSoC6 (legacy) series MCUs +config SOC_CY8C6247_M0 + bool + select SOC_SERIES_PSOC6_62 + select SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_PSOC6_LEGACY_M0 + +config SOC_CY8C6247_M4 + bool + select SOC_SERIES_PSOC6_62 + select SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_PSOC6_LEGACY_M4 + +config SOC_CY8C6347_M0 + bool + select SOC_SERIES_PSOC6_63 + select SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_PSOC6_LEGACY_M0 + +config SOC_CY8C6347_M4 + bool + select SOC_SERIES_PSOC6_63 + select SOC_FAMILY_PSOC6_LEGACY + select SOC_FAMILY_PSOC6_LEGACY_M4 + +config SOC_PART_NUMBER_CY8C6247BZI_D54 + bool + +config SOC_PART_NUMBER_CY8C6347BZI_BLD53 + bool + +config SOC + default "cy8c6247" if SOC_CY8C6247_M0 || SOC_CY8C6247_M4 + default "cy8c6347" if SOC_CY8C6347_M0 || SOC_CY8C6347_M4 + +config SOC_PART_NUMBER + default "CY8C6247BZI_D54" if SOC_PART_NUMBER_CY8C6247BZI_D54 + default "CY8C6347BZI_BLD53" if SOC_PART_NUMBER_CY8C6347BZI_BLD53 diff --git a/soc/cypress/psoc6/old/common/cypress_psoc6_dt.h b/soc/infineon/cat1a/psoc6_legacy/cypress_psoc6_dt.h similarity index 100% rename from soc/cypress/psoc6/old/common/cypress_psoc6_dt.h rename to soc/infineon/cat1a/psoc6_legacy/cypress_psoc6_dt.h diff --git a/soc/cypress/psoc6/old/noinit.ld b/soc/infineon/cat1a/psoc6_legacy/noinit.ld similarity index 100% rename from soc/cypress/psoc6/old/noinit.ld rename to soc/infineon/cat1a/psoc6_legacy/noinit.ld diff --git a/soc/cypress/psoc6/old/rwdata.ld b/soc/infineon/cat1a/psoc6_legacy/rwdata.ld similarity index 100% rename from soc/cypress/psoc6/old/rwdata.ld rename to soc/infineon/cat1a/psoc6_legacy/rwdata.ld diff --git a/soc/cypress/psoc6/old/soc.c b/soc/infineon/cat1a/psoc6_legacy/soc.c similarity index 100% rename from soc/cypress/psoc6/old/soc.c rename to soc/infineon/cat1a/psoc6_legacy/soc.c diff --git a/soc/cypress/psoc6/old/soc.h b/soc/infineon/cat1a/psoc6_legacy/soc.h similarity index 85% rename from soc/cypress/psoc6/old/soc.h rename to soc/infineon/cat1a/psoc6_legacy/soc.h index fe5e982cde156a..8bd23b04ec2ae0 100644 --- a/soc/cypress/psoc6/old/soc.h +++ b/soc/infineon/cat1a/psoc6_legacy/soc.h @@ -20,8 +20,8 @@ #ifndef _ASMLANGUAGE #include -#include "../common/soc_gpio.h" -#include "../common/cypress_psoc6_dt.h" +#include "soc_gpio.h" +#include "cypress_psoc6_dt.h" #endif /* !_ASMLANGUAGE */ diff --git a/soc/cypress/psoc6/old/common/soc_gpio.c b/soc/infineon/cat1a/psoc6_legacy/soc_gpio.c similarity index 100% rename from soc/cypress/psoc6/old/common/soc_gpio.c rename to soc/infineon/cat1a/psoc6_legacy/soc_gpio.c diff --git a/soc/cypress/psoc6/old/common/soc_gpio.h b/soc/infineon/cat1a/psoc6_legacy/soc_gpio.h similarity index 100% rename from soc/cypress/psoc6/old/common/soc_gpio.h rename to soc/infineon/cat1a/psoc6_legacy/soc_gpio.h diff --git a/soc/cypress/soc.yml b/soc/infineon/cat1a/soc.yml similarity index 97% rename from soc/cypress/soc.yml rename to soc/infineon/cat1a/soc.yml index c973ed24b94123..a7d58a4a992407 100644 --- a/soc/cypress/soc.yml +++ b/soc/infineon/cat1a/soc.yml @@ -1,19 +1,5 @@ family: -- name: psoc6 - series: - - name: psoc62 - socs: - - name: cy8c6247 - cpuclusters: - - name: m0 - - name: m4 - - name: psoc63 - socs: - - name: cy8c6347 - cpuclusters: - - name: m0 - - name: m4 -- name: infineon_cat1 +- name: cat1a series: - name: psoc6 socs: @@ -63,7 +49,6 @@ family: - name: cy8c6347bzi_bld34 - name: cy8c6347bzi_bld54 - name: cy8c6247bfi_d54 - - name: cyble_416045_02 - name: cy8c6347fmi_bud53 - name: cy8c6347fmi_bud13 - name: cy8c6347fmi_bud43 @@ -129,3 +114,12 @@ family: - name: cy8c6144lqi_s4f62 - name: cy8c6144azi_s4f12 - name: cy8c6144lqi_s4f12 + - name: cyble_416045_02 + - name: cy8c6247 + cpuclusters: + - name: m0 + - name: m4 + - name: cy8c6347 + cpuclusters: + - name: m0 + - name: m4 diff --git a/soc/infineon/xmc/CMakeLists.txt b/soc/infineon/cat3/CMakeLists.txt similarity index 65% rename from soc/infineon/xmc/CMakeLists.txt rename to soc/infineon/cat3/CMakeLists.txt index 9aed50a0fd86ea..6c98bdb988075b 100644 --- a/soc/infineon/xmc/CMakeLists.txt +++ b/soc/infineon/cat3/CMakeLists.txt @@ -4,3 +4,5 @@ # Author: Parthiban Nallathambi add_subdirectory(${SOC_SERIES}) + +zephyr_compile_definitions($_${CONFIG_SOC_PART_NUMBER}) diff --git a/soc/infineon/xmc/Kconfig b/soc/infineon/cat3/Kconfig similarity index 100% rename from soc/infineon/xmc/Kconfig rename to soc/infineon/cat3/Kconfig diff --git a/soc/infineon/xmc/Kconfig.defconfig b/soc/infineon/cat3/Kconfig.defconfig similarity index 100% rename from soc/infineon/xmc/Kconfig.defconfig rename to soc/infineon/cat3/Kconfig.defconfig diff --git a/soc/infineon/xmc/Kconfig.soc b/soc/infineon/cat3/Kconfig.soc similarity index 100% rename from soc/infineon/xmc/Kconfig.soc rename to soc/infineon/cat3/Kconfig.soc diff --git a/soc/infineon/xmc/soc.yml b/soc/infineon/cat3/soc.yml similarity index 100% rename from soc/infineon/xmc/soc.yml rename to soc/infineon/cat3/soc.yml diff --git a/soc/infineon/xmc/xmc4xxx/CMakeLists.txt b/soc/infineon/cat3/xmc4xxx/CMakeLists.txt similarity index 100% rename from soc/infineon/xmc/xmc4xxx/CMakeLists.txt rename to soc/infineon/cat3/xmc4xxx/CMakeLists.txt diff --git a/soc/infineon/xmc/xmc4xxx/Kconfig b/soc/infineon/cat3/xmc4xxx/Kconfig similarity index 100% rename from soc/infineon/xmc/xmc4xxx/Kconfig rename to soc/infineon/cat3/xmc4xxx/Kconfig diff --git a/soc/infineon/xmc/xmc4xxx/Kconfig.defconfig b/soc/infineon/cat3/xmc4xxx/Kconfig.defconfig similarity index 100% rename from soc/infineon/xmc/xmc4xxx/Kconfig.defconfig rename to soc/infineon/cat3/xmc4xxx/Kconfig.defconfig diff --git a/soc/infineon/xmc/xmc4xxx/Kconfig.defconfig.xmc4500 b/soc/infineon/cat3/xmc4xxx/Kconfig.defconfig.xmc4500 similarity index 100% rename from soc/infineon/xmc/xmc4xxx/Kconfig.defconfig.xmc4500 rename to soc/infineon/cat3/xmc4xxx/Kconfig.defconfig.xmc4500 diff --git a/soc/infineon/xmc/xmc4xxx/Kconfig.defconfig.xmc4700 b/soc/infineon/cat3/xmc4xxx/Kconfig.defconfig.xmc4700 similarity index 100% rename from soc/infineon/xmc/xmc4xxx/Kconfig.defconfig.xmc4700 rename to soc/infineon/cat3/xmc4xxx/Kconfig.defconfig.xmc4700 diff --git a/soc/infineon/xmc/xmc4xxx/Kconfig.soc b/soc/infineon/cat3/xmc4xxx/Kconfig.soc similarity index 100% rename from soc/infineon/xmc/xmc4xxx/Kconfig.soc rename to soc/infineon/cat3/xmc4xxx/Kconfig.soc diff --git a/soc/infineon/xmc/xmc4xxx/noinit.ld b/soc/infineon/cat3/xmc4xxx/noinit.ld similarity index 100% rename from soc/infineon/xmc/xmc4xxx/noinit.ld rename to soc/infineon/cat3/xmc4xxx/noinit.ld diff --git a/soc/infineon/xmc/xmc4xxx/pinctrl_soc.h b/soc/infineon/cat3/xmc4xxx/pinctrl_soc.h similarity index 100% rename from soc/infineon/xmc/xmc4xxx/pinctrl_soc.h rename to soc/infineon/cat3/xmc4xxx/pinctrl_soc.h diff --git a/soc/infineon/xmc/xmc4xxx/soc.c b/soc/infineon/cat3/xmc4xxx/soc.c similarity index 100% rename from soc/infineon/xmc/xmc4xxx/soc.c rename to soc/infineon/cat3/xmc4xxx/soc.c diff --git a/soc/infineon/xmc/xmc4xxx/soc.h b/soc/infineon/cat3/xmc4xxx/soc.h similarity index 100% rename from soc/infineon/xmc/xmc4xxx/soc.h rename to soc/infineon/cat3/xmc4xxx/soc.h From 8dd97b678b3fdf8d87c35fcb404aeebcac062adc Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1035/1389] cy8cproto-063-ble: board: port cy8cproto-063-ble to HWMv2 Port board cy8cproto-063-ble to HWMv2 Signed-off-by: Nazar Palamar --- .../cy8cproto_063_ble/Kconfig.cy8cproto_063_ble | 0 .../cy8cproto_063_ble/Kconfig.defconfig | 0 .../cy8cproto_063_ble/board.cmake | 0 .../cy8cproto_063_ble/board.yml | 2 +- .../cy8cproto_063_ble-pinctrl.dtsi | 0 .../cy8cproto_063_ble/cy8cproto_063_ble.dts | 4 ++-- .../cy8cproto_063_ble/cy8cproto_063_ble.yaml | 3 ++- .../cy8cproto_063_ble/cy8cproto_063_ble_defconfig | 0 .../cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg | Bin .../cy8cproto_063_ble/doc/index.rst | 0 .../cy8cproto_063_ble/support/openocd.cfg | 0 11 files changed, 5 insertions(+), 4 deletions(-) rename boards/{cypress => infineon}/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/Kconfig.defconfig (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/board.cmake (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/board.yml (77%) rename boards/{cypress => infineon}/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/cy8cproto_063_ble.dts (95%) rename boards/{cypress => infineon}/cy8cproto_063_ble/cy8cproto_063_ble.yaml (92%) rename boards/{cypress => infineon}/cy8cproto_063_ble/cy8cproto_063_ble_defconfig (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/doc/index.rst (100%) rename boards/{cypress => infineon}/cy8cproto_063_ble/support/openocd.cfg (100%) diff --git a/boards/cypress/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble b/boards/infineon/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble similarity index 100% rename from boards/cypress/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble rename to boards/infineon/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble diff --git a/boards/cypress/cy8cproto_063_ble/Kconfig.defconfig b/boards/infineon/cy8cproto_063_ble/Kconfig.defconfig similarity index 100% rename from boards/cypress/cy8cproto_063_ble/Kconfig.defconfig rename to boards/infineon/cy8cproto_063_ble/Kconfig.defconfig diff --git a/boards/cypress/cy8cproto_063_ble/board.cmake b/boards/infineon/cy8cproto_063_ble/board.cmake similarity index 100% rename from boards/cypress/cy8cproto_063_ble/board.cmake rename to boards/infineon/cy8cproto_063_ble/board.cmake diff --git a/boards/cypress/cy8cproto_063_ble/board.yml b/boards/infineon/cy8cproto_063_ble/board.yml similarity index 77% rename from boards/cypress/cy8cproto_063_ble/board.yml rename to boards/infineon/cy8cproto_063_ble/board.yml index b35cb08ec2fcf6..6ef5bd8e9d7b81 100644 --- a/boards/cypress/cy8cproto_063_ble/board.yml +++ b/boards/infineon/cy8cproto_063_ble/board.yml @@ -1,5 +1,5 @@ board: name: cy8cproto_063_ble - vendor: cypress + vendor: infineon socs: - name: cyble_416045_02 diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi similarity index 100% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.dts b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.dts similarity index 95% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.dts rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.dts index e918f547bd26f4..0f96ff07a774f3 100644 --- a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.dts +++ b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.dts @@ -6,8 +6,8 @@ /dts-v1/; -#include -#include +#include +#include #include "cy8cproto_063_ble-pinctrl.dtsi" #include diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.yaml b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.yaml similarity index 92% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.yaml rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.yaml index 1aaef3040d38e8..db4f1ec95b001c 100644 --- a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.yaml +++ b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.yaml @@ -19,4 +19,5 @@ supported: - i2c - watchdog - spi -vendor: cypress + - timer +vendor: infineon diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble_defconfig b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble_defconfig similarity index 100% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble_defconfig rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble_defconfig diff --git a/boards/cypress/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg b/boards/infineon/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg similarity index 100% rename from boards/cypress/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg rename to boards/infineon/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg diff --git a/boards/cypress/cy8cproto_063_ble/doc/index.rst b/boards/infineon/cy8cproto_063_ble/doc/index.rst similarity index 100% rename from boards/cypress/cy8cproto_063_ble/doc/index.rst rename to boards/infineon/cy8cproto_063_ble/doc/index.rst diff --git a/boards/cypress/cy8cproto_063_ble/support/openocd.cfg b/boards/infineon/cy8cproto_063_ble/support/openocd.cfg similarity index 100% rename from boards/cypress/cy8cproto_063_ble/support/openocd.cfg rename to boards/infineon/cy8cproto_063_ble/support/openocd.cfg From 9a70e4ce283c0cb818d6947fac4b20f209e65c4b Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1036/1389] cy8ckit_062s4: board: port cy8ckit_062s4 to HWMv2 Port board cy8ckit_062s4 to HWMv2 Signed-off-by: Nazar Palamar --- .../cy8ckit_062s4/Kconfig.cy8ckit_062s4 | 0 .../{cypress => infineon}/cy8ckit_062s4/board.cmake | 0 .../{cypress => infineon}/cy8ckit_062s4/board.yml | 2 +- .../cy8ckit_062s4/cy8ckit_062s4.dts | 2 +- .../cy8ckit_062s4/cy8ckit_062s4.yaml | 2 +- .../cy8ckit_062s4/cy8ckit_062s4_defconfig | 0 .../cy8ckit_062s4/doc/img/cy8ckit_062s4.png | Bin .../cy8ckit_062s4/doc/index.rst | 0 8 files changed, 3 insertions(+), 3 deletions(-) rename boards/{cypress => infineon}/cy8ckit_062s4/Kconfig.cy8ckit_062s4 (100%) rename boards/{cypress => infineon}/cy8ckit_062s4/board.cmake (100%) rename boards/{cypress => infineon}/cy8ckit_062s4/board.yml (77%) rename boards/{cypress => infineon}/cy8ckit_062s4/cy8ckit_062s4.dts (93%) rename boards/{cypress => infineon}/cy8ckit_062s4/cy8ckit_062s4.yaml (93%) rename boards/{cypress => infineon}/cy8ckit_062s4/cy8ckit_062s4_defconfig (100%) rename boards/{cypress => infineon}/cy8ckit_062s4/doc/img/cy8ckit_062s4.png (100%) rename boards/{cypress => infineon}/cy8ckit_062s4/doc/index.rst (100%) diff --git a/boards/cypress/cy8ckit_062s4/Kconfig.cy8ckit_062s4 b/boards/infineon/cy8ckit_062s4/Kconfig.cy8ckit_062s4 similarity index 100% rename from boards/cypress/cy8ckit_062s4/Kconfig.cy8ckit_062s4 rename to boards/infineon/cy8ckit_062s4/Kconfig.cy8ckit_062s4 diff --git a/boards/cypress/cy8ckit_062s4/board.cmake b/boards/infineon/cy8ckit_062s4/board.cmake similarity index 100% rename from boards/cypress/cy8ckit_062s4/board.cmake rename to boards/infineon/cy8ckit_062s4/board.cmake diff --git a/boards/cypress/cy8ckit_062s4/board.yml b/boards/infineon/cy8ckit_062s4/board.yml similarity index 77% rename from boards/cypress/cy8ckit_062s4/board.yml rename to boards/infineon/cy8ckit_062s4/board.yml index adb45b87c07951..c460d9f050396e 100644 --- a/boards/cypress/cy8ckit_062s4/board.yml +++ b/boards/infineon/cy8ckit_062s4/board.yml @@ -1,5 +1,5 @@ board: name: cy8ckit_062s4 - vendor: cypress + vendor: infineon socs: - name: cy8c6244lqi_s4d92 diff --git a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.dts b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts similarity index 93% rename from boards/cypress/cy8ckit_062s4/cy8ckit_062s4.dts rename to boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts index 6695a24a4b88b4..457878a62b7a77 100644 --- a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.dts +++ b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts @@ -4,7 +4,7 @@ */ /dts-v1/; -#include +#include / { model = "Infineon PSoC 62S4 Pioneer Kit"; diff --git a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.yaml b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.yaml similarity index 93% rename from boards/cypress/cy8ckit_062s4/cy8ckit_062s4.yaml rename to boards/infineon/cy8ckit_062s4/cy8ckit_062s4.yaml index aaa7d0c8305517..4ab5c7580ecdd8 100644 --- a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.yaml +++ b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.yaml @@ -12,4 +12,4 @@ toolchain: - gnuarmemb supported: - gpio -vendor: cypress +vendor: infineon diff --git a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4_defconfig b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4_defconfig similarity index 100% rename from boards/cypress/cy8ckit_062s4/cy8ckit_062s4_defconfig rename to boards/infineon/cy8ckit_062s4/cy8ckit_062s4_defconfig diff --git a/boards/cypress/cy8ckit_062s4/doc/img/cy8ckit_062s4.png b/boards/infineon/cy8ckit_062s4/doc/img/cy8ckit_062s4.png similarity index 100% rename from boards/cypress/cy8ckit_062s4/doc/img/cy8ckit_062s4.png rename to boards/infineon/cy8ckit_062s4/doc/img/cy8ckit_062s4.png diff --git a/boards/cypress/cy8ckit_062s4/doc/index.rst b/boards/infineon/cy8ckit_062s4/doc/index.rst similarity index 100% rename from boards/cypress/cy8ckit_062s4/doc/index.rst rename to boards/infineon/cy8ckit_062s4/doc/index.rst From daa92ac0275765e1d56649c153af01a8cb9d541a Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1037/1389] cy8cproto_062_4343w: board: port cy8cproto_062_4343w to HWMv2 Port board cy8cproto_062_4343w to HWMv2 Signed-off-by: Nazar Palamar --- .../cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w | 0 .../cy8cproto_062_4343w/Kconfig.defconfig | 0 .../cy8cproto_062_4343w/board.cmake | 0 .../cy8cproto_062_4343w/board.yml | 2 +- .../cy8cproto_062_4343w-common.dtsi | 0 .../cy8cproto_062_4343w-pinctrl.dtsi | 0 .../cy8cproto_062_4343w/cy8cproto_062_4343w.dts | 4 ++-- .../cy8cproto_062_4343w/cy8cproto_062_4343w.yaml | 5 ++++- .../cy8cproto_062_4343w_defconfig | 0 .../cy8cproto_062_4343w/doc/img/board.jpg | Bin .../cy8cproto_062_4343w/doc/index.rst | 0 .../cy8cproto_062_4343w/support/openocd.cfg | 0 12 files changed, 7 insertions(+), 4 deletions(-) rename boards/{cypress => infineon}/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/Kconfig.defconfig (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/board.cmake (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/board.yml (78%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/cy8cproto_062_4343w.dts (96%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml (87%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/doc/img/board.jpg (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/doc/index.rst (100%) rename boards/{cypress => infineon}/cy8cproto_062_4343w/support/openocd.cfg (100%) diff --git a/boards/cypress/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w b/boards/infineon/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w rename to boards/infineon/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w diff --git a/boards/cypress/cy8cproto_062_4343w/Kconfig.defconfig b/boards/infineon/cy8cproto_062_4343w/Kconfig.defconfig similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/Kconfig.defconfig rename to boards/infineon/cy8cproto_062_4343w/Kconfig.defconfig diff --git a/boards/cypress/cy8cproto_062_4343w/board.cmake b/boards/infineon/cy8cproto_062_4343w/board.cmake similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/board.cmake rename to boards/infineon/cy8cproto_062_4343w/board.cmake diff --git a/boards/cypress/cy8cproto_062_4343w/board.yml b/boards/infineon/cy8cproto_062_4343w/board.yml similarity index 78% rename from boards/cypress/cy8cproto_062_4343w/board.yml rename to boards/infineon/cy8cproto_062_4343w/board.yml index 575dbf83414871..f89df6ee65e023 100644 --- a/boards/cypress/cy8cproto_062_4343w/board.yml +++ b/boards/infineon/cy8cproto_062_4343w/board.yml @@ -1,5 +1,5 @@ board: name: cy8cproto_062_4343w - vendor: cypress + vendor: infineon socs: - name: cy8c624abzi_s2d44 diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.dts b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.dts similarity index 96% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.dts rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.dts index 726b1c9894e9b0..7997344dd540ae 100644 --- a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.dts +++ b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.dts @@ -4,8 +4,8 @@ */ /dts-v1/; -#include -#include +#include +#include #include "cy8cproto_062_4343w-common.dtsi" #include "cy8cproto_062_4343w-pinctrl.dtsi" diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml similarity index 87% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml index 8300a160c5a985..113c686db03716 100644 --- a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml +++ b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml @@ -22,4 +22,7 @@ supported: - gpio - uart - i2c -vendor: cypress + - thermistor + - uart + - timer +vendor: infineon diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig diff --git a/boards/cypress/cy8cproto_062_4343w/doc/img/board.jpg b/boards/infineon/cy8cproto_062_4343w/doc/img/board.jpg similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/doc/img/board.jpg rename to boards/infineon/cy8cproto_062_4343w/doc/img/board.jpg diff --git a/boards/cypress/cy8cproto_062_4343w/doc/index.rst b/boards/infineon/cy8cproto_062_4343w/doc/index.rst similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/doc/index.rst rename to boards/infineon/cy8cproto_062_4343w/doc/index.rst diff --git a/boards/cypress/cy8cproto_062_4343w/support/openocd.cfg b/boards/infineon/cy8cproto_062_4343w/support/openocd.cfg similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/support/openocd.cfg rename to boards/infineon/cy8cproto_062_4343w/support/openocd.cfg From 6fcce3de3e385d9fa7b6198971896f505f7d44b9 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1038/1389] cy8ckit_062_ble: board: port cy8ckit_062_ble to HWMv2 Port board cy8ckit_062_ble to HWMv2 Signed-off-by: Nazar Palamar --- boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts | 2 +- boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts index 8f5176e2623d22..0fae593a8794a0 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include #include "cy8ckit_062_ble_common.dtsi" / { diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts index 82887420422412..e232445e811a64 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include #include "cy8ckit_062_ble_common.dtsi" / { From 2c75ed3b91c17567c0995cd965781cd181d95e52 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1039/1389] cy8ckit_062_wifi_bt : board: port cy8ckit_062_wifi_bt to HWMv2 Port board cy8ckit_062_wifi_bt to HWMv2 Signed-off-by: Nazar Palamar --- .../cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts | 2 +- .../cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts index fff6d89ea5d01c..18fe196201b2f4 100644 --- a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts +++ b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include #include / { diff --git a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts index e192f94580d8e3..7cd87ba86342fa 100644 --- a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts +++ b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include / { model = "cy8ckit_062_wifi_bt_m4 with a Cypress PSoC6 SoC"; From b475643bdacbfeff6332bd62566a2c7addb83359 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:22 +0200 Subject: [PATCH 1040/1389] xmc45_relax_kit: board: port xmc45_relax_kit to HWMv2 Port board xmc45_relax_kit to HWMv2 Signed-off-by: Nazar Palamar --- boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi | 2 +- boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi index 936733ea02a83a..b8bb7b42a8c0cb 100644 --- a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi +++ b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include &uart_tx_p0_1_u1c1 { drive-strength = "strong-soft-edge"; diff --git a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts index 6b1519a455383d..feb0a8e5aba644 100644 --- a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts +++ b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts @@ -8,8 +8,8 @@ /dts-v1/; -#include -#include +#include +#include #include #include "xmc45_relax_kit-pinctrl.dtsi" From 61f66ee634af681116cc9281b6665f9905228478 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1041/1389] xmc47_relax_kit: board: port xmc47_relax_kit to HWMv2 Port board xmc47_relax_kit to HWMv2 Signed-off-by: Nazar Palamar --- boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi | 2 +- boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi index e6688a7ebb2477..75b35c388b77a2 100644 --- a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi +++ b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include &uart_tx_p1_5_u0c0 { drive-strength = "strong-soft-edge"; diff --git a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts index a7b50692c07524..ec8879bcb4008a 100644 --- a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts +++ b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts @@ -7,8 +7,8 @@ /dts-v1/; -#include -#include +#include +#include #include #include "xmc47_relax_kit-pinctrl.dtsi" #include "arduino_r3_connector.dtsi" From a2e4f715300c9ce9c1b030132fcb7a38f064255c Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1042/1389] west: Update Renesas HAL submodule Update Renesas HAL submodule Signed-off-by: Ioannis Damigos --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 11cc8064bb0b74..4c9c58021947f0 100644 --- a/west.yml +++ b/west.yml @@ -210,7 +210,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 8390c9da4d76656934ea135c757ba946bccd736c + revision: b4fe8925d95bddc27e6d1666890f560d30cf9166 groups: - hal - name: hal_rpi_pico From e5f54675f315a15b53c0f997b0c1d9a2a676ba6d Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1043/1389] soc/da1469x: Take PD_SYS control only once during initialization Take PD_SYS control only once during initialization Signed-off-by: Ioannis Damigos --- soc/renesas/smartbond/da1469x/soc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/soc/renesas/smartbond/da1469x/soc.c b/soc/renesas/smartbond/da1469x/soc.c index 28a21d3aa8f3fc..a6626aa9598afc 100644 --- a/soc/renesas/smartbond/da1469x/soc.c +++ b/soc/renesas/smartbond/da1469x/soc.c @@ -146,9 +146,6 @@ static int renesas_da1469x_init(void) CRG_TOP_PMU_CTRL_REG_COM_SLEEP_Msk | CRG_TOP_PMU_CTRL_REG_RADIO_SLEEP_Msk); - /* PDC should take care of PD_SYS */ - CRG_TOP->PMU_CTRL_REG &= ~CRG_TOP_PMU_CTRL_REG_SYS_SLEEP_Msk; - #if defined(CONFIG_PM) /* Enable cache retainability */ CRG_TOP->PMU_CTRL_REG |= CRG_TOP_PMU_CTRL_REG_RETAIN_CACHE_Msk; @@ -167,15 +164,19 @@ static int renesas_da1469x_init(void) CRG_TOP_BOD_CTRL_REG_BOD_V30_EN_Msk | CRG_TOP_BOD_CTRL_REG_BOD_VBAT_EN_Msk); - da1469x_pdc_reset(); - da1469x_otp_init(); da1469x_trimv_init_from_otp(); da1469x_pd_init(); + + /* + * Take PD_SYS control. + */ da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); da1469x_pd_acquire(MCU_PD_DOMAIN_TIM); + da1469x_pdc_reset(); + return 0; } From 715a419837f2cd0d51a75c2c4ee74591e02efd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1044/1389] Bluetooth: Mesh: Shell: Update DFD start bool parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes the parsing of boolean input parameter "PolicyApply" to DFD start command to use shell boolean parse library. Signed-off-by: Anders Storrø --- subsys/bluetooth/mesh/shell/dfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/shell/dfd.c b/subsys/bluetooth/mesh/shell/dfd.c index 4b3d49702822c0..81c9d557c5d236 100644 --- a/subsys/bluetooth/mesh/shell/dfd.c +++ b/subsys/bluetooth/mesh/shell/dfd.c @@ -223,7 +223,7 @@ static int cmd_dfd_start(const struct shell *sh, size_t argc, char *argv[]) } if (argc > 4) { - params.apply = strcmp(argv[4], "true") ? false : true; + params.apply = shell_strtobool(argv[4], 0, &err); } else { params.apply = true; } From 211c1901842a7c83dfe651f8374ac02bd2c51083 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1045/1389] Bluetooth: Host: Forbid holding on to buf given to stack These are safety checks to guard against silent data corruption. The implementation currently does not clobber bufs, but soon it will. The bufs will be zero-copy segmented and fragmented, which involves overwriting already-sent contents with headers for the next fragment. Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/host/conn.c | 10 ++++++++++ subsys/bluetooth/host/l2cap.c | 35 ++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 018329969695cf..244658e6c74f74 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -478,6 +478,16 @@ int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf, LOG_DBG("conn handle %u buf len %u cb %p user_data %p", conn->handle, buf->len, cb, user_data); + if (buf->ref != 1) { + /* The host may alter the buf contents when fragmenting. Higher + * layers cannot expect the buf contents to stay intact. Extra + * refs suggests a silent data corruption would occur if not for + * this error. + */ + LOG_ERR("buf given to conn has other refs"); + return -EINVAL; + } + if (buf->user_data_size < CONFIG_BT_CONN_TX_USER_DATA_SIZE) { LOG_ERR("not enough room in user_data %d < %d pool %u", buf->user_data_size, diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index f0f04ab796fd81..df312f5dd03467 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -1945,7 +1945,8 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, if ((buf->len <= ch->tx.mps) && (net_buf_headroom(buf) >= BT_L2CAP_BUF_SIZE(0))) { LOG_DBG("len <= MPS, not allocating seg for %p", buf); - seg = net_buf_ref(buf); + /* move `buf` to `seg`. `buf` now borrows `seg`. */ + seg = buf; len = seg->len; } else { @@ -2002,14 +2003,21 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, */ LOG_DBG("unref %p (%s)", seg, buf == seg ? "orig" : "seg"); - net_buf_unref(seg); + + if (seg == buf) { + /* move `seg` to `buf` */ + } else { + net_buf_unref(seg); + } if (err == -ENOBUFS) { /* Restore state since segment could not be sent */ net_buf_simple_restore(&buf->b, &state); - return -EAGAIN; + err = -EAGAIN; } + /* move `buf` back to caller */ + return err; } @@ -2026,7 +2034,9 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, return len; } -/* return next netbuf fragment if present, also assign metadata */ +/** + * @param buf [move on success] + */ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch, struct net_buf *buf) { @@ -2048,15 +2058,12 @@ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch, } sent += ret; - - /* If the current buffer has been fully consumed, destroy it */ - if (sent == rem_len) { - net_buf_unref(buf); - } } LOG_DBG("ch %p cid 0x%04x sent %u", ch, ch->tx.cid, sent); + /* `l2cap_chan_le_send` moved `buf` for final seg */ + return sent; } @@ -3065,6 +3072,16 @@ static int bt_l2cap_dyn_chan_send(struct bt_l2cap_le_chan *le_chan, struct net_b return -EMSGSIZE; } + if (buf->ref != 1) { + /* The host may alter the buf contents when segmenting. Higher + * layers cannot expect the buf contents to stay intact. Extra + * refs suggests a silent data corruption would occur if not for + * this error. + */ + LOG_ERR("buf given to l2cap has other refs"); + return -EINVAL; + } + if (net_buf_headroom(buf) < BT_L2CAP_SDU_CHAN_SEND_RESERVE) { /* Call `net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE)` * when allocating buffers intended for bt_l2cap_chan_send(). From b5f963f2d536a9e944cb5f3652642b2b9ba599e9 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1046/1389] samples: net: tftp-client: Configs cleanup As native_posix is no longer supported, due to incompatibility with CONFIG_POSIX_API, remove a dedicated config for it. A config for qemu_cortex_m3 needed to enable RNG, as otherwise it's not available for the platform and gives build error. Finally, enable qemu_cortex_m3 build in the CI. Signed-off-by: Robert Lubos --- samples/net/tftp_client/boards/native_posix.conf | 3 --- samples/net/tftp_client/boards/qemu_cortex_m3.conf | 1 + samples/net/tftp_client/sample.yaml | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 samples/net/tftp_client/boards/native_posix.conf diff --git a/samples/net/tftp_client/boards/native_posix.conf b/samples/net/tftp_client/boards/native_posix.conf deleted file mode 100644 index 1e9e27b074ea10..00000000000000 --- a/samples/net/tftp_client/boards/native_posix.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_DNS_RESOLVER=y -CONFIG_DNS_SERVER_IP_ADDRESSES=y -CONFIG_DNS_SERVER1="192.0.2.2" diff --git a/samples/net/tftp_client/boards/qemu_cortex_m3.conf b/samples/net/tftp_client/boards/qemu_cortex_m3.conf index dc256b47832a2f..944da5cca684cc 100644 --- a/samples/net/tftp_client/boards/qemu_cortex_m3.conf +++ b/samples/net/tftp_client/boards/qemu_cortex_m3.conf @@ -2,3 +2,4 @@ CONFIG_NET_L2_ETHERNET=y CONFIG_ETH_DRIVER=y CONFIG_ETH_STELLARIS=y CONFIG_NET_QEMU_ETHERNET=y +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/samples/net/tftp_client/sample.yaml b/samples/net/tftp_client/sample.yaml index 6e53b0f188172e..fd4b2f2d0c0e96 100644 --- a/samples/net/tftp_client/sample.yaml +++ b/samples/net/tftp_client/sample.yaml @@ -7,6 +7,7 @@ tests: depends_on: netif platform_allow: - native_sim + - qemu_cortex_m3 integration_platforms: - native_sim tags: From 7cffa91c29f2d8385b4f5f32faf45650395cc48d Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1047/1389] tests: net: lib: http_server: Bump min_ram requirements The values set as a min_ram requirement were far from the actual RAM usage reported during build, make them more realistic. Signed-off-by: Robert Lubos --- tests/net/lib/http_server/common/testcase.yaml | 2 +- tests/net/lib/http_server/crime/testcase.yaml | 2 +- tests/net/lib/http_server/prototype/testcase.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/net/lib/http_server/common/testcase.yaml b/tests/net/lib/http_server/common/testcase.yaml index 11d720068cc567..8b89a10da97332 100644 --- a/tests/net/lib/http_server/common/testcase.yaml +++ b/tests/net/lib/http_server/common/testcase.yaml @@ -1,5 +1,5 @@ common: - min_ram: 16 + min_ram: 40 tags: - net - http diff --git a/tests/net/lib/http_server/crime/testcase.yaml b/tests/net/lib/http_server/crime/testcase.yaml index 2c75b4f1ca18b8..615b4264685b2e 100644 --- a/tests/net/lib/http_server/crime/testcase.yaml +++ b/tests/net/lib/http_server/crime/testcase.yaml @@ -1,6 +1,6 @@ common: harness: net - min_ram: 16 + min_ram: 60 tags: - http - net diff --git a/tests/net/lib/http_server/prototype/testcase.yaml b/tests/net/lib/http_server/prototype/testcase.yaml index d5683174bcd046..80d6c7e2651b0c 100644 --- a/tests/net/lib/http_server/prototype/testcase.yaml +++ b/tests/net/lib/http_server/prototype/testcase.yaml @@ -1,6 +1,6 @@ common: harness: net - min_ram: 16 + min_ram: 80 tags: - http - net From f7401dd5dc1c545ec7512e6c9278e4cd65f2fbfb Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1048/1389] tests: Bluetooth: CAP: Add missing CSIP function The bt_csip_set_coordinator_csis_member_by_conn function was seemingly missing, causing the CAP unit tests to not build. Signed-off-by: Emil Gydesen --- tests/bluetooth/audio/cap_commander/uut/csip.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/bluetooth/audio/cap_commander/uut/csip.c b/tests/bluetooth/audio/cap_commander/uut/csip.c index c6e910e8c0bee5..4fcf5b2950456f 100644 --- a/tests/bluetooth/audio/cap_commander/uut/csip.c +++ b/tests/bluetooth/audio/cap_commander/uut/csip.c @@ -52,6 +52,16 @@ int bt_csip_set_coordinator_discover(struct bt_conn *conn) return 0; } +struct bt_csip_set_coordinator_set_member * +bt_csip_set_coordinator_csis_member_by_conn(struct bt_conn *conn) +{ + if (conn == NULL) { + return NULL; + } + + return &member; +} + void mock_bt_csip_init(void) { } From 494758d850b4d988db8f0ad62db6971e605886b7 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1049/1389] dts: nxp_mcxn94x: fix flash write-block-size - Fix mcxn94x flash write-block-size from 16 to 128. - Fix flash_program() return error 0x65, that means "Address or length does not meet the required alignment." - The mcxn94x Flash ROM API flash_program() start address and the length must be 128 bytes-aligned. Signed-off-by: Andrej Butok --- dts/arm/nxp/nxp_mcxn94x_common.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index 31e280e556e4e6..1912d3cc26b643 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -572,7 +572,8 @@ compatible = "soc-nv-flash"; reg = <0 DT_SIZE_M(2)>; erase-block-size = <8192>; - write-block-size = <16>; + /* MCXN94x ROM Flash API supports writing of 128B pages. */ + write-block-size = <128>; }; }; From 32cb2427f861e8e07a7ec061071c4f21072bf241 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1050/1389] doc: mimxrt1160_evk: update doc for linkserver linkserver cmsis-dap fw need updated for this board Signed-off-by: Hake Huang --- boards/nxp/mimxrt1160_evk/doc/index.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boards/nxp/mimxrt1160_evk/doc/index.rst b/boards/nxp/mimxrt1160_evk/doc/index.rst index 44362f44e204b8..deaac1c22ece04 100644 --- a/boards/nxp/mimxrt1160_evk/doc/index.rst +++ b/boards/nxp/mimxrt1160_evk/doc/index.rst @@ -281,8 +281,9 @@ Using LinkServer ---------------- Install the :ref:`linkserver-debug-host-tools` and make sure they are in your -search path. LinkServer works with the default CMSIS-DAP firmware included in -the on-board debugger. +search path. LinkServer works with the CMSIS-DAP firmware include in LinkServer +install. Please follow the ``LPCScrypt\docs\Debug_Probe_Firmware_Programming.pdf`` +for more details. Linkserver is the default runner. You may also se the ``-r linkserver`` option with West to use the LinkServer runner. From d8e704f85ca21efdadaf153f2acf93b5fd17833a Mon Sep 17 00:00:00 2001 From: Charlie Gilliland Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1051/1389] drivers: eth: stm32: fix typo in Kconfig For the choice ETH_STM32_HAL_API_VERSION, both options ETH_STM32_HAL_API_V2 and ETH_STM32_HAL_API_V1 had the same prompt "Use new HAL driver". This commit fixes the prompt for the legacy driver. Signed-off-by: Charlie Gilliland --- drivers/ethernet/Kconfig.stm32_hal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index 4a11796dc88153..6bd0c65f9b91e2 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -30,7 +30,7 @@ config ETH_STM32_HAL_API_V2 Use the new HAL driver instead of the legacy one. config ETH_STM32_HAL_API_V1 - bool "Use new HAL driver" + bool "Use legacy HAL driver" depends on !SOC_SERIES_STM32H5X select DEPRECATED if SOC_SERIES_STM32H7X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X help From b2dcad8cabdc4b9975d7785fde3bcea21afb6304 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1052/1389] soc: intel: adsp: tgl: ace: Set correct virtual memory size Corrected virtual memory size to match the range supported by the Translation Lookup Buffer. The TLB size is 16 MB, however the first 128 KB is dedicated to LPSRAM and bypasses the TLB. This was taken into account in KERNEL_VM_BASE, so KERNEL_VM_SIZE was reduced accordingly. Signed-off-by: Adrian Warecki --- soc/intel/intel_adsp/ace/Kconfig.defconfig.series | 7 +++++++ soc/intel/intel_adsp/cavs/Kconfig.defconfig.cavs_v25 | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/soc/intel/intel_adsp/ace/Kconfig.defconfig.series b/soc/intel/intel_adsp/ace/Kconfig.defconfig.series index b9a548d77c1454..a860d74422693b 100644 --- a/soc/intel/intel_adsp/ace/Kconfig.defconfig.series +++ b/soc/intel/intel_adsp/ace/Kconfig.defconfig.series @@ -74,6 +74,13 @@ config XTENSA_NUM_SPIN_RELAX_NOPS endif # XTENSA_MORE_SPIN_RELAX_NOPS +if KERNEL_VM_SUPPORT + +config KERNEL_VM_SIZE + default 0xfe0000 + +endif + rsource "Kconfig.defconfig.ace*" endif # SOC_SERIES_INTEL_ADSP_ACE diff --git a/soc/intel/intel_adsp/cavs/Kconfig.defconfig.cavs_v25 b/soc/intel/intel_adsp/cavs/Kconfig.defconfig.cavs_v25 index ad6fa8baac6893..d0e7662195e1fa 100644 --- a/soc/intel/intel_adsp/cavs/Kconfig.defconfig.cavs_v25 +++ b/soc/intel/intel_adsp/cavs/Kconfig.defconfig.cavs_v25 @@ -46,7 +46,7 @@ config CAVS_ISR_TBL_OFFSET if KERNEL_VM_SUPPORT config KERNEL_VM_SIZE - default 0x800000 + default 0xfe0000 endif From 3cf8cc29100efdc5f5648b60942eacbb9fbbf15a Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1053/1389] drivers/clock_control/smartbond: Always calibrate RC32K RC32K clocks HW FSM. We should always calibrate it. Signed-off-by: Ioannis Damigos --- drivers/clock_control/clock_control_smartbond.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index 1ba24850f2d982..e00999ec490a0a 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -51,19 +51,18 @@ static void calibration_work_cb(struct k_work *work) da1469x_clock_lp_rcx_calibrate(); lpc_clock_state.rcx_ready = true; lpc_clock_state.rcx_freq = da1469x_clock_lp_rcx_freq_get(); - k_work_schedule(&calibration_work, - K_MSEC(1000 * CALIBRATION_INTERVAL)); LOG_DBG("RCX calibration done, RCX freq: %d", (int)lpc_clock_state.rcx_freq); - } else if (lpc_clock_state.rc32k_started) { + } + if (lpc_clock_state.rc32k_started) { da1469x_clock_lp_rc32k_calibrate(); lpc_clock_state.rc32k_ready = true; lpc_clock_state.rc32k_freq = da1469x_clock_lp_rc32k_freq_get(); - k_work_schedule(&calibration_work, - K_MSEC(1000 * CALIBRATION_INTERVAL)); LOG_DBG("RC32K calibration done, RC32K freq: %d", (int)lpc_clock_state.rc32k_freq); } + k_work_schedule(&calibration_work, + K_MSEC(1000 * CALIBRATION_INTERVAL)); #ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME switch (smartbond_source_clock(SMARTBOND_CLK_LP_CLK)) { case SMARTBOND_CLK_RCX: From 3be52c29b1cfd93589d0e7ce08518f2dacd52b13 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1054/1389] dts/bindings/renesas,smartbond-lp-osc: Substitute calibration-interval Substitute calibration-interval property with kconfig option SMARTBOND_LP_OSC_CALIBRATION_INTERVAL Signed-off-by: Ioannis Damigos --- drivers/clock_control/Kconfig.smartbond | 11 +++++++++++ drivers/clock_control/clock_control_smartbond.c | 8 +++----- dts/arm/renesas/smartbond/da1469x.dtsi | 2 -- dts/bindings/clock/renesas,smartbond-lp-osc.yaml | 10 ---------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/clock_control/Kconfig.smartbond b/drivers/clock_control/Kconfig.smartbond index d20907c60018cf..49ac7c7c660fa0 100644 --- a/drivers/clock_control/Kconfig.smartbond +++ b/drivers/clock_control/Kconfig.smartbond @@ -8,3 +8,14 @@ config CLOCK_CONTROL_SMARTBOND depends on SOC_FAMILY_RENESAS_SMARTBOND help Enable driver for Clock Control subsystem found in SmartBond + +if CLOCK_CONTROL_SMARTBOND + +config SMARTBOND_LP_OSC_CALIBRATION_INTERVAL + int "Low-power oscillators calibration interval" + default 1 + range 1 10 + help + Time in seconds between calibration of low power clock RC32K and RCX. + +endif # CLOCK_CONTROL_SMARTBOND diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index e00999ec490a0a..39ab44f7d0cd2e 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -30,9 +30,7 @@ struct lpc_clock_state { .rc32k_freq = DT_PROP(DT_NODELABEL(rc32k), clock_frequency), }; -#define CALIBRATION_INTERVAL (DT_NODE_HAS_STATUS(DT_NODELABEL(rcx), okay) ? \ - DT_PROP(DT_NODELABEL(rcx), calibration_interval) : \ - DT_PROP(DT_NODELABEL(rc32k), calibration_interval)) +#define CALIBRATION_INTERVAL CONFIG_SMARTBOND_LP_OSC_CALIBRATION_INTERVAL #ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME extern int z_clock_hw_cycles_per_sec; @@ -91,7 +89,7 @@ static void smartbond_start_rc32k(void) CRG_TOP->CLK_RC32K_REG |= CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk; } lpc_clock_state.rc32k_started = true; - if (!lpc_clock_state.rc32k_ready && (CALIBRATION_INTERVAL > 0)) { + if (!lpc_clock_state.rc32k_ready) { if (!k_work_is_pending(&calibration_work.work)) { k_work_schedule(&calibration_work, K_MSEC(1000 * CALIBRATION_INTERVAL)); @@ -106,7 +104,7 @@ static void smartbond_start_rcx(void) da1469x_clock_lp_rcx_enable(); lpc_clock_state.rcx_started = true; } - if (!lpc_clock_state.rcx_ready && (CALIBRATION_INTERVAL > 0)) { + if (!lpc_clock_state.rcx_ready) { if (!k_work_is_pending(&calibration_work.work)) { k_work_schedule(&calibration_work, K_MSEC(1000 * CALIBRATION_INTERVAL)); diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index c78e8bb414bf04..a1539c7887e998 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -46,7 +46,6 @@ rc32k: rc32k { compatible = "renesas,smartbond-lp-osc"; clock-frequency = ; - calibration-interval = <1>; #clock-cells = <0>; status = "okay"; }; @@ -60,7 +59,6 @@ rcx: rcx { compatible = "renesas,smartbond-lp-osc"; clock-frequency = ; - calibration-interval = <1>; #clock-cells = <0>; status = "disabled"; }; diff --git a/dts/bindings/clock/renesas,smartbond-lp-osc.yaml b/dts/bindings/clock/renesas,smartbond-lp-osc.yaml index 0aa82f773e5f28..45c3c56e47277d 100644 --- a/dts/bindings/clock/renesas,smartbond-lp-osc.yaml +++ b/dts/bindings/clock/renesas,smartbond-lp-osc.yaml @@ -13,16 +13,6 @@ include: - clock-frequency properties: - calibration-interval: - type: int - default: 1 - description: | - Time in seconds between calibration of low power clock RCX or RC32K. - For XTAL32K this value is not used. - If set to 0 calibration will not be performed. This can be applied - when XTAL32K is enabled for low power clock and RCX or RC32K is used - for watchdog and strict timing is not required. - settle-time: type: int default: 8000 From 7d6b1fd9b4e8803bf38fa6202ce458464acde042 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1055/1389] drivers/clock_control: Add build assertion for RC32K Add build assertion for RC32K to prevent user from disabling RC32K in DT Signed-off-by: Ioannis Damigos --- drivers/clock_control/clock_control_smartbond.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index 39ab44f7d0cd2e..27290f62c53bfe 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -175,6 +175,8 @@ static inline int smartbond_clock_control_off(const struct device *dev, switch (clk) { case SMARTBOND_CLK_RC32K: + BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(rc32k), okay), + "RC32K is not allowed to be turned off"); if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >> CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) != 0) { CRG_TOP->CLK_RC32K_REG &= ~CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk; From b50b0ab3df0e206fe0b78380e0efdd73f1ebae54 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1056/1389] drivers: sensors: nxp: kinetis: temp: select CONFIG_ADC The NXP Kinetis temperature sensor depends on CONFIG_ADC. Make the driver Kconfig select CONFIG_ADC to get better CI coverage (enabling the driver when CONFIG_SENSOR is enabled without depending on CONFIG_ADC=y). Signed-off-by: Henrik Brix Andersen --- drivers/sensor/nxp/nxp_kinetis_temp/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig b/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig index 63c91cde176c8b..10436fda53a3d3 100644 --- a/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig +++ b/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig @@ -7,7 +7,8 @@ config TEMP_KINETIS bool "NXP Kinetis Temperature Sensor" default y depends on DT_HAS_NXP_KINETIS_TEMPERATURE_ENABLED - depends on (ADC && SOC_FAMILY_KINETIS) + depends on SOC_FAMILY_KINETIS + select ADC help Enable driver for NXP Kinetis temperature sensor. From 1f3a98283c46d02dfb5c7ff02885f1a03ddb496c Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:23 +0200 Subject: [PATCH 1057/1389] drivers: sensor: nxp: kinetis: temp: fix memset() length Use the correct buffer size when calling memset(). Fixes: #73093 Signed-off-by: Henrik Brix Andersen --- drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c b/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c index b72b5eece6ca4c..7f5beda55ebad0 100644 --- a/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c +++ b/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c @@ -159,7 +159,7 @@ static int temp_kinetis_init(const struct device *dev) }, }; - memset(&data->buffer, 0, ARRAY_SIZE(data->buffer)); + memset(&data->buffer, 0, sizeof(data->buffer)); if (!device_is_ready(config->adc)) { LOG_ERR("ADC device is not ready"); From be95bd7bda9d9f09379c545966e9d1f87c6d5a5b Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1058/1389] MAINTAINERS: add butok as "NXP Platforms (MCU)" collaborator Add myself as "NXP Platforms (MCU)" collaborator. Signed-off-by: Andrej Butok --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index e905666fb69330..8134b0da73953e 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3349,6 +3349,7 @@ NXP Platforms (MCU): - yvanderv - EmilioCBen - decsny + - butok files: - boards/nxp/mimxrt*/ - boards/nxp/frdm*/ From 4e9dfbeb9326d4a3cb20f1114804436ff587c7b8 Mon Sep 17 00:00:00 2001 From: Benjamin Lindqvist Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1059/1389] net: lib: coap_client: observe-related fixes An earlier pull request implementing observe support was merged too hastily. It had a few issues: 1. The predicate for whether a request should be marked not ongoing was wrong (it checked ret != 0 instead of ret < 0) 2. Without observes in mind, MID-based deduplication is not a required feature. Deduplication was handled implicitly - the exchange would get dropped after the first response anyway, so duplicate responses would not get matched to anything. But with observes, there are several responses in an exchange. This commit adds this. 3. Using coap_request_is_observe(&internal_req->request) in the response handler requires the whole request to stay in scope for the lifetime of the observation, which I observed was not always the case. Adding an is_observe bool to the internal struct improved stability significantly. With these fixes, GETs with observe option works very well. Signed-off-by: Benjamin Lindqvist --- include/zephyr/net/coap_client.h | 9 ++++++--- subsys/net/lib/coap/coap_client.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index 3997a394f5809a..7779b22fca9607 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -91,6 +91,10 @@ struct coap_client_internal_request { struct coap_client_request coap_request; struct coap_packet request; uint8_t request_tag[COAP_TOKEN_MAX_LEN]; + + /* For GETs with observe option set */ + bool is_observe; + int last_response_id; }; struct coap_client { @@ -141,9 +145,8 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr /** * @brief Cancel all current requests. * - * This is intended for canceling long-running requests (e.g. GETs with the OBSERVE option set, - * or a block transfer) which have gone stale for some reason. It is also intended for responding - * to network connectivity issues. + * This is intended for canceling long-running requests (e.g. GETs with the OBSERVE option set) + * which has gone stale for some reason. * * @param client Client instance. */ diff --git a/subsys/net/lib/coap/coap_client.c b/subsys/net/lib/coap/coap_client.c index f80c440a839ffd..96d1584ccb0315 100644 --- a/subsys/net/lib/coap/coap_client.c +++ b/subsys/net/lib/coap/coap_client.c @@ -66,6 +66,7 @@ static void reset_internal_request(struct coap_client_internal_request *request) { request->offset = 0; request->last_id = 0; + request->last_response_id = -1; reset_block_contexts(request); } @@ -369,6 +370,7 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr } coap_pending_cycle(&internal_req->pending); + internal_req->is_observe = coap_request_is_observe(&internal_req->request); } ret = send_request(sock, internal_req->request.data, internal_req->request.offset, 0, @@ -659,6 +661,7 @@ static int handle_response(struct coap_client *client, const struct coap_packet /* CON, NON_CON and piggybacked ACK need to match the token with original request */ uint16_t payload_len; uint8_t response_code = coap_header_get_code(response); + uint16_t response_id = coap_header_get_id(response); const uint8_t *payload = coap_packet_get_payload(response, &payload_len); /* Separate response coming */ @@ -675,6 +678,14 @@ static int handle_response(struct coap_client *client, const struct coap_packet return 1; } + /* MID-based deduplication */ + if (response_id == internal_req->last_response_id) { + LOG_WRN("Duplicate MID, dropping"); + goto fail; + } + + internal_req->last_response_id = response_id; + /* Received echo option */ if (find_echo_option(response, &client->echo_option)) { /* Resend request with echo option */ @@ -833,7 +844,7 @@ static int handle_response(struct coap_client *client, const struct coap_packet } fail: client->response_ready = false; - if (ret != 0 || !coap_request_is_observe(&internal_req->request)) { + if (ret < 0 || !internal_req->is_observe) { internal_req->request_ongoing = false; } return ret; @@ -851,6 +862,7 @@ void coap_client_cancel_requests(struct coap_client *client) */ report_callback_error(&client->requests[i], -ECANCELED); client->requests[i].request_ongoing = false; + client->requests[i].is_observe = false; } } atomic_clear(&coap_client_recv_active); From 0cc1656e93330d95ba633d52bec4ad6bc742e9bc Mon Sep 17 00:00:00 2001 From: Bartosz Sokolski Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1060/1389] boards: nrf54l15pdk: set default pdk to 0.3.0 Replace default pdk board from 0.2.1 to 0.3.0 Signed-off-by: Bartosz Sokolski --- boards/nordic/nrf54l15pdk/board.yml | 2 +- .../nrf54l15pdk_nrf54l15-common.dtsi | 14 ++++++------- ...=> nrf54l15pdk_nrf54l15_common_0_2_1.dtsi} | 14 ++++++------- ...nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay} | 2 +- .../nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml | 20 ------------------- ...rf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay} | 2 +- ...4l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay | 7 +++++++ 7 files changed, 24 insertions(+), 37 deletions(-) rename boards/nordic/nrf54l15pdk/{nrf54l15pdk_nrf54l15_common_0_3_0.dtsi => nrf54l15pdk_nrf54l15_common_0_2_1.dtsi} (51%) rename boards/nordic/nrf54l15pdk/{nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay => nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay} (65%) delete mode 100644 boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml rename boards/nordic/nrf54l15pdk/{nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay => nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay} (65%) create mode 100644 boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay diff --git a/boards/nordic/nrf54l15pdk/board.yml b/boards/nordic/nrf54l15pdk/board.yml index 6f1cfb22893326..e692040f7bd725 100644 --- a/boards/nordic/nrf54l15pdk/board.yml +++ b/boards/nordic/nrf54l15pdk/board.yml @@ -8,7 +8,7 @@ board: cpucluster: cpuflpr revision: format: major.minor.patch - default: "0.2.1" + default: "0.3.0" revisions: - name: "0.2.1" - name: "0.3.0" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi index e1931726e7162b..028bcfccd54b14 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi @@ -10,15 +10,15 @@ leds { compatible = "gpio-leds"; led0: led_0 { - gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; label = "Green LED 0"; }; led1: led_1 { - gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; label = "Green LED 1"; }; led2: led_2 { - gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>; label = "Green LED 2"; }; led3: led_3 { @@ -30,22 +30,22 @@ buttons { compatible = "gpio-keys"; button0: button_0 { - gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 0"; zephyr,code = ; }; button1: button_1 { - gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 1"; zephyr,code = ; }; button2: button_2 { - gpios = <&gpio2 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 2"; zephyr,code = ; }; button3: button_3 { - gpios = <&gpio2 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 3"; zephyr,code = ; }; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_3_0.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi similarity index 51% rename from boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_3_0.dtsi rename to boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi index 282adfd6b1d69d..bfe673ec966e52 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_3_0.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi @@ -5,15 +5,15 @@ */ &led0 { - gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; }; &led1 { - gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; }; &led2 { - gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; }; &led3 { @@ -21,17 +21,17 @@ }; &button0 { - gpios = <&gpio1 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; }; &button1 { - gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; }; &button2 { - gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio2 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; }; &button3 { - gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio2 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; }; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay similarity index 65% rename from boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay rename to boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay index a37482f7d16422..1ca5cadaff9992 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay @@ -4,4 +4,4 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nrf54l15pdk_nrf54l15_common_0_3_0.dtsi" +#include "nrf54l15pdk_nrf54l15_common_0_2_1.dtsi" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml deleted file mode 100644 index a19bc8fdc8b2bf..00000000000000 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -identifier: nrf54l15pdk@0.3.0/nrf54l15/cpuapp -name: nRF54l15-PDK-nRF54l15-Application -type: mcu -arch: arm -toolchain: - - gnuarmemb - - xtools - - zephyr -ram: 256 -flash: 1536 -supported: - - counter - - gpio - - i2c - - spi - - watchdog - - i2s diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay similarity index 65% rename from boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay rename to boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay index a37482f7d16422..1ca5cadaff9992 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay @@ -4,4 +4,4 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nrf54l15pdk_nrf54l15_common_0_3_0.dtsi" +#include "nrf54l15pdk_nrf54l15_common_0_2_1.dtsi" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay new file mode 100644 index 00000000000000..1ca5cadaff9992 --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15pdk_nrf54l15_common_0_2_1.dtsi" From e2ddd796c262c158b2cdfaff45fba4304f5bf0ae Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1061/1389] scripts: ci: test_plan: fix usage with files When modified files list is used instead of commit range, repo object was incorrect. Signed-off-by: Piotr Kosycarz --- scripts/ci/test_plan.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 26787496a7cccc..3483aab58aecf7 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -24,7 +24,7 @@ # however, pylint complains that it doesn't recognized them when used (used-before-assignment). zephyr_base = Path(os.environ['ZEPHYR_BASE']) repository_path = zephyr_base -repo_to_scan = zephyr_base +repo_to_scan = Repo(zephyr_base) args = None @@ -424,8 +424,8 @@ def parse_args(): errors = 0 if args.repo_to_scan: repository_path = Path(args.repo_to_scan) - if args.commits: repo_to_scan = Repo(repository_path) + if args.commits: commit = repo_to_scan.git.diff("--name-only", args.commits) files = commit.split("\n") elif args.modified_files: From fa71d6ac12eded54c61082437253eda823afe29f Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1062/1389] scripts: ci: test_plan: add parameter for no of testcase roots Allow to provide from CLI, threshold value for number of test case roots selected for execution base on changed files. When such threshold will be exceeded, full scope will be executed. Signed-off-by: Piotr Kosycarz --- scripts/ci/test_plan.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 3483aab58aecf7..1bbfd331debd0c 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -95,7 +95,7 @@ def __repr__(self): class Filters: def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, - pull_request=False, platforms=[], detailed_test_id=True): + pull_request=False, platforms=[], detailed_test_id=True, tc_roots_th=20): self.modified_files = modified_files self.testsuite_root = testsuite_root self.resolved_files = [] @@ -108,6 +108,7 @@ def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, self.detailed_test_id = detailed_test_id self.ignore_path = ignore_path self.tag_cfg_file = alt_tags + self.tc_roots_th = tc_roots_th def process(self): self.find_modules() @@ -288,7 +289,7 @@ def find_tests(self): for t in tests: _options.extend(["-T", t ]) - if len(tests) > 20: + if len(tests) > self.tc_roots_th: logging.warning(f"{len(tests)} tests changed, this looks like a global change, skipping test handling, revert to default") self.full_twister = True return @@ -392,6 +393,9 @@ def parse_args(): help="Number of tests per builder") parser.add_argument('-n', '--default-matrix', default=10, type=int, help="Number of tests per builder") + parser.add_argument('--testcase-roots-threshold', default=20, type=int, + help="Threshold value for number of modified testcase roots, up to which an optimized scope is still applied." + "When exceeded, full scope will be triggered") parser.add_argument('--detailed-test-id', action='store_true', help="Include paths to tests' locations in tests' names.") parser.add_argument("--no-detailed-test-id", dest='detailed_test_id', action="store_false", @@ -438,7 +442,8 @@ def parse_args(): print("=========") f = Filters(files, args.ignore_path, args.alt_tags, args.testsuite_root, - args.pull_request, args.platform, args.detailed_test_id) + args.pull_request, args.platform, args.detailed_test_id, + args.testcase_roots_threshold) f.process() # remove dupes and filtered cases From 5889e533d356ec53ce2777bac1984a030102d8e6 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1063/1389] dts: arm: nuvoton: add pwm node of numaker m2l31x Update m2l31x.dtsi, to add pwm nodes for pwm driver support. Signed-off-by: cyliang tw --- dts/arm/nuvoton/m2l31x.dtsi | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dts/arm/nuvoton/m2l31x.dtsi b/dts/arm/nuvoton/m2l31x.dtsi index 5a755676e8cc12..3485ea22b95918 100644 --- a/dts/arm/nuvoton/m2l31x.dtsi +++ b/dts/arm/nuvoton/m2l31x.dtsi @@ -334,6 +334,30 @@ clocks = <&pcc NUMAKER_RTC_MODULE 0 0>; alarms-count = <1>; }; + + epwm0: epwm@40058000 { + compatible = "nuvoton,numaker-pwm"; + reg = <0x40058000 0x37c>; + interrupts = <25 0>, <26 0>, <27 0>; + interrupt-names = "pair0", "pair1", "pair2"; + resets = <&rst NUMAKER_EPWM0_RST>; + prescaler = <19>; + clocks = <&pcc NUMAKER_EPWM0_MODULE NUMAKER_CLK_CLKSEL2_EPWM0SEL_PCLK0 0>; + #pwm-cells = <3>; + status = "disabled"; + }; + + epwm1: epwm@40059000 { + compatible = "nuvoton,numaker-pwm"; + reg = <0x40059000 0x37c>; + interrupts = <29 0>, <30 0>, <31 0>; + interrupt-names = "pair0", "pair1", "pair2"; + resets = <&rst NUMAKER_EPWM1_RST>; + prescaler = <19>; + clocks = <&pcc NUMAKER_EPWM1_MODULE NUMAKER_CLK_CLKSEL2_EPWM1SEL_PCLK1 0>; + #pwm-cells = <3>; + status = "disabled"; + }; }; }; From dcf60ca4e73804050119ecd7aa20d90a44a8cb29 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1064/1389] tests: drivers: pwm: pwm_loopback: support numaker_m2l31ki Add support for Nuvoton numaker board numaker_m2l31ki. m2l31x has 4 MPU regions and can't afford one more region for TEST_USERSPACE, so set CONFIG_TEST_USERSPACE=n. Signed-off-by: cyliang tw --- .../pwm_loopback/boards/numaker_m2l31ki.conf | 1 + .../boards/numaker_m2l31ki.overlay | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.conf create mode 100644 tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.overlay diff --git a/tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.conf b/tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.conf new file mode 100644 index 00000000000000..9fb2581d7f4a24 --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.conf @@ -0,0 +1 @@ +CONFIG_TEST_USERSPACE=n diff --git a/tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.overlay b/tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.overlay new file mode 100644 index 00000000000000..8d4f3c66d4351e --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/numaker_m2l31ki.overlay @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +&pinctrl { + epwm1_default: epwm1_default { + group0 { + /* EVB's D2, D5 --> PC4, PA6 */ + pinmux = , + ; + }; + }; +}; + +/ { + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + pwms = <&epwm1 1 0 PWM_POLARITY_NORMAL>, + <&epwm1 5 0 PWM_POLARITY_NORMAL>; + }; +}; + +&epwm1 { + status = "okay"; + prescaler = <19>; + pinctrl-0 = <&epwm1_default>; + pinctrl-names = "default"; +}; From 5773353d7ff7dd2a4318f4c4569743de9ca80917 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1065/1389] tests: drivers: pwm: pwm_loopback: correct numaker_pfm_m467 pinmux Fix pinmux of numaker_pfm_m467.overlay to meet pinmux format. Signed-off-by: cyliang tw --- .../drivers/pwm/pwm_loopback/boards/numaker_pfm_m467.overlay | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/drivers/pwm/pwm_loopback/boards/numaker_pfm_m467.overlay b/tests/drivers/pwm/pwm_loopback/boards/numaker_pfm_m467.overlay index 2803a4289a2915..3f28f49a4a2516 100644 --- a/tests/drivers/pwm/pwm_loopback/boards/numaker_pfm_m467.overlay +++ b/tests/drivers/pwm/pwm_loopback/boards/numaker_pfm_m467.overlay @@ -6,8 +6,8 @@ epwm1_default: epwm1_default { group0 { /* EVB's D5, D3 --> PC12, PC10 */ - pinmux = , - ; + pinmux = , + ; }; }; }; From 05d931f0b8089a69457b104017e42bff0e2f2b76 Mon Sep 17 00:00:00 2001 From: Ben Lauret Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1066/1389] MAINTAINERS: updated hal_renesas maintainers list Added ioannis-karachalios as maintainer in the hal_renesas Moved andrzej-kaczmarek to collaborators and added blauret as collaborator too. Signed-off-by: Ben Lauret --- MAINTAINERS.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 8134b0da73953e..fabae903e97eb1 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -4352,6 +4352,9 @@ West: status: maintained maintainers: - KhiemNguyenT + - ioannis-karachalios + collaborators: + - blauret - andrzej-kaczmarek files: [] labels: From ce278dc4b406ca9554f8ff82fd01818e0080617e Mon Sep 17 00:00:00 2001 From: Arkadiusz Cholewinski Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1067/1389] CI: Reschedule codecov workflow Reschedule from '6:25 and 18:25, Monday-Friday' to 'everyday at the same time'. Signed-off-by: Arkadiusz Cholewinski --- .github/workflows/codecov.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 0e16d6b6ab82fb..19c50aba9b4b9d 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -2,7 +2,7 @@ name: Code Coverage with codecov on: schedule: - - cron: '25 06,18 * * 1-5' + - cron: '25 06,18 * * *' concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} From 72661c5bd4a925ae2c9c7462344dc46c5339122e Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1068/1389] lib: bitarray: add method to count bits set in region This is part one of several changes to add more methods to the bitarray api so that it can be used for broader usecases, specifically LoRaWAN forward error correction. Signed-off-by: Lucas Romero --- include/zephyr/sys/bitarray.h | 17 ++++++ lib/utils/bitarray.c | 49 +++++++++++++++ tests/kernel/common/src/bitarray.c | 98 ++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) diff --git a/include/zephyr/sys/bitarray.h b/include/zephyr/sys/bitarray.h index 90d1f59345bb56..6ca166f6b21ccb 100644 --- a/include/zephyr/sys/bitarray.h +++ b/include/zephyr/sys/bitarray.h @@ -168,6 +168,23 @@ int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *p int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, size_t *offset); +/** + * Count bits set in a bit array region + * + * This counts the number of bits set (@p count) in a + * region (@p offset, @p num_bits). + * + * @param[in] bitarray Bitarray struct + * @param[in] num_bits Number of bits to check, must be larger than 0 + * @param[in] offset Starting bit position + * @param[out] count Number of bits set in the region if successful + * + * @retval 0 Operation successful + * @retval -EINVAL Invalid argument (e.g. out-of-bounds access, trying to count 0 bits, etc.) + */ +int sys_bitarray_popcount_region(sys_bitarray_t *bitarray, size_t num_bits, size_t offset, + size_t *count); + /** * Free bits in a bit array * diff --git a/lib/utils/bitarray.c b/lib/utils/bitarray.c index 7213ae201f54ea..6e8c92f118bdcc 100644 --- a/lib/utils/bitarray.c +++ b/lib/utils/bitarray.c @@ -210,6 +210,55 @@ static void set_region(sys_bitarray_t *bitarray, size_t offset, } } +int sys_bitarray_popcount_region(sys_bitarray_t *bitarray, size_t num_bits, size_t offset, + size_t *count) +{ + k_spinlock_key_t key; + size_t idx; + struct bundle_data bd; + int ret; + + key = k_spin_lock(&bitarray->lock); + + __ASSERT_NO_MSG(bitarray != NULL); + __ASSERT_NO_MSG(bitarray->num_bits > 0); + + if (num_bits == 0 || offset + num_bits > bitarray->num_bits) { + ret = -EINVAL; + goto out; + } + + CHECKIF(count == NULL) { + ret = -EINVAL; + goto out; + } + + setup_bundle_data(bitarray, &bd, offset, num_bits); + + if (bd.sidx == bd.eidx) { + /* Start/end at same bundle */ + *count = POPCOUNT(bitarray->bundles[bd.sidx] & bd.smask); + } else { + /* Start/end at different bundle. + * So count the bits in start and end bundles + * separately with correct mask applied. For in-between bundles, + * count all bits. + */ + *count = 0; + *count += POPCOUNT(bitarray->bundles[bd.sidx] & bd.smask); + *count += POPCOUNT(bitarray->bundles[bd.eidx] & bd.emask); + for (idx = bd.sidx + 1; idx < bd.eidx; idx++) { + *count += POPCOUNT(bitarray->bundles[idx]); + } + } + + ret = 0; + +out: + k_spin_unlock(&bitarray->lock, key); + return ret; +} + int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit) { k_spinlock_key_t key; diff --git a/tests/kernel/common/src/bitarray.c b/tests/kernel/common/src/bitarray.c index 05dd12c5343906..dbd43ed201f0f2 100644 --- a/tests/kernel/common/src/bitarray.c +++ b/tests/kernel/common/src/bitarray.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include @@ -519,6 +520,103 @@ ZTEST(bitarray, test_bitarray_alloc_free) alloc_and_free_interval(); } +ZTEST(bitarray, test_bitarray_popcount_region) +{ + int ret; + size_t count; + + /* Bitarrays have embedded spinlocks and can't on the stack. */ + if (IS_ENABLED(CONFIG_KERNEL_COHERENCE)) { + ztest_test_skip(); + } + + SYS_BITARRAY_DEFINE(ba, 128); + + printk("Testing bit array region popcount spanning single bundle\n"); + + /* Pre-populate the bits */ + ba.bundles[0] = 0x00000005; + ba.bundles[1] = 0x00000000; + ba.bundles[2] = 0x00000000; + ba.bundles[3] = 0x00000000; + + ret = sys_bitarray_popcount_region(&ba, 1, 0, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 1, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 1, 1, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 0, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 2, 0, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 1, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 3, 0, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 2, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 3, 1, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 1, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + printk("Testing bit array region popcount spanning multiple bundles\n"); + + /* Pre-populate the bits. + * First and last bit of bitarray are set + */ + ba.bundles[0] = 0x00000001; + ba.bundles[1] = 0x00000000; + ba.bundles[2] = 0x00000000; + ba.bundles[3] = 0x80000000; + + ret = sys_bitarray_popcount_region(&ba, 126, 1, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 0, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 126, 0, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 1, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 127, 1, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 1, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + ret = sys_bitarray_popcount_region(&ba, 1, 127, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 1, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + ret = sys_bitarray_popcount_region(&ba, 128, 0, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + zassert_equal(count, 2, "sys_bitarray_popcount_region() returned unexpected count: %d", + count); + + printk("Testing edge/error cases\n"); + ret = sys_bitarray_popcount_region(&ba, 0, 0, &count); + zassert_equal(ret, -EINVAL, "sys_bitarray_popcount_region() returned unexpected value: %d", + ret); + ret = sys_bitarray_popcount_region(&ba, 0, 128, &count); + zassert_equal(ret, -EINVAL, "sys_bitarray_popcount_region() returned unexpected value: %d", + ret); + ret = sys_bitarray_popcount_region(&ba, 128, 0, &count); + zassert_equal(ret, 0, "sys_bitarray_popcount_region() returned unexpected value: %d", ret); + + ret = sys_bitarray_popcount_region(&ba, 128, 1, &count); + zassert_equal(ret, -EINVAL, "sys_bitarray_popcount_region() returned unexpected value: %d", + ret); + ret = sys_bitarray_popcount_region(&ba, 129, 0, &count); + zassert_equal(ret, -EINVAL, "sys_bitarray_popcount_region() returned unexpected value: %d", + ret); +} + ZTEST(bitarray, test_bitarray_region_set_clear) { int ret; From a35547755f44547e26f110761150327c0e22c878 Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1069/1389] lib: bitarray: add method to xor two bitarrays This is part one of several changes to add more methods to the bitarray api so that it can be used for broader usecases, specifically LoRaWAN forward error correction. Signed-off-by: Lucas Romero --- include/zephyr/sys/bitarray.h | 16 ++++ lib/utils/bitarray.c | 57 ++++++++++++ tests/kernel/common/src/bitarray.c | 143 +++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) diff --git a/include/zephyr/sys/bitarray.h b/include/zephyr/sys/bitarray.h index 6ca166f6b21ccb..edf67d980fac77 100644 --- a/include/zephyr/sys/bitarray.h +++ b/include/zephyr/sys/bitarray.h @@ -168,6 +168,22 @@ int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *p int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, size_t *offset); +/* + * Calculates the bit-wise XOR of two bitarrays in a region. + * The result is stored in the first bitarray passed in (@p dst). + * Both bitarrays must be of the same size. + * + * @param dst Bitarray struct + * @param other Bitarray struct + * @param num_bits Number of bits in the region, must be larger than 0 + * @param offset Starting bit location + * + * @retval 0 Operation successful + * @retval -EINVAL Invalid argument (e.g. out-of-bounds access, mismatching bitarrays, trying to xor + * 0 bits, etc.) + */ +int sys_bitarray_xor(sys_bitarray_t *dst, sys_bitarray_t *other, size_t num_bits, size_t offset); + /** * Count bits set in a bit array region * diff --git a/lib/utils/bitarray.c b/lib/utils/bitarray.c index 6e8c92f118bdcc..2642d45e385c78 100644 --- a/lib/utils/bitarray.c +++ b/lib/utils/bitarray.c @@ -259,6 +259,63 @@ int sys_bitarray_popcount_region(sys_bitarray_t *bitarray, size_t num_bits, size return ret; } +int sys_bitarray_xor(sys_bitarray_t *dst, sys_bitarray_t *other, size_t num_bits, size_t offset) +{ + k_spinlock_key_t key_dst, key_other; + int ret; + size_t idx; + struct bundle_data bd; + + key_dst = k_spin_lock(&dst->lock); + key_other = k_spin_lock(&other->lock); + + __ASSERT_NO_MSG(dst != NULL); + __ASSERT_NO_MSG(dst->num_bits > 0); + __ASSERT_NO_MSG(other != NULL); + __ASSERT_NO_MSG(other->num_bits > 0); + + if (dst->num_bits != other->num_bits) { + ret = -EINVAL; + goto out; + } + + if (num_bits == 0 || offset + num_bits > dst->num_bits) { + ret = -EINVAL; + goto out; + } + + setup_bundle_data(other, &bd, offset, num_bits); + + if (bd.sidx == bd.eidx) { + /* Start/end at same bundle */ + dst->bundles[bd.sidx] = + ((other->bundles[bd.sidx] ^ dst->bundles[bd.sidx]) & bd.smask) | + (dst->bundles[bd.sidx] & ~bd.smask); + } else { + /* Start/end at different bundle. + * So xor the bits in start and end bundles according to their bitmasks + * separately. For in-between bundles, + * xor all bits. + */ + dst->bundles[bd.sidx] = + ((other->bundles[bd.sidx] ^ dst->bundles[bd.sidx]) & bd.smask) | + (dst->bundles[bd.sidx] & ~bd.smask); + dst->bundles[bd.eidx] = + ((other->bundles[bd.eidx] ^ dst->bundles[bd.eidx]) & bd.emask) | + (dst->bundles[bd.eidx] & ~bd.emask); + for (idx = bd.sidx + 1; idx < bd.eidx; idx++) { + dst->bundles[idx] ^= other->bundles[idx]; + } + } + + ret = 0; + +out: + k_spin_unlock(&other->lock, key_other); + k_spin_unlock(&dst->lock, key_dst); + return ret; +} + int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit) { k_spinlock_key_t key; diff --git a/tests/kernel/common/src/bitarray.c b/tests/kernel/common/src/bitarray.c index dbd43ed201f0f2..9381bbe299b9f5 100644 --- a/tests/kernel/common/src/bitarray.c +++ b/tests/kernel/common/src/bitarray.c @@ -617,6 +617,149 @@ ZTEST(bitarray, test_bitarray_popcount_region) ret); } +ZTEST(bitarray, test_bitarray_xor) +{ + int ret; + + /* Bitarrays have embedded spinlocks and can't on the stack. */ + if (IS_ENABLED(CONFIG_KERNEL_COHERENCE)) { + ztest_test_skip(); + } + + SYS_BITARRAY_DEFINE(ba, 128); + SYS_BITARRAY_DEFINE(bb, 128); + SYS_BITARRAY_DEFINE(bc, 129); + + printk("Testing bit array region xor spanning single bundle\n"); + + /* Pre-populate the bits */ + ba.bundles[0] = 0x80001001; + ba.bundles[1] = 0x10000008; + ba.bundles[2] = 0xFFFFFFFF; + ba.bundles[3] = 0x00000000; + + bb.bundles[0] = 0x80010001; + bb.bundles[1] = 0x10000008; + bb.bundles[2] = 0xFFFFFFFF; + bb.bundles[3] = 0x00000000; + + ret = sys_bitarray_xor(&ba, &bb, 32, 0); + zassert_equal(ret, 0, "sys_bitarray_xor() returned unexpected value: %d", ret); + zassert_equal(ba.bundles[0], 0x00011000, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[0]); + zassert_equal(bb.bundles[0], 0x80010001, "sys_bitarray_xor() result unexpected: %x", + bb.bundles[0]); + + zassert_equal(ba.bundles[1], 0x10000008, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[1]); + zassert_equal(bb.bundles[1], 0x10000008, "sys_bitarray_xor() result unexpected: %x", + bb.bundles[1]); + + zassert_equal(ba.bundles[2], 0xFFFFFFFF, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[2]); + zassert_equal(bb.bundles[2], 0xFFFFFFFF, "sys_bitarray_xor() result unexpected: %x", + bb.bundles[2]); + + zassert_equal(ba.bundles[3], 0x00000000, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[3]); + zassert_equal(bb.bundles[3], 0x00000000, "sys_bitarray_xor() result unexpected: %x", + bb.bundles[3]); + + /* Pre-populate the bits */ + ba.bundles[0] = 0x80001001; + ba.bundles[1] = 0x10000008; + ba.bundles[2] = 0xFFFFFFFF; + ba.bundles[3] = 0x00000000; + + bb.bundles[0] = 0x80010001; + bb.bundles[1] = 0x10000008; + bb.bundles[2] = 0xFFFFFFFF; + bb.bundles[3] = 0x00000000; + + ret = sys_bitarray_xor(&ba, &bb, 16, 0); + zassert_equal(ret, 0, "sys_bitarray_xor() returned unexpected value: %d", ret); + zassert_equal(ba.bundles[0], 0x80001000, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[0]); + zassert_equal(bb.bundles[0], 0x80010001, "sys_bitarray_xor() result unexpected: %x", + bb.bundles[0]); + + /* Pre-populate the bits */ + ba.bundles[0] = 0x80001001; + ba.bundles[1] = 0x10000008; + ba.bundles[2] = 0xFFFFFFFF; + ba.bundles[3] = 0x00000000; + + bb.bundles[0] = 0x80010001; + bb.bundles[1] = 0x10000008; + bb.bundles[2] = 0xFFFFFFFF; + bb.bundles[3] = 0x00000000; + + ret = sys_bitarray_xor(&ba, &bb, 16, 16); + zassert_equal(ret, 0, "sys_bitarray_xor() returned unexpected value: %d", ret); + zassert_equal(ba.bundles[0], 0x00011001, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[0]); + zassert_equal(bb.bundles[0], 0x80010001, "sys_bitarray_xor() result unexpected: %x", + bb.bundles[0]); + + printk("Testing bit array region xor spanning multiple bundles\n"); + + /* Pre-populate the bits */ + ba.bundles[0] = 0x00000000; + ba.bundles[1] = 0xFFFFFFFF; + ba.bundles[2] = 0xFFFFFFFF; + ba.bundles[3] = 0xFFFFFFFF; + + bb.bundles[0] = 0x00000000; + bb.bundles[1] = 0xFFFFFFFF; + bb.bundles[2] = 0xFFFFFFFF; + bb.bundles[3] = 0xFFFFFFFF; + + ret = sys_bitarray_xor(&ba, &bb, 32*3 - 2, 32 + 1); + zassert_equal(ret, 0, "sys_bitarray_xor() returned unexpected value: %d", ret); + zassert_equal(ba.bundles[0], 0x00000000, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[0]); + zassert_equal(ba.bundles[1], 0x00000001, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[1]); + zassert_equal(ba.bundles[2], 0x00000000, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[2]); + zassert_equal(ba.bundles[3], 0x80000000, "sys_bitarray_xor() result unexpected: %x", + ba.bundles[3]); + + printk("Testing error cases\n"); + /* Pre-populate the bits */ + ba.bundles[0] = 0x00000000; + ba.bundles[1] = 0x00000000; + ba.bundles[2] = 0x00000000; + ba.bundles[3] = 0x00000000; + + bb.bundles[0] = 0x00000000; + bb.bundles[1] = 0x00000000; + bb.bundles[2] = 0x00000000; + bb.bundles[3] = 0x00000000; + + bc.bundles[0] = 0x00000000; + bc.bundles[1] = 0x00000000; + bc.bundles[2] = 0x00000000; + bc.bundles[3] = 0x00000000; + bc.bundles[4] = 0x00000000; + + ret = sys_bitarray_xor(&ba, &bb, 32, 0); + zassert_equal(ret, 0, "sys_bitarray_xor() returned unexpected value: %d", ret); + ret = sys_bitarray_xor(&ba, &bc, 32, 0); + zassert_equal(ret, -EINVAL, "sys_bitarray_xor() returned unexpected value: %d", ret); + ret = sys_bitarray_xor(&bc, &ba, 32, 0); + zassert_equal(ret, -EINVAL, "sys_bitarray_xor() returned unexpected value: %d", ret); + + ret = sys_bitarray_xor(&ba, &bb, 128, 0); + zassert_equal(ret, 0, "sys_bitarray_xor() returned unexpected value: %d", ret); + ret = sys_bitarray_xor(&ba, &bb, 128, 1); + zassert_equal(ret, -EINVAL, "sys_bitarray_xor() returned unexpected value: %d", ret); + ret = sys_bitarray_xor(&ba, &bb, 129, 0); + zassert_equal(ret, -EINVAL, "sys_bitarray_xor() returned unexpected value: %d", ret); + ret = sys_bitarray_xor(&ba, &bb, 0, 0); + zassert_equal(ret, -EINVAL, "sys_bitarray_xor() returned unexpected value: %d", ret); +} + ZTEST(bitarray, test_bitarray_region_set_clear) { int ret; From 8d306fb1569200f37e60138a8cf7089f2e7ffb50 Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1070/1389] lib: bitarray: add method to find nth bit set in region This is part one of several changes to add more methods to the bitarray api so that it can be used for broader usecases, specifically LoRaWAN forward error correction. Signed-off-by: Lucas Romero --- include/zephyr/sys/bitarray.h | 22 ++++++ lib/utils/bitarray.c | 75 ++++++++++++++++++++ tests/kernel/common/src/bitarray.c | 107 +++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+) diff --git a/include/zephyr/sys/bitarray.h b/include/zephyr/sys/bitarray.h index edf67d980fac77..ebd18081cc53ca 100644 --- a/include/zephyr/sys/bitarray.h +++ b/include/zephyr/sys/bitarray.h @@ -184,6 +184,28 @@ int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, */ int sys_bitarray_xor(sys_bitarray_t *dst, sys_bitarray_t *other, size_t num_bits, size_t offset); +/** + * Find nth bit set in region + * + * This counts the number of bits set (@p count) in a + * region (@p offset, @p num_bits) and returns the index (@p found_at) + * of the nth set bit, if it exists, as long with a zero return value. + * + * If it does not exist, @p found_at is not updated and the method returns + * + * @param[in] bitarray Bitarray struct + * @param[in] n Nth bit set to look for + * @param[in] num_bits Number of bits to check, must be larger than 0 + * @param[in] offset Starting bit position + * @param[out] found_at Index of the nth bit set, if found + * + * @retval 0 Operation successful + * @retval 1 Nth bit set was not found in region + * @retval -EINVAL Invalid argument (e.g. out-of-bounds access, trying to count 0 bits, etc.) + */ +int sys_bitarray_find_nth_set(sys_bitarray_t *bitarray, size_t n, size_t num_bits, size_t offset, + size_t *found_at); + /** * Count bits set in a bit array region * diff --git a/lib/utils/bitarray.c b/lib/utils/bitarray.c index 2642d45e385c78..509fa5f199f6d0 100644 --- a/lib/utils/bitarray.c +++ b/lib/utils/bitarray.c @@ -559,6 +559,81 @@ int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, return ret; } +int sys_bitarray_find_nth_set(sys_bitarray_t *bitarray, size_t n, size_t num_bits, size_t offset, + size_t *found_at) +{ + k_spinlock_key_t key; + size_t count, idx; + uint32_t mask; + struct bundle_data bd; + int ret; + + __ASSERT_NO_MSG(bitarray != NULL); + __ASSERT_NO_MSG(bitarray->num_bits > 0); + + key = k_spin_lock(&bitarray->lock); + + if (n == 0 || num_bits == 0 || offset + num_bits > bitarray->num_bits) { + ret = -EINVAL; + goto out; + } + + ret = 1; + mask = 0; + setup_bundle_data(bitarray, &bd, offset, num_bits); + + count = POPCOUNT(bitarray->bundles[bd.sidx] & bd.smask); + /* If we already found more bits set than n, we found the target bundle */ + if (count >= n) { + idx = bd.sidx; + mask = bd.smask; + goto found; + } + /* Keep looking if there are more bundles */ + if (bd.sidx != bd.eidx) { + /* We are now only looking for the remaining bits */ + n -= count; + /* First bundle was already checked, keep looking in middle (complete) + * bundles. + */ + for (idx = bd.sidx + 1; idx < bd.eidx; idx++) { + count = POPCOUNT(bitarray->bundles[idx]); + if (count >= n) { + mask = ~(mask & 0); + goto found; + } + n -= count; + } + /* Continue searching in last bundle */ + count = POPCOUNT(bitarray->bundles[bd.eidx] & bd.emask); + if (count >= n) { + idx = bd.eidx; + mask = bd.emask; + goto found; + } + } + + goto out; + +found: + /* The bit we are looking for must be in the current bundle idx. + * Find out the exact index of the bit. + */ + for (int j = 0; j <= bundle_bitness(bitarray) - 1; j++) { + if (bitarray->bundles[idx] & mask & BIT(j)) { + if (--n <= 0) { + *found_at = idx * bundle_bitness(bitarray) + j; + ret = 0; + break; + } + } + } + +out: + k_spin_unlock(&bitarray->lock, key); + return ret; +} + int sys_bitarray_free(sys_bitarray_t *bitarray, size_t num_bits, size_t offset) { diff --git a/tests/kernel/common/src/bitarray.c b/tests/kernel/common/src/bitarray.c index 9381bbe299b9f5..a7a7be02a017f9 100644 --- a/tests/kernel/common/src/bitarray.c +++ b/tests/kernel/common/src/bitarray.c @@ -760,6 +760,113 @@ ZTEST(bitarray, test_bitarray_xor) zassert_equal(ret, -EINVAL, "sys_bitarray_xor() returned unexpected value: %d", ret); } +ZTEST(bitarray, test_bitarray_find_nth_set) +{ + int ret; + size_t found_at; + + /* Bitarrays have embedded spinlocks and can't on the stack. */ + if (IS_ENABLED(CONFIG_KERNEL_COHERENCE)) { + ztest_test_skip(); + } + + SYS_BITARRAY_DEFINE(ba, 128); + + printk("Testing bit array nth bit set finding spanning single bundle\n"); + + /* Pre-populate the bits */ + ba.bundles[0] = 0x80000001; + ba.bundles[1] = 0x80000001; + ba.bundles[2] = 0x80000001; + ba.bundles[3] = 0x80000001; + + ret = sys_bitarray_find_nth_set(&ba, 1, 1, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 0, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 1, 32, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 0, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 2, 32, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 31, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 1, 31, 1, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 31, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 2, 31, 1, &found_at); + zassert_equal(ret, 1, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + + printk("Testing bit array nth bit set finding spanning multiple bundles\n"); + + ret = sys_bitarray_find_nth_set(&ba, 1, 128, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 0, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 8, 128, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 127, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 8, 128, 1, &found_at); + zassert_equal(ret, -EINVAL, "sys_bitarray_find_nth_set() returned unexpected value: %d", + ret); + + ret = sys_bitarray_find_nth_set(&ba, 7, 127, 1, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 127, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 7, 127, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 96, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 6, 127, 1, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 96, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 6, 127, 1, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 96, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 1, 32, 48, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 63, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + ret = sys_bitarray_find_nth_set(&ba, 2, 32, 48, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + zassert_equal(found_at, 64, "sys_bitarray_find_nth_set() returned unexpected found_at: %d", + found_at); + + printk("Testing error cases\n"); + + ret = sys_bitarray_find_nth_set(&ba, 1, 128, 0, &found_at); + zassert_equal(ret, 0, "sys_bitarray_find_nth_set() returned unexpected value: %d", ret); + + ret = sys_bitarray_find_nth_set(&ba, 1, 128, 1, &found_at); + zassert_equal(ret, -EINVAL, "sys_bitarray_find_nth_set() returned unexpected value: %d", + ret); + + ret = sys_bitarray_find_nth_set(&ba, 1, 129, 0, &found_at); + zassert_equal(ret, -EINVAL, "sys_bitarray_find_nth_set() returned unexpected value: %d", + ret); + + ret = sys_bitarray_find_nth_set(&ba, 0, 128, 0, &found_at); + zassert_equal(ret, -EINVAL, "sys_bitarray_find_nth_set() returned unexpected value: %d", + ret); +} + ZTEST(bitarray, test_bitarray_region_set_clear) { int ret; From 5f7c375e03a777c0975dc1eda7274be148426cdd Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1071/1389] boards: nxp: rd_rw612_bga: add support for goworld 16880 display module Add support for the goworld 16880 display module. As this display module only features an FFC cable, it is added as a board overlay for the RW612 BGA. This module uses an ST7796S display controller as well as an FT7401 touch controller (which is managed by the FT5336 input driver) Signed-off-by: Daniel DeGrasse --- boards/nxp/rd_rw612_bga/Kconfig.defconfig | 4 + .../dts/goworld_16880_lcm.overlay | 91 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay diff --git a/boards/nxp/rd_rw612_bga/Kconfig.defconfig b/boards/nxp/rd_rw612_bga/Kconfig.defconfig index 713d8594e886af..376f96da2b3328 100644 --- a/boards/nxp/rd_rw612_bga/Kconfig.defconfig +++ b/boards/nxp/rd_rw612_bga/Kconfig.defconfig @@ -30,4 +30,8 @@ config LV_Z_FLUSH_THREAD endif # LVGL +# Enable interrupt support when using FT5336 driver +config INPUT_FT5336_INTERRUPT + default y if INPUT + endif # BOARD_RD_RW612_BGA diff --git a/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay b/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay new file mode 100644 index 00000000000000..8b9dbe924911f5 --- /dev/null +++ b/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay @@ -0,0 +1,91 @@ +#include + +/ { + chosen { + zephyr,display = &st7796s_lcdic; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&ft7401>; + swap-xy; + invert-y; + }; +}; + +&lcdic { + status = "okay"; + nxp,swap-bytes; + /* + * Settings to connect this display: + * Populate the following resistors: + * - R125, R123, R12, R124, R15, R243, R239, R236, R233, R286, R246 + * Remove the following resistors: + * - R9, R11, R20, R19, R242, R241, R237, R235, R245 + * Remove JP30 to disconnect Flexcomm SPI CS + * Display can be connected to Arduino header (J5/J6) + * Pin # | Signal | Header + * ------------------------------- + * 1 | VDD | J5.8 (+3.3V) + * 2 | RST | J6.8 (LCD_SPI_RESETN) + * 3 | SDO | J5.5 (SPI_MISO) + * 4 | CS | J5.3 (LCD_SPI_SS) + * 5 | SCLK | J5.6 (LCD_SPI_SCK) + * 6 | GND | J5.7 (GND) + * 7 | MOSI | J5.4 (LCD_SPI_SDIO) + * 8 | CD | J5.1 (LCD_SPI_DC) + * 9 | TE | J5.2 (LCD_SPI_TE, not enabled) + * + * Pins 10 and 11 correspond to the backlight anode and cathode, + * and must be driven by an external circuit + */ + st7796s_lcdic: st7796s@0 { + compatible = "sitronix,st7796s"; + status = "okay"; + reg = <0>; + mipi-max-frequency = <23000000>; + duplex = ; + height = <320>; + width = <480>; + invert-mode = "1-dot"; + frmctl1 = [80 10]; + bpc = [1F 50 00 20]; + dfc = [8A 07 3B]; + pwr1 = [80 64]; + pwr2 = <0x13>; + pwr3 = <0xA7>; + vcmpctl = <0x09>; + doca = [40 8A 00 00 29 19 A5 38]; + pgc = [F0 06 0B 07 06 05 2E 33 47 3A 17 16 2E 31]; + ngc = [F0 09 0D 09 08 23 2E 33 46 38 13 13 2C 32]; + madctl = <0x28>; + }; +}; + +&flexcomm2 { + status = "okay"; + ft7401: ft7401@38 { + /* + * Settings to connect this touch controller: + * Populate JP3 and JP50 to connect I2C + * Controller can be connected to Arduino Header (J8/J5) + * Pin #1 | Signal | Header + * ------------------------------- + * 1 | VDD | J8.2 (+3.3V) + * 2 | IOVDD | J8.4 (+3.3V) + * 3 | SCL | J5.10 (SCL) + * 4 | SDA | J5.9 (SDA) + * 5 | INT | J6.3 (D2) + * 6 | RST | J6.4 (D3) + * 7 | GND | J8.6 (GND) + * 8 | GND | J8.7 (GND) + * + * Note- the actual controller present on this IC is a FT7401, + * but the FT5336 driver in Zephyr supports this IC. + */ + compatible = "focaltech,ft5336"; + reg = <0x38>; + reset-gpios = <&hsgpio0 15 GPIO_ACTIVE_LOW>; + int-gpios = <&hsgpio0 11 GPIO_ACTIVE_HIGH>; + }; +}; From 4de1008ac6fd149c1cd56f57d1268ea342e7a744 Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1072/1389] soc: microchip: mec: Add new HAL based MEC5 family chips Add new Microchip MEC chips using the new MEC5 HAL and add a HAL version of a legacy chip named MECH172x. Signed-off-by: Scott Worley --- modules/Kconfig.microchip | 3 ++ soc/microchip/mec/Kconfig | 49 +++++++++++++++++++ soc/microchip/mec/common/CMakeLists.txt | 3 ++ soc/microchip/mec/common/soc_cmn_init.c | 41 ++++++++++++++++ soc/microchip/mec/common/soc_cmn_init.h | 16 ++++++ soc/microchip/mec/mec174x/CMakeLists.txt | 11 +++++ soc/microchip/mec/mec174x/Kconfig | 21 ++++++++ .../mec/mec174x/Kconfig.defconfig.mec1743qlj | 16 ++++++ .../mec/mec174x/Kconfig.defconfig.mec1743qsz | 16 ++++++ .../mec/mec174x/Kconfig.defconfig.series | 19 +++++++ soc/microchip/mec/mec174x/Kconfig.soc | 25 ++++++++++ soc/microchip/mec/mec174x/soc.c | 24 +++++++++ soc/microchip/mec/mec174x/soc.h | 25 ++++++++++ soc/microchip/mec/mec175x/CMakeLists.txt | 11 +++++ soc/microchip/mec/mec175x/Kconfig | 21 ++++++++ .../mec/mec175x/Kconfig.defconfig.mec1753qlj | 16 ++++++ .../mec/mec175x/Kconfig.defconfig.mec1753qsz | 16 ++++++ .../mec/mec175x/Kconfig.defconfig.series | 19 +++++++ soc/microchip/mec/mec175x/Kconfig.soc | 25 ++++++++++ soc/microchip/mec/mec175x/soc.c | 24 +++++++++ soc/microchip/mec/mec175x/soc.h | 25 ++++++++++ soc/microchip/mec/mech172x/CMakeLists.txt | 11 +++++ soc/microchip/mec/mech172x/Kconfig | 21 ++++++++ .../mech172x/Kconfig.defconfig.mech1723nlj | 16 ++++++ .../mech172x/Kconfig.defconfig.mech1723nsz | 16 ++++++ .../mec/mech172x/Kconfig.defconfig.series | 19 +++++++ soc/microchip/mec/mech172x/Kconfig.soc | 25 ++++++++++ soc/microchip/mec/mech172x/soc.c | 24 +++++++++ soc/microchip/mec/mech172x/soc.h | 25 ++++++++++ soc/microchip/mec/soc.yml | 12 +++++ 30 files changed, 595 insertions(+) create mode 100644 soc/microchip/mec/common/soc_cmn_init.c create mode 100644 soc/microchip/mec/common/soc_cmn_init.h create mode 100644 soc/microchip/mec/mec174x/CMakeLists.txt create mode 100644 soc/microchip/mec/mec174x/Kconfig create mode 100644 soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qlj create mode 100644 soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qsz create mode 100644 soc/microchip/mec/mec174x/Kconfig.defconfig.series create mode 100644 soc/microchip/mec/mec174x/Kconfig.soc create mode 100644 soc/microchip/mec/mec174x/soc.c create mode 100644 soc/microchip/mec/mec174x/soc.h create mode 100644 soc/microchip/mec/mec175x/CMakeLists.txt create mode 100644 soc/microchip/mec/mec175x/Kconfig create mode 100644 soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qlj create mode 100644 soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qsz create mode 100644 soc/microchip/mec/mec175x/Kconfig.defconfig.series create mode 100644 soc/microchip/mec/mec175x/Kconfig.soc create mode 100644 soc/microchip/mec/mec175x/soc.c create mode 100644 soc/microchip/mec/mec175x/soc.h create mode 100644 soc/microchip/mec/mech172x/CMakeLists.txt create mode 100644 soc/microchip/mec/mech172x/Kconfig create mode 100644 soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nlj create mode 100644 soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nsz create mode 100644 soc/microchip/mec/mech172x/Kconfig.defconfig.series create mode 100644 soc/microchip/mec/mech172x/Kconfig.soc create mode 100644 soc/microchip/mec/mech172x/soc.c create mode 100644 soc/microchip/mec/mech172x/soc.h diff --git a/modules/Kconfig.microchip b/modules/Kconfig.microchip index 8c30ae6087d42e..7497d99ead0a59 100644 --- a/modules/Kconfig.microchip +++ b/modules/Kconfig.microchip @@ -7,3 +7,6 @@ config HAS_MEC_HAL config HAS_MPFS_HAL bool "Microchip MPFS HAL drivers support" + +config HAS_MEC5_HAL + bool "Microchip MEC5 HAL drivers support" diff --git a/soc/microchip/mec/Kconfig b/soc/microchip/mec/Kconfig index 1b5ccda45e05c2..8f0b84b4b4abfa 100644 --- a/soc/microchip/mec/Kconfig +++ b/soc/microchip/mec/Kconfig @@ -8,6 +8,7 @@ if SOC_FAMILY_MICROCHIP_MEC menuconfig MCHP_MEC_UNSIGNED_HEADER bool "Create an unsigned output binary with MCHP MEC binary header" + depends on SOC_SERIES_MEC172X help On Microchip MEC series chip, the ROM code loads firmware image from flash to RAM using a TAG to locate a Header which specifies the location and @@ -210,6 +211,54 @@ config MCHP_HEADER_VERBOSE_OUTPUT endif # MCHP_MEC_UNSIGNED_HEADER +# Common debug configuration +choice + prompt "MEC debug interface general configuration" + default SOC_MEC_DEBUG_AND_TRACING + depends on SOC_SERIES_MEC174X || SOC_SERIES_MEC175X || SOC_SERIES_MECH172X + help + Select Debug SoC interface support for MEC SoC family + + config SOC_MEC_DEBUG_DISABLED + bool "Disable debug support" + help + Debug port is disabled, JTAG/SWD cannot be enabled. JTAG_RST# + pin is ignored. All other JTAG pins can be used as GPIOs + or other non-JTAG alternate functions. + + config SOC_MEC_DEBUG_WITHOUT_TRACING + bool "Debug support via Serial wire debug" + help + JTAG port in SWD mode. + + config SOC_MEC_DEBUG_AND_TRACING + bool "Debug support via Serial wire debug with tracing enabled" + help + JTAG port is enabled in SWD mode. +endchoice + +choice + prompt "MEC debug interface trace configuration" + default SOC_MEC_DEBUG_AND_SWV_TRACING + depends on SOC_MEC_DEBUG_AND_TRACING + help + Select tracing mode for debug interface + + config SOC_MEC_DEBUG_AND_ETM_TRACING + bool "Debug support via Serial wire debug" + help + JTAG port in SWD mode and ETM as tracing method. + ETM re-assigns 5 pins for clock and 4-bit data bus. + Check data sheet for functions shared with ETM. + + config SOC_MEC_DEBUG_AND_SWV_TRACING + bool "debug support via Serial Wire Debug and Viewer" + help + JTAG port in SWD mode and SWV as tracing method. + Check data sheet for functions shared with SWD and SWV pins. +endchoice + +# common processor clock divider configuration config SOC_MEC_PROC_CLK_DIV int "PROC_CLK_DIV" default 1 diff --git a/soc/microchip/mec/common/CMakeLists.txt b/soc/microchip/mec/common/CMakeLists.txt index 0fe0c9f3d8ba5b..0669a09cbe295c 100644 --- a/soc/microchip/mec/common/CMakeLists.txt +++ b/soc/microchip/mec/common/CMakeLists.txt @@ -4,6 +4,9 @@ zephyr_include_directories(.) zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_MEC172X soc_i2c.c ) +zephyr_library_sources_ifdef(CONFIG_HAS_MEC5_HAL + soc_cmn_init.c +) if (DEFINED CONFIG_MCHP_HEADER_VERBOSE_OUTPUT) set(MCHP_HEADER_VERBOSE_OPTION "-v") diff --git a/soc/microchip/mec/common/soc_cmn_init.c b/soc/microchip/mec/common/soc_cmn_init.c new file mode 100644 index 00000000000000..62cd150861f1d7 --- /dev/null +++ b/soc/microchip/mec/common/soc_cmn_init.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +static void mec5_soc_init_debug_interface(void) +{ +#if defined(CONFIG_SOC_MEC_DEBUG_DISABLED) + mec_ecs_etm_pins(ECS_ETM_PINS_DISABLE); + mec_ecs_debug_port(MEC_DEBUG_MODE_DISABLE); +#else +#if defined(SOC_MEC_DEBUG_WITHOUT_TRACING) + mec_ecs_etm_pins(ECS_ETM_PINS_DISABLE); + mec_ecs_debug_port(MEC_DEBUG_MODE_SWD); +#elif defined(SOC_MEC_DEBUG_AND_TRACING) +#if defined(SOC_MEC_DEBUG_AND_ETM_TRACING) + mec_ecs_etm_pins(ECS_ETM_PINS_DISABLE); + mec_ecs_debug_port(MEC_DEBUG_MODE_SWD_SWV); +#elif defined(CONFIG_SOC_MEC_DEBUG_AND_ETM_TRACING) + mec_ecs_debug_port(MEC_DEBUG_MODE_SWD); + mec_ecs_etm_pins(ECS_ETM_PINS_ENABLE); +#endif +#endif +#endif +} + +int mec5_soc_common_init(void) +{ + mec5_soc_init_debug_interface(); + mec_ecia_init(MEC5_ECIA_DIRECT_BITMAP, 1, 0); + + return 0; +} diff --git a/soc/microchip/mec/common/soc_cmn_init.h b/soc/microchip/mec/common/soc_cmn_init.h new file mode 100644 index 00000000000000..807d8f67b0936c --- /dev/null +++ b/soc/microchip/mec/common/soc_cmn_init.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MEC5_SOC_CMN_INIT_H +#define __MEC5_SOC_CMN_INIT_H + +#ifndef _ASMLANGUAGE + +int mec5_soc_common_init(void); + +#endif + +#endif diff --git a/soc/microchip/mec/mec174x/CMakeLists.txt b/soc/microchip/mec/mec174x/CMakeLists.txt new file mode 100644 index 00000000000000..6d2a447f7293fb --- /dev/null +++ b/soc/microchip/mec/mec174x/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2024, Microchip Technology Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_sources(soc.c) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/microchip/mec/mec174x/Kconfig b/soc/microchip/mec/mec174x/Kconfig new file mode 100644 index 00000000000000..52eb412941a897 --- /dev/null +++ b/soc/microchip/mec/mec174x/Kconfig @@ -0,0 +1,21 @@ +# Microchip MEC174X MCU core series + +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_MEC174X + select ARM + select CPU_CORTEX_M4 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_FPU + select CPU_HAS_ARM_MPU + select HAS_SWO + select HAS_MEC5_HAL + select HAS_PM + +if SOC_SERIES_MEC174X + +config RTOS_TIMER + bool "MEC174x RTOS Timer(32KHz) as kernel timer" + +endif # SOC_SERIES_MEC174X diff --git a/soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qlj b/soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qlj new file mode 100644 index 00000000000000..9f52e8bad9a7a5 --- /dev/null +++ b/soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qlj @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC1743QLJ MCU using MEC5 HAL +# Q = 480KB total SRAM +# LJ = 176 pin package + +if SOC_MEC1743_QLJ + +config GPIO + default y + +config PINCTRL + default y + +endif # SOC_MEC1743_QLJ diff --git a/soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qsz b/soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qsz new file mode 100644 index 00000000000000..b75177ea75700a --- /dev/null +++ b/soc/microchip/mec/mec174x/Kconfig.defconfig.mec1743qsz @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC1743QSZ MCU using MEC5 HAL +# Q = 480KB total SRAM +# SZ = 144 pin package + +if SOC_MEC1743_QSZ + +config GPIO + default y + +config PINCTRL + default y + +endif # SOC_MEC1743_QSZ diff --git a/soc/microchip/mec/mec174x/Kconfig.defconfig.series b/soc/microchip/mec/mec174x/Kconfig.defconfig.series new file mode 100644 index 00000000000000..75a55c393566bc --- /dev/null +++ b/soc/microchip/mec/mec174x/Kconfig.defconfig.series @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC174x MCU series configuration options + +if SOC_SERIES_MEC174X + +config NUM_IRQS + # must be >= the highest interrupt number used + # - include the UART interrupts + # All NVIC external sources. + default 194 + +rsource "Kconfig.defconfig.mec174*" + +config CORTEX_M_SYSTICK + depends on !RTOS_TIMER + +endif # SOC_SERIES_MEC174X diff --git a/soc/microchip/mec/mec174x/Kconfig.soc b/soc/microchip/mec/mec174x/Kconfig.soc new file mode 100644 index 00000000000000..e815797d8f4321 --- /dev/null +++ b/soc/microchip/mec/mec174x/Kconfig.soc @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC174x MCU core series + +config SOC_SERIES_MEC174X + bool + select SOC_FAMILY_MICROCHIP_MEC + help + Enable support for Microchip MEC Cortex-M4F MCU series + +config SOC_SERIES + default "mec174x" if SOC_SERIES_MEC174X + +config SOC_MEC1743_QLJ + bool + select SOC_SERIES_MEC174X + +config SOC_MEC1743_QSZ + bool + select SOC_SERIES_MEC174X + +config SOC + default "mec1743_qlj" if SOC_MEC1743_QLJ + default "mec1743_qsz" if SOC_MEC1743_QSZ diff --git a/soc/microchip/mec/mec174x/soc.c b/soc/microchip/mec/mec174x/soc.c new file mode 100644 index 00000000000000..6d7a502b082418 --- /dev/null +++ b/soc/microchip/mec/mec174x/soc.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static int soc_init(void) +{ + mec5_soc_common_init(); + return 0; +} + +/* Enabling HW debug and initializing the MEC interrupt aggregator should be done + * before driver are loaded to not overwrite driver interrupt configuration. + * Use early initialization category called soon after Zephyr z_cstart and before + * Zephyr starts making driver initialization calls. + */ +SYS_INIT(soc_init, EARLY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/microchip/mec/mec174x/soc.h b/soc/microchip/mec/mec174x/soc.h new file mode 100644 index 00000000000000..b0a2a46eef83a7 --- /dev/null +++ b/soc/microchip/mec/mec174x/soc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MEC5_SOC_H +#define __MEC5_SOC_H + +#define SYSCLK_DEFAULT_IOSC_HZ MHZ(96) + +#ifndef _ASMLANGUAGE + +#include "device_mec5.h" + +/* common SoC API */ +#include "soc_dt.h" +#include "soc_espi_channels.h" +#include "soc_gpio.h" +#include "soc_pcr.h" +#include "soc_pins.h" + +#endif + +#endif diff --git a/soc/microchip/mec/mec175x/CMakeLists.txt b/soc/microchip/mec/mec175x/CMakeLists.txt new file mode 100644 index 00000000000000..6d2a447f7293fb --- /dev/null +++ b/soc/microchip/mec/mec175x/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2024, Microchip Technology Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_sources(soc.c) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/microchip/mec/mec175x/Kconfig b/soc/microchip/mec/mec175x/Kconfig new file mode 100644 index 00000000000000..1cce7ce0e2b6a1 --- /dev/null +++ b/soc/microchip/mec/mec175x/Kconfig @@ -0,0 +1,21 @@ +# Microchip MEC175X MCU core series + +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_MEC175X + select ARM + select CPU_CORTEX_M4 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_FPU + select CPU_HAS_ARM_MPU + select HAS_SWO + select HAS_MEC5_HAL + select HAS_PM + +if SOC_SERIES_MEC175X + +config RTOS_TIMER + bool "MEC175x RTOS Timer(32KHz) as kernel timer" + +endif # SOC_SERIES_MEC175X diff --git a/soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qlj b/soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qlj new file mode 100644 index 00000000000000..268b482b3c043a --- /dev/null +++ b/soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qlj @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC1753QLJ MCU using MEC5 HAL +# Q = 480KB total SRAM +# LJ = 176 pin package + +if SOC_MEC1753_QLJ + +config GPIO + default y + +config PINCTRL + default y + +endif # SOC_MEC1753_QLJ diff --git a/soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qsz b/soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qsz new file mode 100644 index 00000000000000..b75177ea75700a --- /dev/null +++ b/soc/microchip/mec/mec175x/Kconfig.defconfig.mec1753qsz @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC1743QSZ MCU using MEC5 HAL +# Q = 480KB total SRAM +# SZ = 144 pin package + +if SOC_MEC1743_QSZ + +config GPIO + default y + +config PINCTRL + default y + +endif # SOC_MEC1743_QSZ diff --git a/soc/microchip/mec/mec175x/Kconfig.defconfig.series b/soc/microchip/mec/mec175x/Kconfig.defconfig.series new file mode 100644 index 00000000000000..9d8cdf99040a69 --- /dev/null +++ b/soc/microchip/mec/mec175x/Kconfig.defconfig.series @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC175x MCU series configuration options + +if SOC_SERIES_MEC175X + +config NUM_IRQS + # must be >= the highest interrupt number used + # - include the UART interrupts + # All NVIC external sources. + default 198 + +rsource "Kconfig.defconfig.mec175*" + +config CORTEX_M_SYSTICK + depends on !RTOS_TIMER + +endif # SOC_SERIES_MEC175X diff --git a/soc/microchip/mec/mec175x/Kconfig.soc b/soc/microchip/mec/mec175x/Kconfig.soc new file mode 100644 index 00000000000000..39fe541636f85f --- /dev/null +++ b/soc/microchip/mec/mec175x/Kconfig.soc @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MEC175x MCU core series + +config SOC_SERIES_MEC175X + bool + select SOC_FAMILY_MICROCHIP_MEC + help + Enable support for Microchip MEC Cortex-M4F MCU series + +config SOC_SERIES + default "mec175x" if SOC_SERIES_MEC175X + +config SOC_MEC1753_QLJ + bool + select SOC_SERIES_MEC175X + +config SOC_MEC1753_QSZ + bool + select SOC_SERIES_MEC175X + +config SOC + default "mec1753_qlj" if SOC_MEC1753_QLJ + default "mec1753_qsz" if SOC_MEC1753_QSZ diff --git a/soc/microchip/mec/mec175x/soc.c b/soc/microchip/mec/mec175x/soc.c new file mode 100644 index 00000000000000..6d7a502b082418 --- /dev/null +++ b/soc/microchip/mec/mec175x/soc.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static int soc_init(void) +{ + mec5_soc_common_init(); + return 0; +} + +/* Enabling HW debug and initializing the MEC interrupt aggregator should be done + * before driver are loaded to not overwrite driver interrupt configuration. + * Use early initialization category called soon after Zephyr z_cstart and before + * Zephyr starts making driver initialization calls. + */ +SYS_INIT(soc_init, EARLY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/microchip/mec/mec175x/soc.h b/soc/microchip/mec/mec175x/soc.h new file mode 100644 index 00000000000000..b0a2a46eef83a7 --- /dev/null +++ b/soc/microchip/mec/mec175x/soc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MEC5_SOC_H +#define __MEC5_SOC_H + +#define SYSCLK_DEFAULT_IOSC_HZ MHZ(96) + +#ifndef _ASMLANGUAGE + +#include "device_mec5.h" + +/* common SoC API */ +#include "soc_dt.h" +#include "soc_espi_channels.h" +#include "soc_gpio.h" +#include "soc_pcr.h" +#include "soc_pins.h" + +#endif + +#endif diff --git a/soc/microchip/mec/mech172x/CMakeLists.txt b/soc/microchip/mec/mech172x/CMakeLists.txt new file mode 100644 index 00000000000000..6d2a447f7293fb --- /dev/null +++ b/soc/microchip/mec/mech172x/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2024, Microchip Technology Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_sources(soc.c) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/microchip/mec/mech172x/Kconfig b/soc/microchip/mec/mech172x/Kconfig new file mode 100644 index 00000000000000..0bc04fbed20bd3 --- /dev/null +++ b/soc/microchip/mec/mech172x/Kconfig @@ -0,0 +1,21 @@ +# Microchip MECH172X MCU core series using MEC5 HAL and DTSI + +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_MECH172X + select ARM + select CPU_CORTEX_M4 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_FPU + select CPU_HAS_ARM_MPU + select HAS_SWO + select HAS_MEC5_HAL + select HAS_PM + +if SOC_SERIES_MECH172X + +config RTOS_TIMER + bool "MECH172x RTOS Timer(32KHz) as kernel timer" + +endif # SOC_SERIES_MECH172X diff --git a/soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nlj b/soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nlj new file mode 100644 index 00000000000000..fe25daf3a93b43 --- /dev/null +++ b/soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nlj @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MECH1723N-LJ MCU using MEC5 HAL +# N = 416KB total SRAM +# LJ = 176 pin package + +if SOC_MECH1723_NLJ + +config GPIO + default y + +config PINCTRL + default y + +endif # SOC_MECH1723_NLJ diff --git a/soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nsz b/soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nsz new file mode 100644 index 00000000000000..b13f40a231f3b7 --- /dev/null +++ b/soc/microchip/mec/mech172x/Kconfig.defconfig.mech1723nsz @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MECH1723N-SZ MCU using MEC5 HAL +# N = 416KB total SRAM +# SZ = 144 pin package + +if SOC_MECH1723_NSZ + +config GPIO + default y + +config PINCTRL + default y + +endif # SOC_MECH1723_NSZ diff --git a/soc/microchip/mec/mech172x/Kconfig.defconfig.series b/soc/microchip/mec/mech172x/Kconfig.defconfig.series new file mode 100644 index 00000000000000..5bbc8bb5df15cf --- /dev/null +++ b/soc/microchip/mec/mech172x/Kconfig.defconfig.series @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MECH172x MCU series configuration options + +if SOC_SERIES_MECH172X + +config NUM_IRQS + # must be >= the highest interrupt number used + # - include the UART interrupts + # All NVIC external sources. + default 181 + +rsource "Kconfig.defconfig.mech172*" + +config CORTEX_M_SYSTICK + depends on !RTOS_TIMER + +endif # SOC_SERIES_MECH172X diff --git a/soc/microchip/mec/mech172x/Kconfig.soc b/soc/microchip/mec/mech172x/Kconfig.soc new file mode 100644 index 00000000000000..3e3a210cf6cd04 --- /dev/null +++ b/soc/microchip/mec/mech172x/Kconfig.soc @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Microchip MECH172x MCU core series + +config SOC_SERIES_MECH172X + bool + select SOC_FAMILY_MICROCHIP_MEC + help + Enable support for Microchip MEC Cortex-M4F MCU series + +config SOC_SERIES + default "mech172x" if SOC_SERIES_MECH172X + +config SOC_MECH1723_NLJ + bool + select SOC_SERIES_MECH172X + +config SOC_MECH1723_NSZ + bool + select SOC_SERIES_MECH172X + +config SOC + default "mech1723_nlj" if SOC_MECH1723_NLJ + default "mech1723_nsz" if SOC_MECH1723_NSZ diff --git a/soc/microchip/mec/mech172x/soc.c b/soc/microchip/mec/mech172x/soc.c new file mode 100644 index 00000000000000..6d7a502b082418 --- /dev/null +++ b/soc/microchip/mec/mech172x/soc.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static int soc_init(void) +{ + mec5_soc_common_init(); + return 0; +} + +/* Enabling HW debug and initializing the MEC interrupt aggregator should be done + * before driver are loaded to not overwrite driver interrupt configuration. + * Use early initialization category called soon after Zephyr z_cstart and before + * Zephyr starts making driver initialization calls. + */ +SYS_INIT(soc_init, EARLY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/microchip/mec/mech172x/soc.h b/soc/microchip/mec/mech172x/soc.h new file mode 100644 index 00000000000000..b0a2a46eef83a7 --- /dev/null +++ b/soc/microchip/mec/mech172x/soc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MEC5_SOC_H +#define __MEC5_SOC_H + +#define SYSCLK_DEFAULT_IOSC_HZ MHZ(96) + +#ifndef _ASMLANGUAGE + +#include "device_mec5.h" + +/* common SoC API */ +#include "soc_dt.h" +#include "soc_espi_channels.h" +#include "soc_gpio.h" +#include "soc_pcr.h" +#include "soc_pins.h" + +#endif + +#endif diff --git a/soc/microchip/mec/soc.yml b/soc/microchip/mec/soc.yml index 6c20b24ff9ffbb..b3c68a80ed069b 100644 --- a/soc/microchip/mec/soc.yml +++ b/soc/microchip/mec/soc.yml @@ -8,3 +8,15 @@ family: socs: - name: mec172x_nsz - name: mec172x_nlj + - name: mec174x + socs: + - name: mec1743_qlj + - name: mec1743_qsz + - name: mec175x + socs: + - name: mec1753_qlj + - name: mec1753_qsz + - name: mech172x + socs: + - name: mech1723_nlj + - name: mech1723_nsz From b2082874d0950c173edd0f03e91b3b267581959b Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1073/1389] Bluetooth: Remove useless field `init_credits` Remove `bt_l2cap_le_endpoint.init_credits` that has zero uses and is just taking up RAM for no reason. Signed-off-by: Aleksander Wasaznik --- doc/releases/migration-guide-3.7.rst | 4 ++++ include/zephyr/bluetooth/l2cap.h | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 280f28370c2104..a89e3150d1b9c3 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -350,6 +350,10 @@ Bluetooth Host (:github:`71686`) +* The field :code:`init_credits` in :c:type:`bt_l2cap_le_endpoint` has been removed as it was no + longer used in Zephyr 3.4.0 and later. Any references to this field should be removed. No further + action is needed. + Networking ********** diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 02bb706f870689..4ba0610b77dd75 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -157,8 +157,6 @@ struct bt_l2cap_le_endpoint { uint16_t mtu; /** Endpoint Maximum PDU payload Size */ uint16_t mps; - /** Endpoint initial credits */ - uint16_t init_credits; /** Endpoint credits */ atomic_t credits; }; From 0d110ae7406a7705f869ba29ffa9954fabfab50b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1074/1389] scripts: west: build: add snippet argument to usage output Add example snippet argument to usage output of the "west build" command and use the singular "SNIPPET" in the generated help text. Signed-off-by: Henrik Brix Andersen --- scripts/west_commands/build.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index f7a605f4d7fc8a..0fda9745579e90 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -24,6 +24,7 @@ BUILD_USAGE = '''\ west build [-h] [-b BOARD[@REV]]] [-d BUILD_DIR] + [-S SNIPPET] [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only] [-n] [-o BUILD_OPT] [-f] [--sysbuild | --no-sysbuild] [--domain DOMAIN] @@ -135,7 +136,7 @@ def do_add_parser(self, parser_adder): group.add_argument('-n', '--just-print', '--dry-run', '--recon', dest='dry_run', action='store_true', help="just print build commands; don't run them") - group.add_argument('-S', '--snippet', dest='snippets', + group.add_argument('-S', '--snippet', dest='snippets', metavar='SNIPPET', action='append', default=[], help='''add the argument to SNIPPET; may be given multiple times. Forces CMake to run again if given. From c19fa5c404f5fd7e796324060ac158b025acef77 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1075/1389] scripts: west: completion: bash: add snippet arguments to build command Add snippet arguments to the "west build" command completion. Signed-off-by: Henrik Brix Andersen --- scripts/west_commands/completion/west-completion.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index cff8817c1eb915..68684c0a397e72 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -702,6 +702,7 @@ __comp_west_build() local special_opts=" --board -b + --snippet -S --pristine -p " From 783079f4e8d8198f535acd16a3d4a4cdcd5c6e06 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:24 +0200 Subject: [PATCH 1076/1389] scripts: list_shields: add script for listing the supported shields Add Python script for listing the supported shields. Signed-off-by: Henrik Brix Andersen --- scripts/list_shields.py | 71 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 scripts/list_shields.py diff --git a/scripts/list_shields.py b/scripts/list_shields.py new file mode 100755 index 00000000000000..dfbf2580eb40cc --- /dev/null +++ b/scripts/list_shields.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2024 Vestas Wind Systems A/S +# Copyright (c) 2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +import argparse +from dataclasses import dataclass +from pathlib import Path + +# +# This is shared code between the build system's 'shields' target +# and the 'west shields' extension command. If you change it, make +# sure to test both ways it can be used. +# +# (It's done this way to keep west optional, making it possible to run +# 'ninja shields' in a build directory without west installed.) +# + +@dataclass(frozen=True) +class Shield: + name: str + dir: Path + +def shield_key(shield): + return shield.name + +def find_shields(args): + ret = [] + + for root in args.board_roots: + for shields in find_shields_in(root): + ret.append(shields) + + return sorted(ret, key=shield_key) + +def find_shields_in(root): + shields = root / 'boards' / 'shields' + ret = [] + + for maybe_shield in (shields).iterdir(): + if not maybe_shield.is_dir(): + continue + for maybe_kconfig in maybe_shield.iterdir(): + if maybe_kconfig.name == 'Kconfig.shield': + for maybe_overlay in maybe_shield.iterdir(): + file_name = maybe_overlay.name + if file_name.endswith('.overlay'): + shield_name = file_name[:-len('.overlay')] + ret.append(Shield(shield_name, maybe_shield)) + + return sorted(ret, key=shield_key) + +def parse_args(): + parser = argparse.ArgumentParser(allow_abbrev=False) + add_args(parser) + return parser.parse_args() + +def add_args(parser): + # Remember to update west-completion.bash if you add or remove + # flags + parser.add_argument("--board-root", dest='board_roots', default=[], + type=Path, action='append', + help='add a board root, may be given more than once') + +def dump_shields(shields): + for shield in shields: + print(f' {shield.name}') + +if __name__ == '__main__': + dump_shields(find_shields(parse_args())) From 02f34e6a6fb7ed53b7170facf6be1ec7519de032 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1077/1389] scripts: west: commands: shields: add cmd for listing supported shields Add "west shields" command for listing supported shields. Signed-off-by: Henrik Brix Andersen --- scripts/west-commands.yml | 5 ++ scripts/west_commands/shields.py | 86 ++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 scripts/west_commands/shields.py diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 803d2b7b2d1a90..6cd0c511fb3bc6 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -10,6 +10,11 @@ west-commands: - name: boards class: Boards help: display information about supported boards + - file: scripts/west_commands/shields.py + commands: + - name: shields + class: Shields + help: display list of supported shields - file: scripts/west_commands/build.py commands: - name: build diff --git a/scripts/west_commands/shields.py b/scripts/west_commands/shields.py new file mode 100644 index 00000000000000..c091646039536c --- /dev/null +++ b/scripts/west_commands/shields.py @@ -0,0 +1,86 @@ +# Copyright (c) 2024 Vestas Wind Systems A/S +# Copyright (c) 2019 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import os +from pathlib import Path +import re +import sys +import textwrap + +from west import log +from west.commands import WestCommand + +from zephyr_ext_common import ZEPHYR_BASE + +sys.path.append(os.fspath(Path(__file__).parent.parent)) +import list_shields +import zephyr_module + +class Shields(WestCommand): + + def __init__(self): + super().__init__( + 'shields', + # Keep this in sync with the string in west-commands.yml. + 'display list of supported shield', + 'Display supported shields', + accepts_unknown_args=False) + + def do_add_parser(self, parser_adder): + default_fmt = '{name}' + parser = parser_adder.add_parser( + self.name, + help=self.help, + formatter_class=argparse.RawDescriptionHelpFormatter, + description=self.description, + epilog=textwrap.dedent(f'''\ + FORMAT STRINGS + -------------- + + Shields are listed using a Python 3 format string. Arguments + to the format string are accessed by name. + + The default format string is: + + "{default_fmt}" + + The following arguments are available: + + - name: shield name + - dir: directory that contains the shield definition + ''')) + + # Remember to update west-completion.bash if you add or remove + # flags + parser.add_argument('-f', '--format', default=default_fmt, + help='''Format string to use to list each shield; + see FORMAT STRINGS below.''') + parser.add_argument('-n', '--name', dest='name_re', + help='''a regular expression; only shields whose + names match NAME_RE will be listed''') + list_shields.add_args(parser) + + return parser + + def do_run(self, args, _): + if args.name_re is not None: + name_re = re.compile(args.name_re) + else: + name_re = None + + modules_board_roots = [ZEPHYR_BASE] + + for module in zephyr_module.parse_modules(ZEPHYR_BASE, self.manifest): + board_root = module.meta.get('build', {}).get('settings', {}).get('board_root') + if board_root is not None: + modules_board_roots.append(Path(module.project) / board_root) + + args.board_roots += modules_board_roots + + for shield in list_shields.find_shields(args): + if name_re is not None and not name_re.search(shield.name): + continue + log.inf(args.format.format(name=shield.name, dir=shield.dir)) From c5dc976342f534af01ad8c20d80a32e2b742d7fa Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1078/1389] scripts: west: commands: completion: bash: add "west shields" completion Add Bash completion for the "west shields" command. Signed-off-by: Henrik Brix Andersen --- .../completion/west-completion.bash | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index 68684c0a397e72..a4128ac227ba04 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -689,6 +689,37 @@ __comp_west_boards() esac } +__comp_west_shields() +{ + local other_opts=" + --format -f + --name -n + " + + local dir_opts=" + --board-root + " + + all_opts="$dir_opts $other_opts" + + case "$prev" in + $(__west_to_extglob "$other_opts") ) + # We don't know how to autocomplete these. + return + ;; + $(__west_to_extglob "$dir_opts") ) + __set_comp_dirs + return + ;; + esac + + case "$cur" in + -*) + __set_comp $all_opts + ;; + esac +} + __comp_west_build() { local bool_opts=" @@ -1124,6 +1155,7 @@ __comp_west() local zephyr_ext_cmds=( completion boards + shields build sign flash From 5f95d66e8801981bb496a7d692e0e495050a17b3 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1079/1389] scripts: west: commands: build: add argument for specifying shields Add "west build" argument for specifying shields. This saves users from having to do "west build ... -- -DSHIELD=...", making shields a much better integrated feature. Signed-off-by: Henrik Brix Andersen --- scripts/west_commands/build.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index 0fda9745579e90..56c463d0e4c26e 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -24,7 +24,7 @@ BUILD_USAGE = '''\ west build [-h] [-b BOARD[@REV]]] [-d BUILD_DIR] - [-S SNIPPET] + [-S SNIPPET] [--shield SHIELD] [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only] [-n] [-o BUILD_OPT] [-f] [--sysbuild | --no-sysbuild] [--domain DOMAIN] @@ -143,6 +143,13 @@ def do_add_parser(self, parser_adder): Do not use this option with manually specified -DSNIPPET... cmake arguments: the results are undefined''') + group.add_argument('--shield', dest='shields', metavar='SHIELD', + action='append', default=[], + help='''add the argument to SHIELD; may be given + multiple times. Forces CMake to run again if given. + Do not use this option with manually specified + -DSHIELD... cmake arguments: the results are + undefined''') group = parser.add_mutually_exclusive_group() group.add_argument('--sysbuild', action='store_true', @@ -215,7 +222,8 @@ def do_run(self, args, remainder): else: self._update_cache() if (self.args.cmake or self.args.cmake_opts or - self.args.cmake_only or self.args.snippets): + self.args.cmake_only or self.args.snippets or + self.args.shields): self.run_cmake = True else: self.run_cmake = True @@ -553,6 +561,8 @@ def _run_cmake(self, board, origin, cmake_opts): cmake_opts.extend(self.args.cmake_opts) if self.args.snippets: cmake_opts.append(f'-DSNIPPET={";".join(self.args.snippets)}') + if self.args.shields: + cmake_opts.append(f'-DSHIELD={";".join(self.args.shields)}') user_args = config_get('cmake-args', None) if user_args: From adf5223a7303d79365dda737e6ba306e47d4c173 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1080/1389] scripts: west: commands: completion: bash: support shield argument Add Bash completion support for "west build" shield argument. Signed-off-by: Henrik Brix Andersen --- scripts/west_commands/completion/west-completion.bash | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index a4128ac227ba04..3a528cded68a7f 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -401,6 +401,11 @@ __set_comp_west_boards() __set_comp ${boards[@]} } +__set_comp_west_shields() +{ + __set_comp "$(__west_x shields "$@")" +} + __comp_west_west() { case "$prev" in @@ -734,6 +739,7 @@ __comp_west_build() local special_opts=" --board -b --snippet -S + --shield --pristine -p " @@ -754,6 +760,10 @@ __comp_west_build() __set_comp_west_boards return ;; + --shield) + __set_comp_west_shields + return + ;; --pristine|-p) __set_comp "auto always never" return From f778662e987f2699c4a0289a741e5d95423046e7 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1081/1389] scripts: west: commands: build: fix pylint issue Do not end except block with a useless return, use a pass instead. This fixes pylint R1711: "Useless return at end of function or method (useless-return)". Signed-off-by: Henrik Brix Andersen --- scripts/west_commands/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index 56c463d0e4c26e..c137d1a95d2bf0 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -276,7 +276,7 @@ def _parse_remainder(self, remainder): if remainder: self.args.cmake_opts = remainder except IndexError: - return + pass def _parse_test_item(self, test_item): found_test_metadata = False From 298c6cddc6f48d0dc0c49a0bcdf76184f8bb5ae9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1082/1389] manifest: Update net-tools to latest version Updating net-tools to latest version in order to get the missing dnsmasq.conf file to Docker. Signed-off-by: Jukka Rissanen --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 4c9c58021947f0..1fae14d6373ed6 100644 --- a/west.yml +++ b/west.yml @@ -290,7 +290,7 @@ manifest: - debug revision: a819419603a2dfcb47f7f39092e1bc112e45d1ef - name: net-tools - revision: cd2eb1858a1570b49241e18fc1e1cd849a450af2 + revision: 7c7a856814d7f27509c8511fef14cec21f7d0c30 path: tools/net-tools groups: - tools From a25a37591c6b6d717e45e22e19f839bbeb254da8 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1083/1389] tests: i2c: i2c_ram: Add nrf52840dk overlay To make it compatible with this test. Signed-off-by: Luis Ubieda --- .../i2c/i2c_ram/boards/nrf52840dk_nrf52840.overlay | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/drivers/i2c/i2c_ram/boards/nrf52840dk_nrf52840.overlay diff --git a/tests/drivers/i2c/i2c_ram/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/i2c/i2c_ram/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..d2b49977fdccf3 --- /dev/null +++ b/tests/drivers/i2c/i2c_ram/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2c-ram = &arduino_i2c; + }; +}; From 9d437077f322ddf5d274403ebdd68a4e6221b5b9 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1084/1389] i2c: Add nRFX TWI RTIO-compatible driver First version of RTIO-compatible nrfx_twi driver. Test Setup: - Board: nrf52840dk - Test: `tests/drivers/i2c/i2c_ram` - Additional Kconfig: `CONFIG_I2C_RTIO=y` Signed-off-by: Luis Ubieda --- drivers/i2c/CMakeLists.txt | 11 +- drivers/i2c/Kconfig.nrfx | 1 + drivers/i2c/i2c_nrfx_twi_common.c | 163 ++++++++++++++++++++++++ drivers/i2c/i2c_nrfx_twi_common.h | 67 ++++++++++ drivers/i2c/i2c_nrfx_twi_rtio.c | 197 ++++++++++++++++++++++++++++++ 5 files changed, 438 insertions(+), 1 deletion(-) create mode 100644 drivers/i2c/i2c_nrfx_twi_common.c create mode 100644 drivers/i2c/i2c_nrfx_twi_common.h create mode 100644 drivers/i2c/i2c_nrfx_twi_rtio.c diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 13878b66d3b3fe..22c5dc252e6d30 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -29,7 +29,16 @@ else() endif() zephyr_library_sources_ifdef(CONFIG_I2C_EMUL i2c_emul.c) -zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI i2c_nrfx_twi.c) + +if(CONFIG_I2C_RTIO) + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI + i2c_nrfx_twi_rtio.c + i2c_nrfx_twi_common.c + ) +else() + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI i2c_nrfx_twi.c) +endif() + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWIM i2c_nrfx_twim.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWI i2c_sam_twi.c) diff --git a/drivers/i2c/Kconfig.nrfx b/drivers/i2c/Kconfig.nrfx index 6898d6e42a93e9..3c0596fc5b9b90 100644 --- a/drivers/i2c/Kconfig.nrfx +++ b/drivers/i2c/Kconfig.nrfx @@ -17,6 +17,7 @@ if I2C_NRFX config I2C_NRFX_TWI def_bool y depends on DT_HAS_NORDIC_NRF_TWI_ENABLED + select HAS_I2C_RTIO select NRFX_TWI0 if HAS_HW_NRF_TWI0 select NRFX_TWI1 if HAS_HW_NRF_TWI1 diff --git a/drivers/i2c/i2c_nrfx_twi_common.c b/drivers/i2c/i2c_nrfx_twi_common.c new file mode 100644 index 00000000000000..0d8bda63425f70 --- /dev/null +++ b/drivers/i2c/i2c_nrfx_twi_common.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2024, Croxel Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "i2c_nrfx_twi_common.h" + +#include +LOG_MODULE_DECLARE(i2c_nrfx_twi); + +int i2c_nrfx_twi_init(const struct device *dev) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + nrfx_err_t result = nrfx_twi_init(&config->twi, &config->config, + config->event_handler, (void *)dev); + if (result != NRFX_SUCCESS) { + LOG_ERR("Failed to initialize device: %s", + dev->name); + return -EBUSY; + } + + return 0; +} + +int i2c_nrfx_twi_configure(const struct device *dev, uint32_t dev_config) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_common_data *data = dev->data; + nrfx_twi_t const *inst = &config->twi; + + if (I2C_ADDR_10_BITS & dev_config) { + return -EINVAL; + } + + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_100K); + break; + case I2C_SPEED_FAST: + nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_400K); + break; + default: + LOG_ERR("unsupported speed"); + return -EINVAL; + } + data->dev_config = dev_config; + + return 0; +} + +int i2c_nrfx_twi_recover_bus(const struct device *dev) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + uint32_t scl_pin; + uint32_t sda_pin; + nrfx_err_t err; + + scl_pin = nrf_twi_scl_pin_get(config->twi.p_twi); + sda_pin = nrf_twi_sda_pin_get(config->twi.p_twi); + + err = nrfx_twi_bus_recover(scl_pin, sda_pin); + return (err == NRFX_SUCCESS ? 0 : -EBUSY); +} + +int i2c_nrfx_twi_msg_transfer(const struct device *dev, uint8_t flags, + uint8_t *buf, size_t buf_len, + uint16_t i2c_addr, bool more_msgs) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + int ret = 0; + uint32_t xfer_flags = 0; + nrfx_err_t res; + nrfx_twi_xfer_desc_t cur_xfer = { + .p_primary_buf = buf, + .primary_length = buf_len, + .address = i2c_addr, + .type = (flags & I2C_MSG_READ) ? + NRFX_TWI_XFER_RX : NRFX_TWI_XFER_TX, + }; + + if (flags & I2C_MSG_ADDR_10_BITS) { + LOG_ERR("10-bit I2C Addr devices not supported"); + ret = -ENOTSUP; + } else if (!(flags & I2C_MSG_STOP)) { + /* - if the transfer consists of more messages + * and the I2C repeated START is not requested + * to appear before the next message, suspend + * the transfer after the current message, + * so that it can be resumed with the next one, + * resulting in the two messages merged into + * a continuous transfer on the bus + */ + if (more_msgs) { + xfer_flags |= NRFX_TWI_FLAG_SUSPEND; + /* - otherwise, just finish the transfer without + * generating the STOP condition, unless the current + * message is an RX request, for which such feature + * is not supported + */ + } else if (flags & I2C_MSG_READ) { + ret = -ENOTSUP; + } else { + xfer_flags |= NRFX_TWI_FLAG_TX_NO_STOP; + } + } + + if (!ret) { + res = nrfx_twi_xfer(&config->twi, &cur_xfer, xfer_flags); + switch (res) { + case NRFX_SUCCESS: + break; + case NRFX_ERROR_BUSY: + ret = -EBUSY; + break; + default: + ret = -EIO; + break; + } + } + + return ret; +} + +#ifdef CONFIG_PM_DEVICE +int twi_nrfx_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_common_data *data = dev->data; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + i2c_nrfx_twi_init(dev); + if (data->dev_config) { + i2c_nrfx_twi_configure(dev, data->dev_config); + } + break; + + case PM_DEVICE_ACTION_SUSPEND: + nrfx_twi_uninit(&config->twi); + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + return ret; + } + break; + + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ diff --git a/drivers/i2c/i2c_nrfx_twi_common.h b/drivers/i2c/i2c_nrfx_twi_common.h new file mode 100644 index 00000000000000..a8925d3f75b161 --- /dev/null +++ b/drivers/i2c/i2c_nrfx_twi_common.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024, Croxel Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_I2C_I2C_NRFX_TWI_COMMON_H_ +#define ZEPHYR_DRIVERS_I2C_I2C_NRFX_TWI_COMMON_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2C_NRFX_TWI_INVALID_FREQUENCY ((nrf_twi_frequency_t)-1) +#define I2C_NRFX_TWI_FREQUENCY(bitrate) \ + (bitrate == I2C_BITRATE_STANDARD ? NRF_TWI_FREQ_100K \ + : bitrate == 250000 ? NRF_TWI_FREQ_250K \ + : bitrate == I2C_BITRATE_FAST ? NRF_TWI_FREQ_400K \ + : I2C_NRFX_TWI_INVALID_FREQUENCY) +#define I2C(idx) DT_NODELABEL(i2c##idx) +#define I2C_FREQUENCY(idx) \ + I2C_NRFX_TWI_FREQUENCY(DT_PROP(I2C(idx), clock_frequency)) + +struct i2c_nrfx_twi_common_data { + uint32_t dev_config; +}; + +struct i2c_nrfx_twi_config { + nrfx_twi_t twi; + nrfx_twi_config_t config; + nrfx_twi_evt_handler_t event_handler; + const struct pinctrl_dev_config *pcfg; +}; + +static inline nrfx_err_t i2c_nrfx_twi_get_evt_result(nrfx_twi_evt_t const *p_event) +{ + switch (p_event->type) { + case NRFX_TWI_EVT_DONE: + return NRFX_SUCCESS; + case NRFX_TWI_EVT_ADDRESS_NACK: + return NRFX_ERROR_DRV_TWI_ERR_ANACK; + case NRFX_TWI_EVT_DATA_NACK: + return NRFX_ERROR_DRV_TWI_ERR_DNACK; + default: + return NRFX_ERROR_INTERNAL; + } +} + +int i2c_nrfx_twi_init(const struct device *dev); +int i2c_nrfx_twi_configure(const struct device *dev, uint32_t dev_config); +int i2c_nrfx_twi_recover_bus(const struct device *dev); +int i2c_nrfx_twi_msg_transfer(const struct device *dev, uint8_t flags, + uint8_t *buf, size_t buf_len, + uint16_t i2c_addr, bool more_msgs); + +#ifdef CONFIG_PM_DEVICE +int twi_nrfx_pm_action(const struct device *dev, enum pm_device_action action); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_I2C_I2C_NRFX_TWI_COMMON_H_ */ diff --git a/drivers/i2c/i2c_nrfx_twi_rtio.c b/drivers/i2c/i2c_nrfx_twi_rtio.c new file mode 100644 index 00000000000000..cf2e4c06312d97 --- /dev/null +++ b/drivers/i2c/i2c_nrfx_twi_rtio.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2018, Nordic Semiconductor ASA + * Copyright (c) 2024, Croxel Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "i2c_nrfx_twi_common.h" + +#include +#include +LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL); + +struct i2c_nrfx_twi_rtio_data { + uint32_t dev_config; + bool twi_enabled; + struct i2c_rtio *ctx; +}; + +/* Enforce dev_config matches the same offset as the common structure, + * otherwise common API won't be compatible with i2c_nrfx_twi_rtio. + */ +BUILD_ASSERT( + offsetof(struct i2c_nrfx_twi_rtio_data, dev_config) == + offsetof(struct i2c_nrfx_twi_common_data, dev_config) +); + +static void i2c_nrfx_twi_complete(const struct device *dev, int status); + +static bool i2c_nrfx_twi_msg_start(const struct device *dev, uint8_t flags, + uint8_t *buf, size_t buf_len, uint16_t i2c_addr) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data; + struct i2c_rtio *ctx = dev_data->ctx; + int ret = 0; + + /** Enabling while already enabled ends up in a failed assertion: skip it. */ + if (!dev_data->twi_enabled) { + nrfx_twi_enable(&config->twi); + dev_data->twi_enabled = true; + } + + ret = i2c_nrfx_twi_msg_transfer(dev, flags, buf, buf_len, i2c_addr, false); + if (ret != 0) { + nrfx_twi_disable(&config->twi); + dev_data->twi_enabled = false; + + return i2c_rtio_complete(ctx, ret); + } + + return false; +} + +static bool i2c_nrfx_twi_start(const struct device *dev) +{ + struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data; + struct i2c_rtio *ctx = dev_data->ctx; + struct rtio_sqe *sqe = &ctx->txn_curr->sqe; + struct i2c_dt_spec *dt_spec = sqe->iodev->data; + + switch (sqe->op) { + case RTIO_OP_RX: + return i2c_nrfx_twi_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags, + sqe->buf, sqe->buf_len, dt_spec->addr); + case RTIO_OP_TINY_TX: + return i2c_nrfx_twi_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, + sqe->tiny_buf, sqe->tiny_buf_len, dt_spec->addr); + case RTIO_OP_TX: + return i2c_nrfx_twi_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, + sqe->buf, sqe->buf_len, dt_spec->addr); + case RTIO_OP_I2C_CONFIGURE: + (void)i2c_nrfx_twi_configure(dev, sqe->i2c_config); + return false; + case RTIO_OP_I2C_RECOVER: + (void)i2c_rtio_recover(ctx); + return false; + default: + LOG_ERR("Invalid op code %d for submission %p\n", sqe->op, (void *)sqe); + return i2c_rtio_complete(ctx, -EINVAL); + } +} + +static void i2c_nrfx_twi_complete(const struct device *dev, int status) +{ + /** Finalize if there are no more pending xfers */ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_rtio_data *data = dev->data; + struct i2c_rtio *const ctx = data->ctx; + + if (i2c_rtio_complete(ctx, status)) { + (void)i2c_nrfx_twi_start(dev); + } else { + nrfx_twi_disable(&config->twi); + data->twi_enabled = false; + } +} + +static int i2c_nrfx_twi_transfer(const struct device *dev, + struct i2c_msg *msgs, + uint8_t num_msgs, uint16_t addr) +{ + struct i2c_rtio *const ctx = ((struct i2c_nrfx_twi_rtio_data *) + dev->data)->ctx; + + return i2c_rtio_transfer(ctx, msgs, num_msgs, addr); +} + +static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) +{ + const struct device *dev = p_context; + int status = 0; + + if (i2c_nrfx_twi_get_evt_result(p_event) != NRFX_SUCCESS) { + status = -EIO; + } + + i2c_nrfx_twi_complete(dev, status); +} + +static void i2c_nrfx_twi_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_seq) +{ + struct i2c_nrfx_twi_rtio_data *data = dev->data; + struct i2c_rtio *const ctx = data->ctx; + + if (i2c_rtio_submit(ctx, iodev_seq)) { + (void)i2c_nrfx_twi_start(dev); + } +} + +static const struct i2c_driver_api i2c_nrfx_twi_driver_api = { + .configure = i2c_nrfx_twi_configure, + .transfer = i2c_nrfx_twi_transfer, + .recover_bus = i2c_nrfx_twi_recover_bus, + .iodev_submit = i2c_nrfx_twi_submit, +}; + +#define I2C_NRFX_TWI_RTIO_DEVICE(idx) \ + NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \ + BUILD_ASSERT(I2C_FREQUENCY(idx) != \ + I2C_NRFX_TWI_INVALID_FREQUENCY, \ + "Wrong I2C " #idx " frequency setting in dts"); \ + static int twi_##idx##_init(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_IRQN(I2C(idx)), DT_IRQ(I2C(idx), priority), \ + nrfx_isr, nrfx_twi_##idx##_irq_handler, 0); \ + const struct i2c_nrfx_twi_config *config = dev->config; \ + const struct i2c_nrfx_twi_rtio_data *dev_data = dev->data; \ + int err = pinctrl_apply_state(config->pcfg, \ + PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + return err; \ + } \ + i2c_rtio_init(dev_data->ctx, dev); \ + return i2c_nrfx_twi_init(dev); \ + } \ + I2C_RTIO_DEFINE(_i2c##idx##_twi_rtio, \ + DT_INST_PROP_OR(n, sq_size, CONFIG_I2C_RTIO_SQ_SIZE), \ + DT_INST_PROP_OR(n, cq_size, CONFIG_I2C_RTIO_CQ_SIZE)); \ + static struct i2c_nrfx_twi_rtio_data twi_##idx##_data = { \ + .ctx = &_i2c##idx##_twi_rtio, \ + }; \ + PINCTRL_DT_DEFINE(I2C(idx)); \ + static const struct i2c_nrfx_twi_config twi_##idx##z_config = { \ + .twi = NRFX_TWI_INSTANCE(idx), \ + .config = { \ + .skip_gpio_cfg = true, \ + .skip_psel_cfg = true, \ + .frequency = I2C_FREQUENCY(idx), \ + }, \ + .event_handler = event_handler, \ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \ + }; \ + PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \ + I2C_DEVICE_DT_DEFINE(I2C(idx), \ + twi_##idx##_init, \ + PM_DEVICE_DT_GET(I2C(idx)), \ + &twi_##idx##_data, \ + &twi_##idx##z_config, \ + POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, \ + &i2c_nrfx_twi_driver_api) + +#ifdef CONFIG_HAS_HW_NRF_TWI0 +I2C_NRFX_TWI_RTIO_DEVICE(0); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWI1 +I2C_NRFX_TWI_RTIO_DEVICE(1); +#endif From 1167e916c6418772310bc1084d4319120573758b Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1085/1389] i2c: nrfx_twi: Refactor nrfx_twi to utilize common code Code is refactored to take advantage of common codebase shared with i2c_nrfx_twi_rtio driver. Signed-off-by: Luis Ubieda --- drivers/i2c/CMakeLists.txt | 5 +- drivers/i2c/i2c_nrfx_twi.c | 188 +++++-------------------------------- 2 files changed, 26 insertions(+), 167 deletions(-) diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 22c5dc252e6d30..cb180ef24e3cd8 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -36,7 +36,10 @@ if(CONFIG_I2C_RTIO) i2c_nrfx_twi_common.c ) else() - zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI i2c_nrfx_twi.c) + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI + i2c_nrfx_twi.c + i2c_nrfx_twi_common.c + ) endif() zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWIM i2c_nrfx_twim.c) diff --git a/drivers/i2c/i2c_nrfx_twi.c b/drivers/i2c/i2c_nrfx_twi.c index 8af5fe4ddeecaf..56d3727e125ef7 100644 --- a/drivers/i2c/i2c_nrfx_twi.c +++ b/drivers/i2c/i2c_nrfx_twi.c @@ -11,6 +11,7 @@ #include #include #include +#include "i2c_nrfx_twi_common.h" #include #include @@ -23,19 +24,19 @@ LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL); #endif struct i2c_nrfx_twi_data { + uint32_t dev_config; struct k_sem transfer_sync; struct k_sem completion_sync; volatile nrfx_err_t res; - uint32_t dev_config; -}; - -struct i2c_nrfx_twi_config { - nrfx_twi_t twi; - nrfx_twi_config_t config; - const struct pinctrl_dev_config *pcfg; }; -static int i2c_nrfx_twi_recover_bus(const struct device *dev); +/* Enforce dev_config matches the same offset as the common structure, + * otherwise common API won't be compatible with i2c_nrfx_twi. + */ +BUILD_ASSERT( + offsetof(struct i2c_nrfx_twi_data, dev_config) == + offsetof(struct i2c_nrfx_twi_common_data, dev_config) +); static int i2c_nrfx_twi_transfer(const struct device *dev, struct i2c_msg *msgs, @@ -53,60 +54,17 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, nrfx_twi_enable(&config->twi); for (size_t i = 0; i < num_msgs; i++) { - if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) { - ret = -ENOTSUP; + bool more_msgs = ((i < (num_msgs - 1)) && + !(msgs[i + 1].flags & I2C_MSG_RESTART)); + + ret = i2c_nrfx_twi_msg_transfer(dev, msgs[i].flags, + msgs[i].buf, + msgs[i].len, addr, + more_msgs); + if (ret) { break; } - nrfx_twi_xfer_desc_t cur_xfer = { - .p_primary_buf = msgs[i].buf, - .primary_length = msgs[i].len, - .address = addr, - .type = (msgs[i].flags & I2C_MSG_READ) ? - NRFX_TWI_XFER_RX : NRFX_TWI_XFER_TX - }; - uint32_t xfer_flags = 0; - nrfx_err_t res; - - /* In case the STOP condition is not supposed to appear after - * the current message, check what is requested further: - */ - if (!(msgs[i].flags & I2C_MSG_STOP)) { - /* - if the transfer consists of more messages - * and the I2C repeated START is not requested - * to appear before the next message, suspend - * the transfer after the current message, - * so that it can be resumed with the next one, - * resulting in the two messages merged into - * a continuous transfer on the bus - */ - if ((i < (num_msgs - 1)) && - !(msgs[i + 1].flags & I2C_MSG_RESTART)) { - xfer_flags |= NRFX_TWI_FLAG_SUSPEND; - /* - otherwise, just finish the transfer without - * generating the STOP condition, unless the current - * message is an RX request, for which such feature - * is not supported - */ - } else if (msgs[i].flags & I2C_MSG_READ) { - ret = -ENOTSUP; - break; - } else { - xfer_flags |= NRFX_TWI_FLAG_TX_NO_STOP; - } - } - - res = nrfx_twi_xfer(&config->twi, &cur_xfer, xfer_flags); - if (res != NRFX_SUCCESS) { - if (res == NRFX_ERROR_BUSY) { - ret = -EBUSY; - break; - } else { - ret = -EIO; - break; - } - } - ret = k_sem_take(&data->completion_sync, I2C_TRANSFER_TIMEOUT_MSEC); if (ret != 0) { @@ -132,8 +90,7 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, break; } - res = data->res; - if (res != NRFX_SUCCESS) { + if (data->res != NRFX_SUCCESS) { ret = -EIO; break; } @@ -147,7 +104,8 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) { - struct i2c_nrfx_twi_data *dev_data = p_context; + const struct device *dev = p_context; + struct i2c_nrfx_twi_data *dev_data = (struct i2c_nrfx_twi_data *)dev->data; switch (p_event->type) { case NRFX_TWI_EVT_DONE: @@ -167,115 +125,12 @@ static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) k_sem_give(&dev_data->completion_sync); } -static int i2c_nrfx_twi_configure(const struct device *dev, - uint32_t dev_config) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - struct i2c_nrfx_twi_data *data = dev->data; - nrfx_twi_t const *inst = &config->twi; - - if (I2C_ADDR_10_BITS & dev_config) { - return -EINVAL; - } - - switch (I2C_SPEED_GET(dev_config)) { - case I2C_SPEED_STANDARD: - nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_100K); - break; - case I2C_SPEED_FAST: - nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_400K); - break; - default: - LOG_ERR("unsupported speed"); - return -EINVAL; - } - data->dev_config = dev_config; - - return 0; -} - -static int i2c_nrfx_twi_recover_bus(const struct device *dev) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - uint32_t scl_pin; - uint32_t sda_pin; - nrfx_err_t err; - - scl_pin = nrf_twi_scl_pin_get(config->twi.p_twi); - sda_pin = nrf_twi_sda_pin_get(config->twi.p_twi); - - err = nrfx_twi_bus_recover(scl_pin, sda_pin); - return (err == NRFX_SUCCESS ? 0 : -EBUSY); -} - static const struct i2c_driver_api i2c_nrfx_twi_driver_api = { .configure = i2c_nrfx_twi_configure, .transfer = i2c_nrfx_twi_transfer, .recover_bus = i2c_nrfx_twi_recover_bus, }; -static int init_twi(const struct device *dev) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - struct i2c_nrfx_twi_data *dev_data = dev->data; - nrfx_err_t result = nrfx_twi_init(&config->twi, &config->config, - event_handler, dev_data); - if (result != NRFX_SUCCESS) { - LOG_ERR("Failed to initialize device: %s", - dev->name); - return -EBUSY; - } - - return 0; -} - -#ifdef CONFIG_PM_DEVICE -static int twi_nrfx_pm_action(const struct device *dev, - enum pm_device_action action) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - struct i2c_nrfx_twi_data *data = dev->data; - int ret = 0; - - switch (action) { - case PM_DEVICE_ACTION_RESUME: - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; - } - init_twi(dev); - if (data->dev_config) { - i2c_nrfx_twi_configure(dev, data->dev_config); - } - break; - - case PM_DEVICE_ACTION_SUSPEND: - nrfx_twi_uninit(&config->twi); - - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); - if (ret < 0) { - return ret; - } - break; - - default: - ret = -ENOTSUP; - } - - return ret; -} -#endif /* CONFIG_PM_DEVICE */ - -#define I2C_NRFX_TWI_INVALID_FREQUENCY ((nrf_twi_frequency_t)-1) -#define I2C_NRFX_TWI_FREQUENCY(bitrate) \ - (bitrate == I2C_BITRATE_STANDARD ? NRF_TWI_FREQ_100K \ - : bitrate == 250000 ? NRF_TWI_FREQ_250K \ - : bitrate == I2C_BITRATE_FAST ? NRF_TWI_FREQ_400K \ - : I2C_NRFX_TWI_INVALID_FREQUENCY) -#define I2C(idx) DT_NODELABEL(i2c##idx) -#define I2C_FREQUENCY(idx) \ - I2C_NRFX_TWI_FREQUENCY(DT_PROP(I2C(idx), clock_frequency)) - #define I2C_NRFX_TWI_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \ BUILD_ASSERT(I2C_FREQUENCY(idx) != \ @@ -291,7 +146,7 @@ static int twi_nrfx_pm_action(const struct device *dev, if (err < 0) { \ return err; \ } \ - return init_twi(dev); \ + return i2c_nrfx_twi_init(dev); \ } \ static struct i2c_nrfx_twi_data twi_##idx##_data = { \ .transfer_sync = Z_SEM_INITIALIZER( \ @@ -307,6 +162,7 @@ static int twi_nrfx_pm_action(const struct device *dev, .skip_psel_cfg = true, \ .frequency = I2C_FREQUENCY(idx), \ }, \ + .event_handler = event_handler, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \ From caaaec67cddc248b8f41948098b9886ab6d8499d Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1086/1389] soc: nxp: rw: Add flash config header Add header file for flash configuration blocks which is an image header consumed by the RW bootrom. Signed-off-by: Declan Snyder --- soc/nxp/rw/CMakeLists.txt | 2 + soc/nxp/rw/flash_config.h | 191 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 soc/nxp/rw/flash_config.h diff --git a/soc/nxp/rw/CMakeLists.txt b/soc/nxp/rw/CMakeLists.txt index ace3c53eda847a..3790d07afd87a9 100644 --- a/soc/nxp/rw/CMakeLists.txt +++ b/soc/nxp/rw/CMakeLists.txt @@ -15,3 +15,5 @@ zephyr_linker_sources_ifdef(CONFIG_NXP_RW6XX_BOOT_HEADER ROM_START SORT_KEY 0 boot_header.ld) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") + +zephyr_include_directories(.) diff --git a/soc/nxp/rw/flash_config.h b/soc/nxp/rw/flash_config.h new file mode 100644 index 00000000000000..b5c7db0da72987 --- /dev/null +++ b/soc/nxp/rw/flash_config.h @@ -0,0 +1,191 @@ +/* + * Copyright 2021-2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __FLASH_CONFIG__ +#define __FLASH_CONFIG__ + +#include +#include +#include "fsl_common.h" + + +#define FC_BLOCK_TAG (0x42464346) +#define FC_BLOCK_VERSION (0x00000000) + +#define FC_CMD_SDR 0x01 +#define FC_CMD_DDR 0x21 +#define FC_RADDR_SDR 0x02 +#define FC_RADDR_DDR 0x22 +#define FC_CADDR_SDR 0x03 +#define FC_CADDR_DDR 0x23 +#define FC_MODE1_SDR 0x04 +#define FC_MODE1_DDR 0x24 +#define FC_MODE2_SDR 0x05 +#define FC_MODE2_DDR 0x25 +#define FC_MODE4_SDR 0x06 +#define FC_MODE4_DDR 0x26 +#define FC_MODE8_SDR 0x07 +#define FC_MODE8_DDR 0x27 +#define FC_WRITE_SDR 0x08 +#define FC_WRITE_DDR 0x28 +#define FC_READ_SDR 0x09 +#define FC_READ_DDR 0x29 +#define FC_LEARN_SDR 0x0A +#define FC_LEARN_DDR 0x2A +#define FC_DATSZ_SDR 0x0B +#define FC_DATSZ_DDR 0x2B +#define FC_DUMMY_SDR 0x0C +#define FC_DUMMY_DDR 0x2C +#define FC_DUMMY_RWDS_SDR 0x0D +#define FC_DUMMY_RWDS_DDR 0x2D +#define FC_JMP_ON_CS 0x1F +#define FC_STOP_EXE 0 + +#define FC_FLEXSPI_1PAD 0 +#define FC_FLEXSPI_2PAD 1 +#define FC_FLEXSPI_4PAD 2 +#define FC_FLEXSPI_8PAD 3 + +#define FC_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | \ + FLEXSPI_LUT_OPERAND1(op1) | FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1)) + + +enum { + kSerialFlash_1Pads = 1, + kSerialFlash_2Pads = 2, + kSerialFlash_4Pads = 4, + kSerialFlash_8Pads = 8, +}; + + +enum { + kFlexSpiSerialClk_30MHz = 1, + kFlexSpiSerialClk_50MHz = 2, + kFlexSpiSerialClk_60MHz = 3, + kFlexSpiSerialClk_80MHz = 4, + kFlexSpiSerialClk_100MHz = 5, + kFlexSpiSerialClk_120MHz = 6, + kFlexSpiSerialClk_133MHz = 7, + kFlexSpiSerialClk_166MHz = 8, + kFlexSpiSerialClk_200MHz = 9, +}; + + +enum { + kFlexSpiSerialClk_SDR_24MHz = 1, + kFlexSpiSerialClk_SDR_48MHz = 2, +}; + + +enum { + kFlexSpiSerialClk_DDR_48MHz = 1, +}; + + +enum { + kFlexSpiMiscOffset_DiffClkEnable = 0, + kFlexSpiMiscOffset_WordAddressableEnable = 3, + kFlexSpiMiscOffset_SafeConfigFreqEnable = + 4, + kFlexSpiMiscOffset_DdrModeEnable = 6, +}; + + +enum { + kDeviceConfigCmdType_Generic, + kDeviceConfigCmdType_QuadEnable, + kDeviceConfigCmdType_Spi2Xpi, + kDeviceConfigCmdType_Xpi2Spi, + kDeviceConfigCmdType_Spi2NoCmd, + kDeviceConfigCmdType_Reset, +}; + +typedef struct _fc_flexspi_dll_time { + uint8_t time_100ps; + uint8_t delay_cells; +} fc_flexspi_dll_time_t; + + +typedef struct _fc_flexspi_lut_seq { + uint8_t seqNum; + uint8_t seqId; + uint16_t reserved; +} fc_flexspi_lut_seq_t; + + +typedef struct _fc_flexspi_mem_config { + uint32_t tag; + uint32_t version; + uint32_t reserved0; + uint8_t readSampleClkSrc; + uint8_t csHoldTime; + uint8_t csSetupTime; + uint8_t columnAddressWidth; + uint8_t deviceModeCfgEnable; + uint8_t deviceModeType; + uint16_t waitTimeCfgCommands; + fc_flexspi_lut_seq_t deviceModeSeq; + uint32_t deviceModeArg; + uint8_t configCmdEnable; + uint8_t configModeType[3]; + fc_flexspi_lut_seq_t configCmdSeqs[3]; + uint32_t reserved1; + uint32_t configCmdArgs[3]; + uint32_t reserved2; + uint32_t controllerMiscOption; + uint8_t deviceType; + uint8_t sflashPadType; + uint8_t serialClkFreq; + uint8_t lutCustomSeqEnable; + uint32_t reserved3[2]; + uint32_t sflashA1Size; + uint32_t sflashA2Size; + uint32_t sflashB1Size; + uint32_t sflashB2Size; + uint32_t csPadSettingOverride; + uint32_t sclkPadSettingOverride; + uint32_t dataPadSettingOverride; + uint32_t dqsPadSettingOverride; + uint32_t timeoutInMs; + uint32_t commandInterval; + fc_flexspi_dll_time_t dataValidTime[2]; + uint16_t busyOffset; + uint16_t busyBitPolarity; + uint32_t lookupTable[64]; + fc_flexspi_lut_seq_t lutCustomSeq[12]; + uint32_t reserved4[4]; +} fc_flexspi_mem_config_t; + +typedef struct _fc_flexspi_nor_config { +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) + uint8_t padding[0x400]; +#endif + fc_flexspi_mem_config_t memConfig; + uint32_t pageSize; + uint32_t sectorSize; + uint8_t ipcmdSerialClkFreq; + uint8_t isUniformBlockSize; + uint8_t isDataOrderSwapped; + uint8_t reserved0[1]; + uint8_t serialNorType; + uint8_t needExitNoCmdMode; + uint8_t halfClkForNonReadCmd; + uint8_t needRestoreNoCmdMode; + uint32_t blockSize; + uint32_t flashStateCtx; + uint32_t reserve2[10]; + uint32_t fcb_fill[0x280]; +} fc_flexspi_nor_config_t; +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif From adb9ce2b3a1144c0cc3dc266b46b452734146fc1 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1087/1389] boards: nxp: Add frdm_rw612 Add basic board definition of the freedom rw612 board. Signed-off-by: Declan Snyder --- boards/nxp/frdm_rw612/CMakeLists.txt | 15 +++ boards/nxp/frdm_rw612/Kconfig.frdm_rw612 | 5 + boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c | 106 ++++++++++++++++ boards/nxp/frdm_rw612/board.cmake | 9 ++ boards/nxp/frdm_rw612/board.yml | 5 + boards/nxp/frdm_rw612/doc/index.rst | 116 ++++++++++++++++++ boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi | 16 +++ boards/nxp/frdm_rw612/frdm_rw612.dts | 57 +++++++++ boards/nxp/frdm_rw612/frdm_rw612.yaml | 18 +++ boards/nxp/frdm_rw612/frdm_rw612_defconfig | 15 +++ boards/nxp/frdm_rw612/pre_dt_board.cmake | 7 ++ 11 files changed, 369 insertions(+) create mode 100644 boards/nxp/frdm_rw612/CMakeLists.txt create mode 100644 boards/nxp/frdm_rw612/Kconfig.frdm_rw612 create mode 100644 boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c create mode 100644 boards/nxp/frdm_rw612/board.cmake create mode 100644 boards/nxp/frdm_rw612/board.yml create mode 100644 boards/nxp/frdm_rw612/doc/index.rst create mode 100644 boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi create mode 100644 boards/nxp/frdm_rw612/frdm_rw612.dts create mode 100644 boards/nxp/frdm_rw612/frdm_rw612.yaml create mode 100644 boards/nxp/frdm_rw612/frdm_rw612_defconfig create mode 100644 boards/nxp/frdm_rw612/pre_dt_board.cmake diff --git a/boards/nxp/frdm_rw612/CMakeLists.txt b/boards/nxp/frdm_rw612/CMakeLists.txt new file mode 100644 index 00000000000000..a2a0b1227353d7 --- /dev/null +++ b/boards/nxp/frdm_rw612/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright 2022-2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +if(CONFIG_NXP_RW6XX_BOOT_HEADER) + zephyr_compile_definitions(BOARD_FLASH_SIZE=CONFIG_FLASH_SIZE*1024) + zephyr_library() + # This FCB is specific to the flash on this board, it won't work + # for boards with different flash chips. If you flash this FCB + # onto a board with a different flash chip you may break it. + # See MCUXpresso config tools for making a correct one. + zephyr_library_sources(W25Q512JVFIQ_FCB.c) +endif() diff --git a/boards/nxp/frdm_rw612/Kconfig.frdm_rw612 b/boards/nxp/frdm_rw612/Kconfig.frdm_rw612 new file mode 100644 index 00000000000000..53ccaf667f3a24 --- /dev/null +++ b/boards/nxp/frdm_rw612/Kconfig.frdm_rw612 @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_RW612 + select SOC_PART_NUMBER_RW612ETA2I diff --git a/boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c b/boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c new file mode 100644 index 00000000000000..cecf36ad9a2756 --- /dev/null +++ b/boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c @@ -0,0 +1,106 @@ +/* + * Copyright 2021-2024 NXP + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +__attribute__((section(".flash_conf"), used)) const fc_flexspi_nor_config_t +flexspi_config = { + .memConfig = { + .tag = FC_BLOCK_TAG, + .version = FC_BLOCK_VERSION, + .readSampleClkSrc = 1, + .csHoldTime = 3, + .csSetupTime = 3, + .deviceModeCfgEnable = 1, + .deviceModeSeq = {.seqNum = 1, .seqId = 2}, + .deviceModeArg = 0x02, + .configCmdEnable = 0, + .deviceType = 0x1, + .sflashPadType = kSerialFlash_4Pads, + .serialClkFreq = 5, + .sflashA1Size = 0x4000000U, + .sflashA2Size = 0, + .sflashB1Size = 0, + .sflashB2Size = 0, + .lookupTable = { + + [0] = FC_FLEXSPI_LUT_SEQ( + FC_CMD_SDR, FC_FLEXSPI_1PAD, 0xEC, + FC_RADDR_SDR, FC_FLEXSPI_4PAD, + 0x20), + [1] = FC_FLEXSPI_LUT_SEQ( + FC_MODE8_SDR, FC_FLEXSPI_4PAD, 0xF0, + FC_DUMMY_SDR, FC_FLEXSPI_4PAD, + 0x04), + [2] = FC_FLEXSPI_LUT_SEQ( + FC_READ_SDR, FC_FLEXSPI_4PAD, 0x04, + FC_STOP_EXE, FC_FLEXSPI_1PAD, 0x00), + + + [4 * 1 + 0] = FC_FLEXSPI_LUT_SEQ( + FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x05, + FC_READ_SDR, FC_FLEXSPI_1PAD, 0x04), + + + [4 * 2 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x31, FC_WRITE_SDR, + FC_FLEXSPI_1PAD, + 0x01), + + + [4 * 3 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x06, FC_STOP_EXE, FC_FLEXSPI_1PAD, + 0x00), + + + [4 * 5 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x21, FC_RADDR_SDR, + FC_FLEXSPI_1PAD, + 0x20), + + + [4 * 8 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0xDC, FC_RADDR_SDR, + FC_FLEXSPI_1PAD, + 0x20), + + + [4 * 9 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x34, FC_RADDR_SDR, + FC_FLEXSPI_1PAD, + 0x20), + [4 * 9 + 1] = + FC_FLEXSPI_LUT_SEQ(FC_WRITE_SDR, + FC_FLEXSPI_4PAD, + 0x00, + FC_STOP_EXE, FC_FLEXSPI_1PAD, + 0x00), + + + [4 * 11 + 0] = FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0xC7, FC_STOP_EXE, + FC_FLEXSPI_1PAD, + 0x00), + }, + }, + .pageSize = 0x100, + .sectorSize = 0x1000, + .ipcmdSerialClkFreq = 0, + .blockSize = 0x10000, + .fcb_fill[0] = 0xFFFFFFFF, +}; diff --git a/boards/nxp/frdm_rw612/board.cmake b/boards/nxp/frdm_rw612/board.cmake new file mode 100644 index 00000000000000..c7b1d7d51d4a30 --- /dev/null +++ b/boards/nxp/frdm_rw612/board.cmake @@ -0,0 +1,9 @@ +# Copyright 2022-2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=RW612" "--reset-after-load") + +board_runner_args(linkserver "--device=RW612:RDRW612") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/nxp/frdm_rw612/board.yml b/boards/nxp/frdm_rw612/board.yml new file mode 100644 index 00000000000000..e52333358c4686 --- /dev/null +++ b/boards/nxp/frdm_rw612/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_rw612 + vendor: nxp + socs: + - name: rw612 diff --git a/boards/nxp/frdm_rw612/doc/index.rst b/boards/nxp/frdm_rw612/doc/index.rst new file mode 100644 index 00000000000000..caefff181f0fd4 --- /dev/null +++ b/boards/nxp/frdm_rw612/doc/index.rst @@ -0,0 +1,116 @@ +.. _frdm_rw612: + +NXP FRDM_RW612 +############## + +Overview +******** + +The RW612 is a highly integrated, low-power tri-radio wireless MCU with an +integrated 260 MHz ARM Cortex-M33 MCU and Wi-Fi 6 + Bluetooth Low Energy (LE) 5.3 / 802.15.4 +radios designed for a broad array of applications, including connected smart home devices, +gaming controllers, enterprise and industrial automation, smart accessories and smart energy. + +The RW612 MCU subsystem includes 1.2 MB of on-chip SRAM and a high-bandwidth Quad SPI interface +with an on-the-fly decryption engine for securely accessing off-chip XIP flash. + +The advanced design of the RW612 delivers tight integration, low power and highly secure +operation in a space- and cost-efficient wireless MCU requiring only a single 3.3 V power supply. + +Hardware +******** + +- 260 MHz ARM Cortex-M33, tri-radio cores for Wifi 6 + BLE 5.3 + 802.15.4 +- 1.2 MB on-chip SRAM + +Supported Features +================== + ++-----------+------------+-----------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+===================================+ +| NVIC | on-chip | nested vector interrupt controller| ++-----------+------------+-----------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-----------------------------------+ +| MCI_IOMUX | on-chip | pinmux | ++-----------+------------+-----------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-----------------------------------+ +| USART | on-chip | serial | ++-----------+------------+-----------------------------------+ + + +The default configuration can be found in the defconfig file: + + :zephyr_file:`boards/nxp/frdm_rw612/frdm_rw612_defconfig` + +Other hardware features are not currently supported + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Configuring a Debug Probe +========================= + +A debug probe is used for both flashing and debugging the board. This board is +configured by default to use the JLink Firmware. + +Configuring a Console +===================== + +Connect a USB cable from your PC to J10, and use the serial terminal of your choice +(minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Flashing +======== + +Here is an example for the :ref:`hello_world` application. This example uses the +:ref:`jlink-debug-host-tools` as default. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_rw612 + :goals: flash + +Open a serial terminal, reset the board (press the RESET button), and you should +see the following message in the terminal: + +.. code-block:: console + + ***** Booting Zephyr OS v3.6.0 ***** + Hello World! frdm_rw612 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. This example uses the +:ref:`jlink-debug-host-tools` as default. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_rw612 + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + ***** Booting Zephyr OS zephyr-v3.6.0 ***** + Hello World! frdm_rw612 + + +Resources +========= + +.. _RW612 Website: + https://www.nxp.com/products/wireless-connectivity/wi-fi-plus-bluetooth-plus-802-15-4/wireless-mcu-with-integrated-tri-radiobr1x1-wi-fi-6-plus-bluetooth-low-energy-5-3-802-15-4:RW612 diff --git a/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi new file mode 100644 index 00000000000000..c9b0bcb8984a1e --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright 2022-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + pinmux_flexcomm3_usart: pinmux_flexcomm3_usart { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + }; +}; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.dts b/boards/nxp/frdm_rw612/frdm_rw612.dts new file mode 100644 index 00000000000000..ad7237fb6583ec --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612.dts @@ -0,0 +1,57 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_rw612-pinctrl.dtsi" + +/ { + model = "nxp,frdm_rw612"; + + aliases { + led0 = &green_led; + }; + + chosen { + zephyr,sram = &sram_data; + zephyr,flash = &w25q512jvfiq; + zephyr,console = &flexcomm3; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&hsgpio0 12 0>; + }; + }; +}; + +&flexcomm3 { + compatible = "nxp,lpc-usart"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_flexcomm3_usart>; + pinctrl-names = "default"; +}; + +&hsgpio0 { + status = "okay"; +}; + +&flexspi { + status = "okay"; + /* Winbond external flash */ + w25q512jvfiq: w25q512jvfiq@0 { + compatible = "nxp,imx-flexspi-nor"; + reg = <0>; + size = <(DT_SIZE_M(512) / 8)>; + status = "okay"; + erase-block-size = <4096>; + write-block-size = <1>; + spi-max-frequency = <133000000>; + }; +}; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.yaml b/boards/nxp/frdm_rw612/frdm_rw612.yaml new file mode 100644 index 00000000000000..cbb95c517163b5 --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612.yaml @@ -0,0 +1,18 @@ +# +# Copyright 2022-2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: frdm_rw612 +name: NXP FRDM_RW612 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 960 +flash: 65536 +supported: + - gpio diff --git a/boards/nxp/frdm_rw612/frdm_rw612_defconfig b/boards/nxp/frdm_rw612/frdm_rw612_defconfig new file mode 100644 index 00000000000000..b987fa24dc09b3 --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612_defconfig @@ -0,0 +1,15 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_PINCTRL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_GPIO=y +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_TRUSTED_EXECUTION_SECURE=y diff --git a/boards/nxp/frdm_rw612/pre_dt_board.cmake b/boards/nxp/frdm_rw612/pre_dt_board.cmake new file mode 100644 index 00000000000000..2c56668e4355a8 --- /dev/null +++ b/boards/nxp/frdm_rw612/pre_dt_board.cmake @@ -0,0 +1,7 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "simple_bus_reg" on RW6XX boards as all GPIO ports use the same register. +list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") +# Suppress "spi_bus_bridge" as flexcomm node can be used as a SPI device. +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") From 57355f5f35f229893612d8b30bf7ff30a684564d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1088/1389] debug: Add MIPI STPv2 data stream decoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a decoder of STPv2 stream. Signed-off-by: Krzysztof Chruściński --- include/zephyr/debug/mipi_stp_decoder.h | 145 +++++ subsys/debug/CMakeLists.txt | 5 + subsys/debug/Kconfig | 6 + subsys/debug/mipi_stp_decoder.c | 791 ++++++++++++++++++++++++ 4 files changed, 947 insertions(+) create mode 100644 include/zephyr/debug/mipi_stp_decoder.h create mode 100644 subsys/debug/mipi_stp_decoder.c diff --git a/include/zephyr/debug/mipi_stp_decoder.h b/include/zephyr/debug/mipi_stp_decoder.h new file mode 100644 index 00000000000000..85b08af6419c41 --- /dev/null +++ b/include/zephyr/debug/mipi_stp_decoder.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEBUG_MIPI_STP_DECODER_H__ +#define ZEPHYR_INCLUDE_DEBUG_MIPI_STP_DECODER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup mipi_stp_decoder_apis STP Decoder API + * @ingroup coresight_apis + * @{ + */ + +/** @brief STPv2 opcodes. */ +enum mipi_stp_decoder_ctrl_type { + STP_DATA4 = 1, + STP_DATA8 = 2, + STP_DATA16 = 4, + STP_DATA32 = 8, + STP_DATA64 = 16, + STP_DECODER_NULL = 128, + STP_DECODER_MASTER, + STP_DECODER_MERROR, + STP_DECODER_CHANNEL, + STP_DECODER_VERSION, + STP_DECODER_FREQ, + STP_DECODER_GERROR, + STP_DECODER_FLAG, + STP_DECODER_ASYNC, + STP_DECODER_NOT_SUPPORTED, +}; + +/** @brief Convert type to a string literal. + * + * @param _type type + * @return String literal. + */ +#define STP_DECODER_TYPE2STR(_type) \ + _type == STP_DATA4 ? "DATA4" : (\ + _type == STP_DATA8 ? "DATA8" : (\ + _type == STP_DATA16 ? "DATA16" : (\ + _type == STP_DATA32 ? "DATA32" : (\ + _type == STP_DATA64 ? "DATA64" : (\ + _type == STP_DECODER_NULL ? "NULL" : (\ + _type == STP_DECODER_MASTER ? "MASTER" : (\ + _type == STP_DECODER_MERROR ? "MERROR" : (\ + _type == STP_DECODER_CHANNEL ? "CHANNEL" : (\ + _type == STP_DECODER_VERSION ? "VERSION" : (\ + _type == STP_DECODER_FREQ ? "FREQ" : (\ + _type == STP_DECODER_GERROR ? "GERROR" : (\ + _type == STP_DECODER_FLAG ? "FLAG" : (\ + _type == STP_DECODER_ASYNC ? "ASYNC" : (\ + "Unknown")))))))))))))) + +/** @brief Union with data associated with a given STP opcode. */ +union mipi_stp_decoder_data { + /** ID - used for master and channel. */ + uint16_t id; + + /** Frequency. */ + uint64_t freq; + + /** Version. */ + uint32_t ver; + + /** Error code. */ + uint32_t err; + + /** Dummy. */ + uint32_t dummy; + + /** Data. */ + uint64_t data; +}; + +/** @brief Callback signature. + * + * Callback is called whenever an element from STPv2 stream is decoded. + * + * @note Callback is called with interrupts locked. + * + * @param type Type. See @ref mipi_stp_decoder_ctrl_type. + * @param data Data. Data associated with a given @p type. + * @param ts Timestamp. Present if not NULL. + * @param marked Set to true if opcode was marked. + */ +typedef void (*mipi_stp_decoder_cb)(enum mipi_stp_decoder_ctrl_type type, + union mipi_stp_decoder_data data, + uint64_t *ts, bool marked); + +/** @brief Decoder configuration. */ +struct mipi_stp_decoder_config { + /** Indicates that decoder start in out of sync state. */ + bool start_out_of_sync; + + /** Callback. */ + mipi_stp_decoder_cb cb; +}; + +/** @brief Initialize the decoder. + * + * @param config Configuration. + * + * @retval 0 On successful initialization. + * @retval negative On failure. + */ +int mipi_stp_decoder_init(const struct mipi_stp_decoder_config *config); + +/** @brief Decode STPv2 stream. + * + * Function decodes the stream and calls the callback for every decoded element. + * + * @param data Data. + * @param len Data length. + * + * @retval 0 On successful decoding. + * @retval negative On failure. + */ +int mipi_stp_decoder_decode(const uint8_t *data, size_t len); + +/** @brief Indicate synchronization loss. + * + * If detected, then decoder starts to look for ASYNC marker and drops all data + * until ASYNC is found. Synchronization can be lost when there is data loss (e.g. + * due to overflow). + */ +void mipi_stp_decoder_sync_loss(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEBUG_MIPI_STP_DECODER_H__ */ diff --git a/subsys/debug/CMakeLists.txt b/subsys/debug/CMakeLists.txt index a6e59d54325395..d9cbc68b975b86 100644 --- a/subsys/debug/CMakeLists.txt +++ b/subsys/debug/CMakeLists.txt @@ -29,3 +29,8 @@ zephyr_sources_ifdef( CONFIG_GDBSTUB_SERIAL_BACKEND gdbstub/gdbstub_backend_serial.c ) + +zephyr_sources_ifdef( + CONFIG_MIPI_STP_DECODER + mipi_stp_decoder.c + ) diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 1f14b80b47cace..5fd5d9bfd5d2cc 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -444,3 +444,9 @@ config SEGGER_DEBUGMON This option will enable Segger's implementation of the debug monitor interrupt, overriding the default z_arm_debug_monitor symbol. + +config MIPI_STP_DECODER + bool "MIPI STPv2 decoder" + depends on !BIG_ENDIAN + help + Module decodes a stream of STPv2 data. diff --git a/subsys/debug/mipi_stp_decoder.c b/subsys/debug/mipi_stp_decoder.c new file mode 100644 index 00000000000000..39aacbdd4d7665 --- /dev/null +++ b/subsys/debug/mipi_stp_decoder.c @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#if defined(CONFIG_CPU_CORTEX_M) && !defined(CONFIG_CPU_CORTEX_M0) +#define UNALIGNED_ACCESS_SUPPORTED 1 +#else +#define UNALIGNED_ACCESS_SUPPORTED 0 +#endif + +enum stp_state { + STP_STATE_OP, + STP_STATE_DATA, + STP_STATE_TS, + STP_STATE_OUT_OF_SYNC, +}; + +enum stp_id { + STP_NULL, + STP_M8, + STP_MERR, + STP_C8, + STP_D8, + STP_D16, + STP_D32, + STP_D64, + STP_D8MTS, + STP_D16MTS, + STP_D32MTS, + STP_D64MTS, + STP_D4, + STP_D4MTS, + STP_FLAG_TS, + STP_VERSION, + STP_TAG_3NIBBLE_OP = STP_VERSION, + STP_NULL_TS, + STP_USER, + STP_USER_TS, + STP_TIME, + STP_TIME_TS, + STP_TRIG, + STP_TRIG_TS, + STP_FREQ, + STP_FREQ_TS, + STP_XSYNC, + STP_XSYNC_TS, + STP_FREQ_40, + STP_TAG_4NIBBLE_OP = STP_FREQ_40, + STP_FREQ_40_TS, + STP_DIP, + STP_M16, + STP_TAG_2NIBBLE_OP = STP_M16, + STP_GERR, + STP_C16, + STP_D8TS, + STP_D16TS, + STP_D32TS, + STP_D64TS, + STP_D8M, + STP_D16M, + STP_D32M, + STP_D64M, + STP_D4TS, + STP_D4M, + STP_FLAG, + STP_ASYNC, + STP_INVALID, + STP_OP_MAX +}; + +#define STP_LONG_OP_ID 0xF +#define STP_2B_OP_ID 0xF0 + +#define STP_VAR_DATA 0xff + +typedef void (*stp_cb)(uint64_t data, uint64_t ts); + +struct stp_item { + const char *name; + enum stp_id type; + uint8_t id[3]; + uint8_t id_ncnt; + uint8_t d_ncnt; + bool has_ts; + stp_cb cb; +}; + +#define STP_ITEM(_type, _id, _id_ncnt, _d_ncnt, _has_ts, _cb) \ + { \ + .name = STRINGIFY(_type), .type = _type, .id = {__DEBRACKET _id}, \ + .id_ncnt = _id_ncnt, .d_ncnt = _d_ncnt, \ + .has_ts = _has_ts, .cb = (stp_cb)_cb \ + } + +static struct mipi_stp_decoder_config cfg; +static uint64_t prev_ts; +static uint64_t base_ts; +static enum stp_state state; +static size_t ntotal; +static size_t ncnt; +static size_t noff; +static uint16_t curr_ch; + +static void data4_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA4, d, NULL, false); +} + +static void data8_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA8, d, NULL, false); +} + +static void data16_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA16, d, NULL, false); +} + +static void data32_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA32, d, NULL, false); +} + +static void data64_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA64, d, NULL, false); +} + +static void data4_m_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA4, d, NULL, true); +} + +static void data8_m_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA8, d, NULL, true); +} + +static void data16_m_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA16, d, NULL, true); +} + +static void data32_m_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA32, d, NULL, true); +} + +static void data64_m_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA64, d, NULL, true); +} + +static void data4_ts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA4, d, &ts, false); +} + +static void data8_ts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA8, d, &ts, false); +} + +static void data16_ts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA16, d, &ts, false); +} + +static void data32_ts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA32, d, &ts, false); +} + +static void data64_ts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA64, d, &ts, false); +} + +static void data4_mts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA4, d, &ts, true); +} + +static void data8_mts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA8, d, &ts, true); +} + +static void data16_mts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA16, d, &ts, true); +} + +static void data32_mts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA32, d, &ts, true); +} + +static void data64_mts_cb(uint64_t data, uint64_t ts) +{ + union mipi_stp_decoder_data d = {.data = data}; + + cfg.cb(STP_DATA64, d, &ts, true); +} + +static void master_cb(uint64_t id, uint64_t ts) +{ + ARG_UNUSED(ts); + uint16_t m_id = (uint16_t)id; + union mipi_stp_decoder_data data = {.id = m_id}; + + curr_ch = 0; + + cfg.cb(STP_DECODER_MASTER, data, NULL, false); +} + +static void channel16_cb(uint64_t id, uint64_t ts) +{ + uint16_t ch = (uint16_t)id; + + curr_ch = 0xFF00 & ch; + + ARG_UNUSED(ts); + union mipi_stp_decoder_data data = {.id = ch}; + + cfg.cb(STP_DECODER_CHANNEL, data, NULL, false); +} +static void channel_cb(uint64_t id, uint64_t ts) +{ + uint16_t ch = (uint16_t)id; + + ch |= curr_ch; + + ARG_UNUSED(ts); + union mipi_stp_decoder_data data = {.id = ch}; + + cfg.cb(STP_DECODER_CHANNEL, data, NULL, false); +} + +static void merror_cb(uint64_t err, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data data = {.err = (uint32_t)err}; + + cfg.cb(STP_DECODER_MERROR, data, NULL, false); +} + +static void gerror_cb(uint64_t err, uint64_t ts) +{ + ARG_UNUSED(ts); + union mipi_stp_decoder_data data = {.err = (uint32_t)err}; + + cfg.cb(STP_DECODER_GERROR, data, NULL, false); +} + +static void flag_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + ARG_UNUSED(data); + union mipi_stp_decoder_data dummy = {.dummy = 0}; + + cfg.cb(STP_DECODER_FLAG, dummy, NULL, false); +} + +static void flag_ts_cb(uint64_t unused, uint64_t ts) +{ + ARG_UNUSED(unused); + union mipi_stp_decoder_data data = {.dummy = 0}; + + cfg.cb(STP_DECODER_FLAG, data, &ts, false); +} + +static void version_cb(uint64_t version, uint64_t ts) +{ + ARG_UNUSED(ts); + + curr_ch = 0; + + union mipi_stp_decoder_data data = {.ver = version}; + + cfg.cb(STP_DECODER_VERSION, data, NULL, false); +} + +static void notsup_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + ARG_UNUSED(data); + + union mipi_stp_decoder_data dummy = {.dummy = 0}; + + cfg.cb(STP_DECODER_NOT_SUPPORTED, dummy, NULL, false); +} + +static void freq_cb(uint64_t freq, uint64_t ts) +{ + ARG_UNUSED(ts); + + union mipi_stp_decoder_data data = {.freq = freq}; + + cfg.cb(STP_DECODER_FREQ, data, NULL, false); +} + +static void freq_ts_cb(uint64_t freq, uint64_t ts) +{ + union mipi_stp_decoder_data data = {.freq = freq}; + + cfg.cb(STP_DECODER_FREQ, data, &ts, false); +} + +static void null_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + ARG_UNUSED(data); + + union mipi_stp_decoder_data dummy = {.dummy = 0}; + + cfg.cb(STP_DECODER_NULL, dummy, NULL, false); +} + +static void async_cb(uint64_t data, uint64_t ts) +{ + ARG_UNUSED(ts); + ARG_UNUSED(data); + + union mipi_stp_decoder_data dummy = {.dummy = 0}; + + cfg.cb(STP_DECODER_ASYNC, dummy, NULL, false); +} + +static const struct stp_item items[] = { + STP_ITEM(STP_NULL, (0x0), 1, 0, false, null_cb), + STP_ITEM(STP_M8, (0x1), 1, 2, false, master_cb), + STP_ITEM(STP_MERR, (0x2), 1, 2, false, merror_cb), + STP_ITEM(STP_C8, (0x3), 1, 2, false, channel_cb), + STP_ITEM(STP_D8, (0x4), 1, 2, false, data8_cb), + STP_ITEM(STP_D16, (0x5), 1, 4, false, data16_cb), + STP_ITEM(STP_D32, (0x6), 1, 8, false, data32_cb), + STP_ITEM(STP_D64, (0x7), 1, 16, false, data64_cb), + STP_ITEM(STP_D8MTS, (0x8), 1, 2, true, data8_mts_cb), + STP_ITEM(STP_D16MTS, (0x9), 1, 4, true, data16_mts_cb), + STP_ITEM(STP_D32MTS, (0xa), 1, 8, true, data32_mts_cb), + STP_ITEM(STP_D64MTS, (0xb), 1, 16, true, data64_mts_cb), + STP_ITEM(STP_D4, (0xc), 1, 1, false, data4_cb), + STP_ITEM(STP_D4MTS, (0xd), 1, 1, true, data4_mts_cb), + STP_ITEM(STP_FLAG_TS, (0xe), 1, 0, true, flag_ts_cb), + STP_ITEM(STP_VERSION, (0xf0, 0x00), 3, 1, false, version_cb), + STP_ITEM(STP_NULL_TS, (0xf0, 0x01), 3, 0, true, notsup_cb), + STP_ITEM(STP_USER, (0xf0, 0x02), 3, 0, false, notsup_cb), + STP_ITEM(STP_USER_TS, (0xf0, 0x03), 3, 0, true, notsup_cb), + STP_ITEM(STP_TIME, (0xf0, 0x04), 3, 0, false, notsup_cb), + STP_ITEM(STP_TIME_TS, (0xf0, 0x05), 3, 0, true, notsup_cb), + STP_ITEM(STP_TRIG, (0xf0, 0x06), 3, 0, false, notsup_cb), + STP_ITEM(STP_TRIG_TS, (0xf0, 0x07), 3, 0, true, notsup_cb), + STP_ITEM(STP_FREQ, (0xf0, 0x08), 3, 8, false, freq_cb), + STP_ITEM(STP_FREQ_TS, (0xf0, 0x09), 3, 8, true, freq_ts_cb), + STP_ITEM(STP_XSYNC, (0xf0, 0x0a), 3, 0, false, notsup_cb), + STP_ITEM(STP_XSYNC_TS, (0xf0, 0x0b), 3, 0, true, notsup_cb), + STP_ITEM(STP_FREQ_40, (0xf0, 0xf0), 4, 10, false, freq_cb), + STP_ITEM(STP_FREQ_40_TS, (0xf0, 0xf1), 4, 0, true, notsup_cb), + STP_ITEM(STP_DIP, (0xf0, 0xf2), 4, 0, false, notsup_cb), + STP_ITEM(STP_M16, (0xf1), 2, 4, false, master_cb), + STP_ITEM(STP_GERR, (0xf2), 2, 2, false, gerror_cb), + STP_ITEM(STP_C16, (0xf3), 2, 4, false, channel16_cb), + STP_ITEM(STP_D8TS, (0xf4), 2, 2, true, data8_ts_cb), + STP_ITEM(STP_D16TS, (0xf5), 2, 4, true, data16_ts_cb), + STP_ITEM(STP_D32TS, (0xf6), 2, 8, true, data32_ts_cb), + STP_ITEM(STP_D64TS, (0xf7), 2, 16, true, data64_ts_cb), + STP_ITEM(STP_D8M, (0xf8), 2, 2, false, data8_m_cb), + STP_ITEM(STP_D16M, (0xf9), 2, 4, false, data16_m_cb), + STP_ITEM(STP_D32M, (0xfa), 2, 8, false, data32_m_cb), + STP_ITEM(STP_D64M, (0xfb), 2, 16, false, data64_m_cb), + STP_ITEM(STP_D4TS, (0xfc), 2, 1, true, data4_ts_cb), + STP_ITEM(STP_D4M, (0xfd), 2, 1, false, data4_m_cb), + STP_ITEM(STP_FLAG, (0xfe), 2, 0, false, flag_cb), + STP_ITEM(STP_ASYNC, (0xff, 0xff, 0xff), 6, 16, false, async_cb), + STP_ITEM(STP_INVALID, (0x0), 0, 0, false, NULL), +}; + +/** @brief Decode a nibble and read opcode from the stream. + * + * Function reads a nibble and continues or starts decoding of a STP opcode. + * + * @param data Pointer to the stream. + * @param[in,out] noff Offset (in nibbles). + * @param nlen Length (in nibbles). + * @param[in,out] ncnt Current number of nibbles + * @param[in,out] ntotal Number of nibbles in the opcode. + * + * @retval STP_INVALID Opcode decoding is in progress. + * @retval opcode Decoded opcode. + */ +static inline uint8_t get_nibble(const uint8_t *data, size_t noff) +{ + uint8_t ret = data[noff / 2]; + + if (noff & 0x1UL) { + ret >>= 4; + } + + ret &= 0x0F; + + return ret; +} + +static inline void get_nibbles64(const uint8_t *src, size_t src_noff, uint8_t *dst, size_t dst_noff, + size_t nlen) +{ + bool src_ba = (src_noff & 0x1UL) == 0; + bool dst_ba = (dst_noff & 0x1UL) == 0; + uint64_t *src64 = (uint64_t *)&src[src_noff / 2]; + uint64_t *dst64 = (uint64_t *)&dst[dst_noff / 2]; + + if (nlen == 16) { + /* dst must be aligned. */ + if (src_ba) { + uint32_t *s32 = (uint32_t *)src64; + uint32_t *d32 = (uint32_t *)dst64; + + d32[0] = s32[0]; + d32[1] = s32[1]; + } else { + uint64_t part_a = src64[0] >> 4; + uint64_t part_b = src64[1] << 60; + + dst64[0] = part_a | part_b; + } + return; + } + + uint64_t mask = BIT64_MASK(nlen * 4) << (src_ba ? 0 : 4); + uint64_t src_d = src64[0] & mask; + + if (((src_noff ^ dst_noff) & 0x1UL) == 0) { + dst64[0] |= src_d; + } else if (dst_ba) { + dst64[0] |= (src_d >> 4); + } else { + dst64[0] |= (src_d << 4); + } +} + +/* Function performs getting nibbles in less efficient way but does not use unaligned + * access which may not be supported by some platforms. + */ +static void get_nibbles_unaligned(const uint8_t *src, size_t src_noff, uint8_t *dst, + size_t dst_noff, size_t nlen) +{ + for (size_t i = 0; i < nlen; i++) { + size_t idx = (src_noff + i) / 2; + size_t ni = (src_noff + i) & 0x1; + uint8_t n = src[idx] >> (ni ? 4 : 0); + size_t d_idx = (dst_noff + i) / 2; + size_t dni = (dst_noff + i) & 0x1; + + if (dni == 0) { + dst[d_idx] = n; + } else { + dst[d_idx] |= n << 4; + } + } +} + +static inline void get_nibbles(const uint8_t *src, size_t src_noff, uint8_t *dst, size_t dst_noff, + size_t nlen) +{ + if (!UNALIGNED_ACCESS_SUPPORTED) { + get_nibbles_unaligned(src, src_noff, dst, dst_noff, nlen); + return; + } + + bool src_ba = (src_noff & 0x1UL) == 0; + bool dst_ba = (dst_noff & 0x1UL) == 0; + uint32_t *src32 = (uint32_t *)&src[src_noff / 2]; + uint32_t *dst32 = (uint32_t *)&dst[dst_noff / 2]; + + if (nlen > 8) { + get_nibbles64(src, src_noff, dst, dst_noff, nlen); + return; + } else if (nlen == 8) { + /* dst must be aligned. */ + if (src_ba) { + dst32[0] = src32[0]; + } else { + uint32_t part_a = src32[0] >> 4; + uint32_t part_b = src32[1] << 28; + + dst32[0] = part_a | part_b; + } + return; + } + + uint32_t mask = BIT_MASK(nlen * 4) << (src_ba ? 0 : 4); + uint32_t src_d = src32[0] & mask; + + if (((src_noff ^ dst_noff) & 0x1UL) == 0) { + dst32[0] |= src_d; + } else if (dst_ba) { + dst32[0] |= (src_d >> 4); + } else { + dst32[0] |= (src_d << 4); + } +} + +/* Function swaps nibbles in a byte. */ +static uint8_t swap8(uint8_t byte) +{ + return (byte << 4) | (byte >> 4); +} + +/* Function swaps nibbles in a 16 bit variable. */ +static uint16_t swap16(uint16_t halfword) +{ + halfword = __builtin_bswap16(halfword); + uint16_t d1 = (halfword & 0xf0f0) >> 4; + uint16_t d2 = (halfword & 0x0f0f) << 4; + + return d1 | d2; +} + +/* Function swaps nibbles in a 32 bit word. */ +static uint32_t swap32(uint32_t word) +{ + word = __builtin_bswap32(word); + uint32_t d1 = (word & 0xf0f0f0f0) >> 4; + uint32_t d2 = (word & 0x0f0f0f0f) << 4; + + return d1 | d2; +} + +/* Function swaps nibbles in a 64 bit word. */ +static uint64_t swap64(uint64_t dword) +{ + uint32_t l = (uint32_t)dword; + uint32_t u = (uint32_t)(dword >> 32); + + return ((uint64_t)swap32(l) << 32) | (uint64_t)swap32(u); +} + +static void swap_n(uint8_t *data, uint32_t n) +{ + switch (n) { + case 2: + *data = swap8(*data); + break; + case 4: + *(uint16_t *)data = swap16(*(uint16_t *)data); + break; + case 8: + *(uint32_t *)data = swap32(*(uint32_t *)data); + break; + case 16: + *(uint64_t *)data = swap64(*(uint64_t *)data); + break; + default: + *(uint64_t *)data = swap64(*(uint64_t *)data); + *(uint64_t *)data >>= (4 * (16 - n)); + break; + } +} + +static enum stp_id get_op(const uint8_t *data, size_t *noff, size_t *nlen, size_t *ncnt, + size_t *ntotal) +{ + uint8_t op = 0; + + op = get_nibble(data, *noff); + + *noff += 1; + *ncnt += 1; + if (*ntotal == 0 && *ncnt == 1) { + /* Starting to read op. */ + /* op code has only 1 nibble. */ + if (op != 0xF) { + return (enum stp_id)op; + } + } else if (*ncnt == 2) { + if (op == 0xF) { + /* ASYNC*/ + *ntotal = 6; + } else if (op != 0) { + return (enum stp_id)(STP_TAG_2NIBBLE_OP - 1 + op); + } + } else if (*ncnt == 3) { + if (op != 0xf) { + return (enum stp_id)(STP_TAG_3NIBBLE_OP + op); + } else if (*ntotal == 0) { + *ntotal = 4; + } + } else if (*ncnt == *ntotal) { + if (*ntotal == 4) { + return (enum stp_id)(STP_TAG_4NIBBLE_OP + op); + } else { + return STP_ASYNC; + } + } + + return STP_INVALID; +} + +void mipi_stp_decoder_sync_loss(void) +{ + state = STP_STATE_OUT_OF_SYNC; + ncnt = 0; + ntotal = 0; +} + +int mipi_stp_decoder_decode(const uint8_t *data, size_t len) +{ + static enum stp_id curr_id = STP_INVALID; + static uint8_t data_buf[8] __aligned(sizeof(uint64_t)); + static uint8_t ts_buf[8] __aligned(sizeof(uint64_t)); + uint64_t *data64 = (uint64_t *)data_buf; + uint64_t *ts64 = (uint64_t *)ts_buf; + size_t nlen = 2 * len; + + do { + switch (state) { + case STP_STATE_OUT_OF_SYNC: { + uint8_t b = get_nibble(data, noff); + + noff++; + if (ncnt < 21 && b == 0xF) { + ncnt++; + } else if (ncnt == 21 && b == 0) { + curr_id = STP_INVALID; + ncnt = 0; + + items[STP_ASYNC].cb(0, 0); + state = STP_STATE_OP; + } else { + ncnt = 0; + } + break; + } + case STP_STATE_OP: { + curr_id = get_op(data, &noff, &nlen, &ncnt, &ntotal); + if (curr_id != STP_INVALID) { + ntotal = items[curr_id].d_ncnt; + ncnt = 0; + if (ntotal > 0) { + state = STP_STATE_DATA; + data64[0] = 0; + } else if (items[curr_id].has_ts) { + state = STP_STATE_TS; + } else { + /* item without data and ts, notify. */ + items[curr_id].cb(0, 0); + curr_id = STP_INVALID; + } + } + break; + } + case STP_STATE_DATA: { + size_t ncpy = MIN(ntotal - ncnt, nlen - noff); + + get_nibbles(data, noff, data_buf, ncnt, ncpy); + + ncnt += ncpy; + noff += ncpy; + if (ncnt == ntotal) { + swap_n(data_buf, ntotal); + ncnt = 0; + if (items[curr_id].has_ts) { + ncnt = 0; + ntotal = 0; + state = STP_STATE_TS; + } else { + items[curr_id].cb(*data64, 0); + curr_id = STP_INVALID; + state = STP_STATE_OP; + ntotal = 0; + ncnt = 0; + } + } + break; + } + case STP_STATE_TS: + if (ntotal == 0 && ncnt == 0) { + /* TS to be read but length is unknown yet */ + *ts64 = 0; + ntotal = get_nibble(data, noff); + noff++; + /* Values up to 12 represents number of nibbles on which + * timestamp is encoded. Above are the exceptions: + * - 13 => 14 nibbles + * - 14 => 16 nibbles + */ + if (ntotal > 12) { + if (ntotal == 13) { + ntotal = 14; + base_ts = ~BIT64_MASK(4 * ntotal) & prev_ts; + } else { + ntotal = 16; + base_ts = 0; + } + } else { + base_ts = ~BIT64_MASK(4 * ntotal) & prev_ts; + } + + } else { + size_t ncpy = MIN(ntotal - ncnt, nlen - noff); + + get_nibbles(data, noff, ts_buf, ncnt, ncpy); + ncnt += ncpy; + noff += ncpy; + if (ncnt == ntotal) { + swap_n(ts_buf, ntotal); + prev_ts = base_ts | *ts64; + items[curr_id].cb(*data64, prev_ts); + curr_id = STP_INVALID; + state = STP_STATE_OP; + ntotal = 0; + ncnt = 0; + } + } + break; + + default: + break; + } + } while (noff < nlen); + + noff = 0; + + return 0; +} + +int mipi_stp_decoder_init(const struct mipi_stp_decoder_config *config) +{ + state = config->start_out_of_sync ? STP_STATE_OUT_OF_SYNC : STP_STATE_OP; + ntotal = 0; + ncnt = 0; + cfg = *config; + prev_ts = 0; + base_ts = 0; + noff = 0; + + return 0; +} From 5abff030966053a8215f5d3442b625a423bdafb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1089/1389] tests: debug: Add test for MIPI STPv2 decoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test suite. Signed-off-by: Krzysztof Chruściński --- .../debug/mipi_stp_decoder/CMakeLists.txt | 8 + tests/subsys/debug/mipi_stp_decoder/README | 1 + tests/subsys/debug/mipi_stp_decoder/prj.conf | 2 + .../subsys/debug/mipi_stp_decoder/src/main.c | 325 ++++++++++++++++++ .../debug/mipi_stp_decoder/testcase.yaml | 6 + 5 files changed, 342 insertions(+) create mode 100644 tests/subsys/debug/mipi_stp_decoder/CMakeLists.txt create mode 100644 tests/subsys/debug/mipi_stp_decoder/README create mode 100644 tests/subsys/debug/mipi_stp_decoder/prj.conf create mode 100644 tests/subsys/debug/mipi_stp_decoder/src/main.c create mode 100644 tests/subsys/debug/mipi_stp_decoder/testcase.yaml diff --git a/tests/subsys/debug/mipi_stp_decoder/CMakeLists.txt b/tests/subsys/debug/mipi_stp_decoder/CMakeLists.txt new file mode 100644 index 00000000000000..4b55d300ab929c --- /dev/null +++ b/tests/subsys/debug/mipi_stp_decoder/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(mipi_stp_decoder) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/debug/mipi_stp_decoder/README b/tests/subsys/debug/mipi_stp_decoder/README new file mode 100644 index 00000000000000..c4e9984fc58875 --- /dev/null +++ b/tests/subsys/debug/mipi_stp_decoder/README @@ -0,0 +1 @@ +Test for MIPI STPv2 data stream decoder. diff --git a/tests/subsys/debug/mipi_stp_decoder/prj.conf b/tests/subsys/debug/mipi_stp_decoder/prj.conf new file mode 100644 index 00000000000000..10d6c08c2c283e --- /dev/null +++ b/tests/subsys/debug/mipi_stp_decoder/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_MIPI_STP_DECODER=y diff --git a/tests/subsys/debug/mipi_stp_decoder/src/main.c b/tests/subsys/debug/mipi_stp_decoder/src/main.c new file mode 100644 index 00000000000000..ecf519de4aa51c --- /dev/null +++ b/tests/subsys/debug/mipi_stp_decoder/src/main.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +static int cnt; +static enum mipi_stp_decoder_ctrl_type exp_type[10]; +static union mipi_stp_decoder_data exp_data[10]; +static size_t exp_data_len[10]; +static uint64_t exp_ts[10]; +static bool exp_marked[10]; +static int d_cnt; + +static void cb(enum mipi_stp_decoder_ctrl_type type, union mipi_stp_decoder_data data, uint64_t *ts, + bool marked) +{ + zassert_equal(exp_type[d_cnt], type, "Expected: %d got:%d", exp_type[d_cnt], type); + + if (exp_ts[d_cnt] == UINT64_MAX) { + zassert_equal(ts, NULL, NULL); + } else { + zassert_true(ts != NULL, NULL); + zassert_equal(exp_ts[d_cnt], *ts, "exp:%llx got:%llx", exp_ts[d_cnt], *ts); + } + + zassert_equal(exp_marked[d_cnt], marked, NULL); + zassert_equal( + memcmp((uint8_t *)&exp_data[d_cnt], (uint8_t *)&data.data, exp_data_len[d_cnt]), 0, + NULL); + d_cnt++; +} + +static const struct mipi_stp_decoder_config config = { + .cb = cb, +}; + +#define ADD_ITEM(_cnt, _type, _ts, _marked, _data) \ + do { \ + exp_type[_cnt] = _type; \ + exp_ts[_cnt] = (uint64_t)_ts; \ + exp_marked[_cnt] = _marked; \ + exp_data[_cnt].data = _data; \ + exp_data_len[_cnt++] = sizeof(_data); \ + } while (0) + +ZTEST(mipi_stp_decoder_test, test_chunk_null) +{ + uint8_t data[] = {0x00, 0x00}; + + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(cnt, d_cnt, NULL); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_master) +{ + /* 0x1(m8) 0xab 0x0 (null) 0xf1(m16) 0x3412 */ + uint8_t data[] = {0xa1, 0x0b, 0x1f, 0x34, 0x12}; + + ADD_ITEM(cnt, STP_DECODER_MASTER, UINT64_MAX, false, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_MASTER, UINT64_MAX, false, (uint16_t)0x4321); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(cnt, d_cnt, NULL); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_channel) +{ + /* 0(null) 1(m8) ab 3(c8) ab f3(c16) 4664 3(c8) bb 1(m8) 0b 3(c8) aa*/ + uint8_t data[] = {0x10, 0xba, 0xa3, 0xfb, 0x63, 0x44, 0x36, 0xbb, 0x01, 0x3b, 0xaa}; + + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_MASTER, UINT64_MAX, false, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DECODER_CHANNEL, UINT64_MAX, false, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DECODER_CHANNEL, UINT64_MAX, false, (uint16_t)0x6446); + /* MSB byte is taken from previous C16 */ + ADD_ITEM(cnt, STP_DECODER_CHANNEL, UINT64_MAX, false, (uint16_t)0x64bb); + ADD_ITEM(cnt, STP_DECODER_MASTER, UINT64_MAX, false, (uint8_t)0x0b); + /* M8 resets current channel */ + ADD_ITEM(cnt, STP_DECODER_CHANNEL, UINT64_MAX, false, (uint8_t)0xaa); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_data) +{ + /* 4(d8) ab 5(d16) 0x3456 6(d32) 0x11223344 7(d64) 0x1020304050607080 */ + /* f8(dm8) ab f9(dm16) 0x3456 fa(dm32) 0x11223344 fb(dm64) 0x1020304050607080 */ + uint8_t data[] = {0xa4, 0x5b, 0x43, 0x65, 0x16, 0x21, 0x32, 0x43, 0x74, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + + 0x8f, 0xba, 0x9f, 0x43, 0x65, 0xaf, 0x11, 0x22, 0x33, 0x44, + 0xbf, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; + + ADD_ITEM(cnt, STP_DATA8, UINT64_MAX, false, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DATA16, UINT64_MAX, false, (uint16_t)0x3456); + ADD_ITEM(cnt, STP_DATA32, UINT64_MAX, false, (uint32_t)0x11223344); + ADD_ITEM(cnt, STP_DATA64, UINT64_MAX, false, (uint32_t)0x1020304050607080); + ADD_ITEM(cnt, STP_DATA8, UINT64_MAX, true, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DATA16, UINT64_MAX, true, (uint16_t)0x3456); + ADD_ITEM(cnt, STP_DATA32, UINT64_MAX, true, (uint32_t)0x11223344); + ADD_ITEM(cnt, STP_DATA64, UINT64_MAX, true, (uint32_t)0x1020304050607080); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_data_ts) +{ + uint8_t data[] = { + /*d8ts + 13b TS */ 0x4f, + 0xba, + 0x1d, + 0x21, + 0x32, + 0x43, + 0x54, + 0x65, + 0x76, + 0x07, + /*d16ts + 3b TS */ 0x5f, + 0xba, + 0xdc, + 0x13, + 0x22, + /*d32ts + 3b TS */ 0x6f, + 0x11, + 0x22, + 0xba, + 0xdc, + 0x13, + 0x22, + /*d64ts + 3b TS */ 0x7f, + 0x11, + 0x22, + 0xba, + 0xdc, + 0x11, + 0x22, + 0x33, + 0x44, + 0x13, + 0x22, + /*d8mts + 14b TS */ 0xa8, + 0xeb, + 0x11, + 0x22, + 0x33, + 0x44, + 0x55, + 0x66, + 0x77, + 0x88, + /*d16mts + 2b TS */ 0xa9, + 0xcb, + 0x2d, + 0x31, + /*d32mts + 2b TS */ 0xaa, + 0xcb, + 0x1d, + 0x21, + 0x22, + 0x31, + /*d64mts + 2b TS */ 0xab, + 0xcb, + 0x1d, + 0x21, + 0x12, + 0x11, + 0x11, + 0x11, + 0x21, + 0x31, + }; + + ADD_ITEM(cnt, STP_DATA8, 0x11223344556677, false, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DATA16, 0x11223344556122, false, (uint16_t)0xabcd); + ADD_ITEM(cnt, STP_DATA32, 0x11223344556122, false, (uint32_t)0x1122abcd); + ADD_ITEM(cnt, STP_DATA64, 0x11223344556122, false, (uint64_t)0x1122abcd11223344); + ADD_ITEM(cnt, STP_DATA8, 0x1122334455667788, true, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DATA16, 0x1122334455667713, true, (uint16_t)0xabcd); + ADD_ITEM(cnt, STP_DATA32, 0x1122334455667713, true, (uint32_t)0xabcd1122); + ADD_ITEM(cnt, STP_DATA64, 0x1122334455667713, true, (uint64_t)0xabcd112211111111); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_multi_chunk_data_ts) +{ + /*d8ts + 13b TS */ + uint8_t data[] = {0x4f, 0xba, 0x1d, 0x21, 0x32}; + uint8_t data2[] = { + 0x43, 0x54, 0x65, 0x76, 0x07, + }; + + ADD_ITEM(cnt, STP_DATA8, 0x11223344556677, false, (uint8_t)0xab); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + + /* First part without any packet decoded. */ + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, 0, "got:%d exp:%d", d_cnt, 0); + + mipi_stp_decoder_decode(data2, sizeof(data2)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_errors) +{ + uint8_t data[] = {/*merr 0x12 gerr 0x12 null */ 0x12, 0xf2, 0x12, 0x02}; + + ADD_ITEM(cnt, STP_DECODER_MERROR, UINT64_MAX, false, (uint8_t)0x12); + ADD_ITEM(cnt, STP_DECODER_GERROR, UINT64_MAX, false, (uint8_t)0x12); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_freq) +{ + uint8_t data[] = {/* freq 0x11223344 null */ 0x0f, + 0x18, + 0x21, + 0x32, + 0x43, + 0x04, + /* freq_ts 0x11223344 + 2b TS */ 0x0f, + 0x19, + 0x21, + 0x32, + 0x43, + 0x24, + 0x12}; + + ADD_ITEM(cnt, STP_DECODER_FREQ, UINT64_MAX, false, (uint32_t)0x11223344); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_FREQ, 0x21ULL, false, (uint32_t)0x11223344); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_async) +{ + uint8_t data[] = {/* null async null*/ + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_ASYNC, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_multi_chunk_async) +{ + /* null async null split into 2 buffers */ + uint8_t data[] = { + 0xf0, + 0xff, + 0xff, + }; + uint8_t data2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_ASYNC, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + + /* First part only null packet is decoded */ + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, 1, "got:%d exp:%d", d_cnt, 1); + + mipi_stp_decoder_decode(data2, sizeof(data2)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_chunk_freq2) +{ + /* null async null split into 2 buffers */ + uint8_t data[] = {0xf0, 0x80, 0x00, 0xc4, 0xb4, 0x04}; + + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_FREQ, UINT64_MAX, false, (uint64_t)5000000); + + mipi_stp_decoder_decode(data, sizeof(data)); + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +ZTEST(mipi_stp_decoder_test, test_sync_loss) +{ + /* null async null split into 2 buffers */ + uint8_t data[] = {0xf0, 0x80, 0x00, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, 0x11, 0x11, 0x11, 0x11}; + + ADD_ITEM(cnt, STP_DECODER_NULL, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DECODER_ASYNC, UINT64_MAX, false, (uint8_t)0); + ADD_ITEM(cnt, STP_DATA32, UINT64_MAX, false, (uint32_t)0x11111111); + + mipi_stp_decoder_decode(data, 4); + mipi_stp_decoder_sync_loss(); + mipi_stp_decoder_decode(&data[4], sizeof(data) - 4); + + zassert_equal(d_cnt, cnt, "got:%d exp:%d", d_cnt, cnt); +} + +static void before(void *data) +{ + cnt = 0; + d_cnt = 0; + mipi_stp_decoder_init(&config); +} + +ZTEST_SUITE(mipi_stp_decoder_test, NULL, NULL, before, NULL, NULL); diff --git a/tests/subsys/debug/mipi_stp_decoder/testcase.yaml b/tests/subsys/debug/mipi_stp_decoder/testcase.yaml new file mode 100644 index 00000000000000..85d342cd60c55e --- /dev/null +++ b/tests/subsys/debug/mipi_stp_decoder/testcase.yaml @@ -0,0 +1,6 @@ +tests: + debug.mipi_stp_decoder: + filter: not CONFIG_BIG_ENDIAN + tags: stp_decoder + integration_platforms: + - native_posix From 6bc1c42e7bc98ada8e7ef8f5183a05dbca7f18a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1090/1389] doc: services: debugging: Add documentation for MIPI STP decoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add section about MIPI STP decoder. Signed-off-by: Krzysztof Chruściński --- doc/services/debugging/index.rst | 1 + doc/services/debugging/mipi_stp_decoder.rst | 43 +++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 doc/services/debugging/mipi_stp_decoder.rst diff --git a/doc/services/debugging/index.rst b/doc/services/debugging/index.rst index c1a455f5b1cae2..259fd894ac4d85 100644 --- a/doc/services/debugging/index.rst +++ b/doc/services/debugging/index.rst @@ -10,3 +10,4 @@ Debugging coredump.rst gdbstub.rst debugmon.rst + mipi_stp_decoder.rst diff --git a/doc/services/debugging/mipi_stp_decoder.rst b/doc/services/debugging/mipi_stp_decoder.rst new file mode 100644 index 00000000000000..dfba9c7e99b1ba --- /dev/null +++ b/doc/services/debugging/mipi_stp_decoder.rst @@ -0,0 +1,43 @@ +.. _mipi_stp_decoder: + +MIPI STP Decoder +################ + +The MIPI System Trace Protocol (MIPI STP) was developed as a generic base protocol that can +be shared by multiple application-specific trace protocols. It serves as a wrapper protocol +that merges disparate streams that typically contain different trace protocols from different +trace sources. Stream consists of opcode (shortest is 4 bit long) followed by optional data and +optional timestamp. There are opcodes for data (8, 16, 32, 64 bit data marked/not marked, with or +without timestamp), stream recognition (master and channel), synchronization (ASYNC opcode) and +others. + +One example where protocol is used is ARM Coresight STM (System Trace Macrocell) where data +written to Stimulus Port registers maps directly to STP stream. + +This module can be used to perform on-chip decoding of the data stream. STP v2 is used. + +Usage +##### + +Decoder is initialized with a callback. A callback is called on each decoded opcode. +Decoder has internal state since there are dependency between opcodes (e.g. timestamp can be +relative). Decoder can be in synchronization or not. Initial state is configurable. +If decoder is not synchronized to the stream then it decodes each nibble in search for ASYNC opcode. +Loss of synchronization can be indicated to the decoder by calling +:c:func:`mipi_stp_decoder_sync_loss`. :c:func:`mipi_stp_decoder_decode` is used to decode the data. + +Limitations +########### + +There are following limitations: + +* Decoder supports only little endian architectures. +* When decoding nibbles, it is more efficient when core supports unaligned memory access. + Implementation supports optimized version with unaligned memory access and generic one. + Optimized version is used for ARM Cortex-M (expect for M0). +* Limited set of the most common opcodes is implemented. + +API documentation +***************** + +.. doxygengroup:: mipi_stp_decoder_apis From 782e302066bfe0e53be87650f8e6e021a95b9017 Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1091/1389] net: gptp: fix again computation of follow up correction field Commit 413eceeddbe4 ("net: gptp: fix follow_up message correction_field") breaks computation of follow up correction field in case time aware system is not the grand master clock but behave as a transparent clock which relay sync and follow-up messages from one slave port to one or several master port(s). In this case, according to IEEE802.AS 11.1.3 and 11.2.14.2.3, md sync send state machine shall compute the sum of link propagation delay and residence time, expressed in grand master time base. Then this quantity shall be added to last received fup correction field to build value of correction field. This patch checks whether time aware system is the grand master clock or not, and computes value correction field accordingly. Signed-off-by: Jean-Nicolas Graux --- subsys/net/l2/ethernet/gptp/gptp_md.c | 46 +++++++++++++++++++++ subsys/net/l2/ethernet/gptp/gptp_messages.c | 15 ------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/subsys/net/l2/ethernet/gptp/gptp_md.c b/subsys/net/l2/ethernet/gptp/gptp_md.c index fd0c62182a4835..1c4cf53f899be9 100644 --- a/subsys/net/l2/ethernet/gptp/gptp_md.c +++ b/subsys/net/l2/ethernet/gptp/gptp_md.c @@ -29,11 +29,14 @@ static void gptp_md_sync_prepare(struct net_pkt *pkt, } static void gptp_md_follow_up_prepare(struct net_pkt *pkt, + struct net_pkt *sync, struct gptp_md_sync_info *sync_send, int port_number) { struct gptp_hdr *hdr; struct gptp_follow_up *fup; + uint64_t sync_ts_ns, delay_ns; + struct net_ptp_time *sync_ts = net_pkt_timestamp(sync); hdr = GPTP_HDR(pkt); fup = GPTP_FOLLOW_UP(pkt); @@ -45,6 +48,48 @@ static void gptp_md_follow_up_prepare(struct net_pkt *pkt, hdr->log_msg_interval = sync_send->log_msg_interval; + if (memcmp(GPTP_GLOBAL_DS()->gm_priority.root_system_id.grand_master_id, + GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN) == 0 && + GPTP_GLOBAL_DS()->gm_present) { + /* + * Time aware system acting as the Grand Master. + * + * Get preciseOriginTimestamp from previous sync message + * according to IEEE802.1AS 11.4.4.2.1 syncEventEgressTimestamp + */ + fup->prec_orig_ts_secs_high = htons(sync_ts->_sec.high); + fup->prec_orig_ts_secs_low = htonl(sync_ts->_sec.low); + fup->prec_orig_ts_nsecs = htonl(sync_ts->nanosecond); + /* + * Grand master clock should keep correction_field at zero, + * according to IEEE802.1AS Table 11-6 and 10.6.2.2.9 + */ + hdr->correction_field = 0LL; + } else { + /* + * Time aware system acting as a bridge. + */ + fup->prec_orig_ts_secs_high = + htons(sync_send->precise_orig_ts._sec.high); + fup->prec_orig_ts_secs_low = htonl(sync_send->precise_orig_ts._sec.low); + fup->prec_orig_ts_nsecs = htonl(sync_send->precise_orig_ts.nanosecond); + /* + * According to IEEE802.AS 11.1.3 and 11.2.14.2.3, when time aware + * system is operating as a transparent clock also called a bridge, it + * shall compute the sum of link propagation delay and residence time, + * expressed in grand master time base. Then this quantity shall be + * added to last received fup correction field to build value of + * correction field. + */ + sync_ts_ns = sync_ts->second; + sync_ts_ns *= NSEC_PER_SEC; + sync_ts_ns += sync_ts->nanosecond; + delay_ns = sync_ts_ns - sync_send->upstream_tx_time; + + hdr->correction_field = sync_send->follow_up_correction_field + + (int64_t)(sync_send->rate_ratio * delay_ns); + hdr->correction_field = htonll(hdr->correction_field << 16); + } fup->tlv_hdr.type = htons(GPTP_TLV_ORGANIZATION_EXT); fup->tlv_hdr.len = htons(sizeof(struct gptp_follow_up_tlv)); fup->tlv.org_id[0] = GPTP_FUP_TLV_ORG_ID_BYTE_0; @@ -852,6 +897,7 @@ static void gptp_md_sync_send_state_machine(int port) pkt = gptp_prepare_follow_up(port, state->sync_ptr); if (pkt) { gptp_md_follow_up_prepare(pkt, + state->sync_ptr, state->sync_send_ptr, port); gptp_send_follow_up(port, pkt); diff --git a/subsys/net/l2/ethernet/gptp/gptp_messages.c b/subsys/net/l2/ethernet/gptp/gptp_messages.c index d56b679ab7ae56..da25e358af6450 100644 --- a/subsys/net/l2/ethernet/gptp/gptp_messages.c +++ b/subsys/net/l2/ethernet/gptp/gptp_messages.c @@ -241,7 +241,6 @@ struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync) struct gptp_follow_up *fup; struct net_if *iface; struct net_pkt *pkt; - struct net_ptp_time *sync_ts; NET_ASSERT(sync); NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END)); @@ -259,7 +258,6 @@ struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync) hdr = GPTP_HDR(pkt); fup = GPTP_FOLLOW_UP(pkt); sync_hdr = GPTP_HDR(sync); - sync_ts = net_pkt_timestamp(sync); /* * Header configuration. @@ -271,11 +269,6 @@ struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync) hdr->ptp_version = GPTP_VERSION; hdr->sequence_id = sync_hdr->sequence_id; hdr->domain_number = 0U; - /* - * Grand master clock should keep correction_field at zero, - * according to IEEE802.1AS Table 11-6 and 10.6.2.2.9 - */ - hdr->correction_field = 0LL; hdr->flags.octets[0] = 0U; hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE; hdr->message_length = htons(sizeof(struct gptp_hdr) + @@ -287,14 +280,6 @@ struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync) hdr->reserved1 = 0U; hdr->reserved2 = 0U; - /* - * Get preciseOriginTimestamp from previous sync message - * according to IEEE802.1AS 11.4.4.2.1 syncEventEgressTimestamp - */ - fup->prec_orig_ts_secs_high = htons(sync_ts->_sec.high); - fup->prec_orig_ts_secs_low = htonl(sync_ts->_sec.low); - fup->prec_orig_ts_nsecs = htonl(sync_ts->nanosecond); - /* PTP configuration will be set by the MDSyncSend state machine. */ return pkt; From dd7ac4f0cb58b83d4c4f2873b0eddd02b1ea61da Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1092/1389] net: gptp: do not run clock master sync send SM if we are not the GM clock Without this patch, in case time aware system is grand master capable but is not the grand master clock and behave as a bridge so that it shall ONLY relay SYNC and FUP messages from slave port to master port(s), SYNC and FUP are mistakenly generated by ClockMasterSyncSend state machine. This patch only call ClockMasterSyncSend state machine in case a Grand Master clock is present and is this time aware system. This check is not described by IEEE802.1AS. Instead, according to 10.2.9.3, the SiteSyncSync state machine shall not take into account information from ClockMasterSyncSend in case this time aware system is not grand-master capable. Current implementation of ClockMasterSyncSend state machine sends sync indication to the PortSync entities, instead of sending it to the SiteSyncSync entity. And the SiteSyncSync state machine does not make any check. Signed-off-by: Jean-Nicolas Graux --- subsys/net/l2/ethernet/gptp/gptp_mi.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/subsys/net/l2/ethernet/gptp/gptp_mi.c b/subsys/net/l2/ethernet/gptp/gptp_mi.c index 2e460ce0303dd6..4d09a38fe1d67e 100644 --- a/subsys/net/l2/ethernet/gptp/gptp_mi.c +++ b/subsys/net/l2/ethernet/gptp/gptp_mi.c @@ -2014,7 +2014,22 @@ void gptp_mi_state_machines(void) gptp_mi_port_role_selection_state_machine(); gptp_mi_clk_master_sync_offset_state_machine(); #if defined(CONFIG_NET_GPTP_GM_CAPABLE) - gptp_mi_clk_master_sync_snd_state_machine(); + /* + * Only call ClockMasterSyncSend state machine in case a Grand Master clock + * is present and is this time aware system. + * This check is not described by IEEE802.1AS. Instead, according to + * 10.2.9.3, the SiteSyncSync state machine shall not take into account + * information from ClockMasterSyncSend in case this time aware system is + * not grand-master capable. Current implementation of ClockMasterSyncSend + * state machine send sync indication to the PortSync entities, instead of + * sending it to the SiteSyncSync entity. And the SiteSyncSync state machine + * does not make sanity check. + */ + if (memcmp(GPTP_GLOBAL_DS()->gm_priority.root_system_id.grand_master_id, + GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN) == 0 && + GPTP_GLOBAL_DS()->gm_present) { + gptp_mi_clk_master_sync_snd_state_machine(); + } #endif gptp_mi_clk_master_sync_rcv_state_machine(); } From ed6ff1de72d7c651f543500f00580a78394bc8d5 Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Sun, 26 May 2024 22:39:25 +0200 Subject: [PATCH 1093/1389] net: gptp: fix rate_ratio in gptp_mi_set_ps_sync_cmss() Setting a ration of 0 breaks the computation of scaled_rate_offset in gptp_md_follow_up_prepare(). According to IEEE802.1AS 10.2.2.3.9, when sent by clock master entity, rate_ratio shall be equal to gmRateRatio. But since in gptp_md_follow_up_prepare(), in case we are the grand master clock, we take the assumption that clock source is the local clock, we may set this ratio to 1.0. Signed-off-by: Jean-Nicolas Graux --- subsys/net/l2/ethernet/gptp/gptp_mi.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/subsys/net/l2/ethernet/gptp/gptp_mi.c b/subsys/net/l2/ethernet/gptp/gptp_mi.c index 4d09a38fe1d67e..bb5a36cf16b070 100644 --- a/subsys/net/l2/ethernet/gptp/gptp_mi.c +++ b/subsys/net/l2/ethernet/gptp/gptp_mi.c @@ -960,12 +960,17 @@ static void gptp_mi_set_ps_sync_cmss(void) sync_info->precise_orig_ts.second = current_time / NSEC_PER_SEC; sync_info->precise_orig_ts.nanosecond = current_time % NSEC_PER_SEC; - /* TODO calculate correction field properly, rate_ratio is also set to - * zero instead of being copied from global_ds as it affects the final - * value of FUP correction field. + /* TODO calculate rate ratio and correction field properly. + * Whenever time aware system is the grand master clock, we currently + * make the following shortcuts: + * - assuming that clock source is the local clock, + * rate_ratio is set to 1.0 instead of being copied from global_ds. + * - considering that precise origin timestamp is directly inherited + * from sync egress timestamp in gptp_md_follow_up_prepare(), + * follow_up_correction_field is set to 0. */ sync_info->follow_up_correction_field = 0; - sync_info->rate_ratio = 0; + sync_info->rate_ratio = 1.0; memcpy(&sync_info->src_port_id.clk_id, GPTP_DEFAULT_DS()->clk_id, From 9f260c000ddaa0add4851c1a40d476683a1b4c0e Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1094/1389] net: gptp: fix race condition on timestamp callback If time aware system has more than 1 gptp port, because there is only one boolean to handle callback registering, a race condition can occur for instance in case 2 master ports are waiting for a timestamp following sending of sync message. More in details, callback may be unregistered by port 1 while port 2 is waiting for timestamp event. The issue is solved by declaring as much as boolean and struct net_if_timestamp_cb as the number of declared ports (=CONFIG_NET_GPTP_NUM_PORTS). Signed-off-by: Jean-Nicolas Graux --- subsys/net/l2/ethernet/gptp/gptp_messages.c | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/subsys/net/l2/ethernet/gptp/gptp_messages.c b/subsys/net/l2/ethernet/gptp/gptp_messages.c index da25e358af6450..7fe558d8a2ca7e 100644 --- a/subsys/net/l2/ethernet/gptp/gptp_messages.c +++ b/subsys/net/l2/ethernet/gptp/gptp_messages.c @@ -16,10 +16,10 @@ LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL); #define NET_BUF_TIMEOUT K_MSEC(100) -static struct net_if_timestamp_cb sync_timestamp_cb; -static struct net_if_timestamp_cb pdelay_response_timestamp_cb; -static bool sync_cb_registered; -static bool ts_cb_registered; +static struct net_if_timestamp_cb sync_timestamp_cb[CONFIG_NET_GPTP_NUM_PORTS]; +static struct net_if_timestamp_cb pdelay_response_timestamp_cb[CONFIG_NET_GPTP_NUM_PORTS]; +static bool sync_cb_registered[CONFIG_NET_GPTP_NUM_PORTS]; +static bool ts_cb_registered[CONFIG_NET_GPTP_NUM_PORTS]; static const struct net_eth_addr gptp_multicast_eth_addr = { { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } }; @@ -98,8 +98,8 @@ static void gptp_sync_timestamp_callback(struct net_pkt *pkt) if (hdr->message_type == GPTP_SYNC_MESSAGE) { state->md_sync_timestamp_avail = true; - net_if_unregister_timestamp_cb(&sync_timestamp_cb); - sync_cb_registered = false; + net_if_unregister_timestamp_cb(&sync_timestamp_cb[port - 1]); + sync_cb_registered[port - 1] = false; /* The pkt was ref'ed in gptp_send_sync() */ net_pkt_unref(pkt); @@ -129,8 +129,8 @@ static void gptp_pdelay_response_timestamp_callback(struct net_pkt *pkt) goto out; } - net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb); - ts_cb_registered = false; + net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb[port - 1]); + ts_cb_registered[port - 1] = false; gptp_send_pdelay_follow_up(port, follow_up, net_pkt_timestamp(pkt)); @@ -624,13 +624,13 @@ void gptp_handle_pdelay_req(int port, struct net_pkt *pkt) GPTP_STATS_INC(port, rx_pdelay_req_count); - if (ts_cb_registered == true) { + if (ts_cb_registered[port - 1] == true) { NET_WARN("Multiple pdelay requests"); - net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb); - net_pkt_unref(pdelay_response_timestamp_cb.pkt); + net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb[port - 1]); + net_pkt_unref(pdelay_response_timestamp_cb[port - 1].pkt); - ts_cb_registered = false; + ts_cb_registered[port - 1] = false; } /* Prepare response and send */ @@ -639,7 +639,7 @@ void gptp_handle_pdelay_req(int port, struct net_pkt *pkt) return; } - net_if_register_timestamp_cb(&pdelay_response_timestamp_cb, + net_if_register_timestamp_cb(&pdelay_response_timestamp_cb[port - 1], reply, net_pkt_iface(pkt), gptp_pdelay_response_timestamp_callback); @@ -650,7 +650,7 @@ void gptp_handle_pdelay_req(int port, struct net_pkt *pkt) */ net_pkt_ref(reply); - ts_cb_registered = true; + ts_cb_registered[port - 1] = true; gptp_send_pdelay_resp(port, reply, net_pkt_timestamp(pkt)); } @@ -806,12 +806,12 @@ void gptp_handle_signaling(int port, struct net_pkt *pkt) void gptp_send_sync(int port, struct net_pkt *pkt) { - if (!sync_cb_registered) { - net_if_register_timestamp_cb(&sync_timestamp_cb, + if (!sync_cb_registered[port - 1]) { + net_if_register_timestamp_cb(&sync_timestamp_cb[port - 1], pkt, net_pkt_iface(pkt), gptp_sync_timestamp_callback); - sync_cb_registered = true; + sync_cb_registered[port - 1] = true; } GPTP_STATS_INC(port, tx_sync_count); From 00bfbd2c6ea4e4495d9b1b3d76958e44863cacef Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1095/1389] manifest: update mipi-syst to latest revision Update manifest to include recent fixes in mipi-syst. Signed-off-by: Anas Nashif --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 1fae14d6373ed6..4349b0d9d41ce5 100644 --- a/west.yml +++ b/west.yml @@ -288,7 +288,7 @@ manifest: path: modules/debug/mipi-sys-t groups: - debug - revision: a819419603a2dfcb47f7f39092e1bc112e45d1ef + revision: 71ace1f5caa03e56c8740a09863e685efb4b2360 - name: net-tools revision: 7c7a856814d7f27509c8511fef14cec21f7d0c30 path: tools/net-tools From db2dfcbce9b00cf6297ce6e24d37fe1b5353a84f Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1096/1389] dts: bindings: reset_controller: Clarify cell name Clarify that there needs to be a cell named "id" in order to be usable by the reset controller macros. Signed-off-by: Declan Snyder --- dts/bindings/reset/reset-controller.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dts/bindings/reset/reset-controller.yaml b/dts/bindings/reset/reset-controller.yaml index eddf52c376ada3..6a2cf5e10d3d60 100644 --- a/dts/bindings/reset/reset-controller.yaml +++ b/dts/bindings/reset/reset-controller.yaml @@ -7,4 +7,6 @@ properties: "#reset-cells": type: int required: true - description: Number of cells in reset property + description: | + Number of cells in reset property. There must be a cell + named "id" to use the reset_dt_spec macros. From c3a19d8a0d3c01f2e72e6a64b533c9b7cb3957aa Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1097/1389] dts: bindings: Add bindings for NXP LPC resets Add binding representing the peripheral reset controller of the NXP LPC SYSCON heritage hardware including SYSCON itself and the newer RSTCTL. Signed-off-by: Declan Snyder --- dts/bindings/reset/nxp,lpc-syscon-reset.yaml | 15 +++++++++++++++ dts/bindings/reset/nxp,rstctl.yaml | 18 ++++++++++++++++++ .../reset/nxp_syscon_reset_common.h | 12 ++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 dts/bindings/reset/nxp,lpc-syscon-reset.yaml create mode 100644 dts/bindings/reset/nxp,rstctl.yaml create mode 100644 include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h diff --git a/dts/bindings/reset/nxp,lpc-syscon-reset.yaml b/dts/bindings/reset/nxp,lpc-syscon-reset.yaml new file mode 100644 index 00000000000000..df4e01c2a2e635 --- /dev/null +++ b/dts/bindings/reset/nxp,lpc-syscon-reset.yaml @@ -0,0 +1,15 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: LPC SYSCON Peripheral reset controller + +compatible: "nxp,lpc-syscon-reset" + +include: [reset-controller.yaml] + +properties: + "#reset-cells": + const: 1 + +reset-cells: + - id diff --git a/dts/bindings/reset/nxp,rstctl.yaml b/dts/bindings/reset/nxp,rstctl.yaml new file mode 100644 index 00000000000000..04a1a48d043b6a --- /dev/null +++ b/dts/bindings/reset/nxp,rstctl.yaml @@ -0,0 +1,18 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP RSTCTL Peripheral reset controller + +compatible: "nxp,rstctl" + +include: [reset-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#reset-cells": + const: 1 + +reset-cells: + - id diff --git a/include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h b/include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h new file mode 100644 index 00000000000000..9888572325a0fa --- /dev/null +++ b/include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h @@ -0,0 +1,12 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NXP_SYSCON_RESET_COMMON_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NXP_SYSCON_RESET_COMMON_H_ + +#define NXP_SYSCON_RESET(offset, bit) ((offset << 16) | bit) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NXP_SYSCON_RESET_COMMON_H_ */ From e4334cc9ed9125b53eeeaa3af167cda4b234e0f4 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1098/1389] drivers: reset: Add NXP LPC SYSCON reset driver Add driver for the peripheral reset control function of the NXP LPC SYSCON SOC control module. Signed-off-by: Declan Snyder --- drivers/reset/CMakeLists.txt | 1 + drivers/reset/Kconfig | 1 + drivers/reset/Kconfig.lpc_syscon | 10 +++++ drivers/reset/reset_lpc_syscon.c | 65 ++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 drivers/reset/Kconfig.lpc_syscon create mode 100644 drivers/reset/reset_lpc_syscon.c diff --git a/drivers/reset/CMakeLists.txt b/drivers/reset/CMakeLists.txt index f27f31f683c110..8b33eaa86a72d6 100644 --- a/drivers/reset/CMakeLists.txt +++ b/drivers/reset/CMakeLists.txt @@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_RESET_STM32 reset_stm32.c) zephyr_library_sources_ifdef(CONFIG_RESET_NUMAKER reset_numaker.c) zephyr_library_sources_ifdef(CONFIG_RESET_INTEL_SOCFPGA reset_intel_socfpga.c) zephyr_library_sources_ifdef(CONFIG_RESET_NPCX reset_npcx.c) +zephyr_library_sources_ifdef(CONFIG_RESET_NXP_SYSCON reset_lpc_syscon.c) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 1d361aa8e243d4..ccd28e954d0b65 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,5 +34,6 @@ rsource "Kconfig.stm32" rsource "Kconfig.numaker" rsource "Kconfig.intel_socfpga" rsource "Kconfig.npcx" +rsource "Kconfig.lpc_syscon" endif # RESET diff --git a/drivers/reset/Kconfig.lpc_syscon b/drivers/reset/Kconfig.lpc_syscon new file mode 100644 index 00000000000000..cfa6bcdd558578 --- /dev/null +++ b/drivers/reset/Kconfig.lpc_syscon @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config RESET_NXP_SYSCON + bool "NXP Syscon Reset controller driver" + default y + depends on DT_HAS_NXP_LPC_SYSCON_RESET_ENABLED + help + Enable the NXP syscon reset controller driver. + Syscon is found on LPC parts and LPC heritage parts. diff --git a/drivers/reset/reset_lpc_syscon.c b/drivers/reset/reset_lpc_syscon.c new file mode 100644 index 00000000000000..9effda66518981 --- /dev/null +++ b/drivers/reset/reset_lpc_syscon.c @@ -0,0 +1,65 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_lpc_syscon_reset + +#include +#include +#include + +#include + +#define LPC_RESET_OFFSET(id) (id >> 16) +#define LPC_RESET_BIT(id) (BIT(id & 0xFFFF)) + +static int reset_nxp_syscon_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const volatile uint32_t *ctrl_reg = ((uint32_t *)dev->config)+(LPC_RESET_OFFSET(id)); + *status = (uint8_t)FIELD_GET((uint32_t)LPC_RESET_BIT(id), *ctrl_reg); + + return 0; +} + +static int reset_nxp_syscon_line_assert(const struct device *dev, uint32_t id) +{ + SYSCON->PRESETCTRLSET[LPC_RESET_OFFSET(id)] = FIELD_PREP(LPC_RESET_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_syscon_line_deassert(const struct device *dev, uint32_t id) +{ + SYSCON->PRESETCTRLCLR[LPC_RESET_OFFSET(id)] = FIELD_PREP(LPC_RESET_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_syscon_line_toggle(const struct device *dev, uint32_t id) +{ + uint8_t status = 0; + + reset_nxp_syscon_line_assert(dev, id); + + do { + reset_nxp_syscon_status(dev, id, &status); + } while (status != 0b1); + + reset_nxp_syscon_line_deassert(dev, id); + + return 0; +} + +static const struct reset_driver_api reset_nxp_syscon_driver_api = { + .status = reset_nxp_syscon_status, + .line_assert = reset_nxp_syscon_line_assert, + .line_deassert = reset_nxp_syscon_line_deassert, + .line_toggle = reset_nxp_syscon_line_toggle, +}; + +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, + (void *)(DT_REG_ADDR(DT_INST_PARENT(0)) + 0x100), + PRE_KERNEL_1, CONFIG_RESET_INIT_PRIORITY, + &reset_nxp_syscon_driver_api); From 77b7f808e2f9e14743827886b889b6fc1ec1b25f Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1099/1389] drivers: reset: Add NXP RSTCTL driver Add driver for NXP RSTCTL reset controller peripheral. Signed-off-by: Declan Snyder --- drivers/reset/CMakeLists.txt | 1 + drivers/reset/Kconfig | 1 + drivers/reset/Kconfig.nxp_rstctl | 10 ++++ drivers/reset/reset_nxp_rstctl.c | 80 ++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 drivers/reset/Kconfig.nxp_rstctl create mode 100644 drivers/reset/reset_nxp_rstctl.c diff --git a/drivers/reset/CMakeLists.txt b/drivers/reset/CMakeLists.txt index 8b33eaa86a72d6..84f0443cabb5f7 100644 --- a/drivers/reset/CMakeLists.txt +++ b/drivers/reset/CMakeLists.txt @@ -11,3 +11,4 @@ zephyr_library_sources_ifdef(CONFIG_RESET_NUMAKER reset_numaker.c) zephyr_library_sources_ifdef(CONFIG_RESET_INTEL_SOCFPGA reset_intel_socfpga.c) zephyr_library_sources_ifdef(CONFIG_RESET_NPCX reset_npcx.c) zephyr_library_sources_ifdef(CONFIG_RESET_NXP_SYSCON reset_lpc_syscon.c) +zephyr_library_sources_ifdef(CONFIG_RESET_NXP_RSTCTL reset_nxp_rstctl.c) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ccd28e954d0b65..87ba9c7576cac2 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -35,5 +35,6 @@ rsource "Kconfig.numaker" rsource "Kconfig.intel_socfpga" rsource "Kconfig.npcx" rsource "Kconfig.lpc_syscon" +rsource "Kconfig.nxp_rstctl" endif # RESET diff --git a/drivers/reset/Kconfig.nxp_rstctl b/drivers/reset/Kconfig.nxp_rstctl new file mode 100644 index 00000000000000..6e604b96643452 --- /dev/null +++ b/drivers/reset/Kconfig.nxp_rstctl @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config RESET_NXP_RSTCTL + bool "NXP RSTCTL driver" + default y + depends on DT_HAS_NXP_RSTCTL_ENABLED + help + Enable the driver for the NXP RSTCTL, + a peripheral reset controller. diff --git a/drivers/reset/reset_nxp_rstctl.c b/drivers/reset/reset_nxp_rstctl.c new file mode 100644 index 00000000000000..22d7cfa0650888 --- /dev/null +++ b/drivers/reset/reset_nxp_rstctl.c @@ -0,0 +1,80 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_rstctl + +#include +#include +#include + +#include + +#define NXP_RSTCTL_OFFSET(id) ((id >> 16) * sizeof(uint32_t)) +#define NXP_RSTCTL_BIT(id) (BIT(id & 0xFFFF)) +#define NXP_RSTCTL_CTL(id) (NXP_RSTCTL_OFFSET(id) + 0x10) +#define NXP_RSTCTL_SET(id) (NXP_RSTCTL_OFFSET(id) + 0x40) +#define NXP_RSTCTL_CLR(id) (NXP_RSTCTL_OFFSET(id) + 0x70) + +static int reset_nxp_rstctl_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const uint32_t *base = dev->config; + volatile const uint32_t *ctl_reg = base+(NXP_RSTCTL_CTL(id)/sizeof(uint32_t)); + uint32_t val = *ctl_reg; + + *status = (uint8_t)FIELD_GET(NXP_RSTCTL_BIT(id), val); + + return 0; +} + +static int reset_nxp_rstctl_line_assert(const struct device *dev, uint32_t id) +{ + const uint32_t *base = dev->config; + volatile uint32_t *set_reg = (uint32_t *)base+(NXP_RSTCTL_SET(id)/sizeof(uint32_t)); + + *set_reg = FIELD_PREP(NXP_RSTCTL_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_rstctl_line_deassert(const struct device *dev, uint32_t id) +{ + const uint32_t *base = dev->config; + volatile uint32_t *clr_reg = (uint32_t *)base+(NXP_RSTCTL_CLR(id)/sizeof(uint32_t)); + + *clr_reg = FIELD_PREP(NXP_RSTCTL_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_rstctl_line_toggle(const struct device *dev, uint32_t id) +{ + uint8_t status = 0; + + reset_nxp_rstctl_line_assert(dev, id); + + do { + reset_nxp_rstctl_status(dev, id, &status); + } while (status != 0b1); + + reset_nxp_rstctl_line_deassert(dev, id); + + return 0; +} + +static const struct reset_driver_api reset_nxp_rstctl_driver_api = { + .status = reset_nxp_rstctl_status, + .line_assert = reset_nxp_rstctl_line_assert, + .line_deassert = reset_nxp_rstctl_line_deassert, + .line_toggle = reset_nxp_rstctl_line_toggle, +}; + +#define NXP_RSTCTL_INIT(n) \ + DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, \ + (void *)DT_INST_REG_ADDR(n), \ + PRE_KERNEL_1, CONFIG_RESET_INIT_PRIORITY, \ + &reset_nxp_rstctl_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NXP_RSTCTL_INIT) From 4a9d11cdb359378a8200a5966f05e3841a2c6e31 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1100/1389] include: reset.h: Add _OR dt spec macros Add _OR versions of all the reset_dt_spec macros. Also bump the API version to 0.2.0 (unstable) since there are multiple implementations of this API. Signed-off-by: Declan Snyder --- include/zephyr/drivers/reset.h | 62 +++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/include/zephyr/drivers/reset.h b/include/zephyr/drivers/reset.h index 4e601ea8f9d474..c892b530076723 100644 --- a/include/zephyr/drivers/reset.h +++ b/include/zephyr/drivers/reset.h @@ -16,7 +16,7 @@ * @brief Reset Controller Interface * @defgroup reset_controller_interface Reset Controller Interface * @since 3.1 - * @version 0.1.0 + * @version 0.2.0 * @ingroup io_interfaces * @{ */ @@ -74,6 +74,27 @@ struct reset_dt_spec { .id = DT_RESET_ID_BY_IDX(node_id, idx) \ } +/** + * @brief Like RESET_DT_SPEC_GET_BY_IDX(), with a fallback to a default value + * + * If the devicetree node identifier 'node_id' refers to a node with a + * 'resets' property, this expands to + * RESET_DT_SPEC_GET_BY_IDX(node_id, idx). The @p + * default_value parameter is not expanded in this case. + * + * Otherwise, this expands to @p default_value. + * + * @param node_id devicetree node identifier + * @param idx logical index into the 'resets' property + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, resets), \ + (RESET_DT_SPEC_GET_BY_IDX(node_id, idx)), \ + (default_value)) + /** * @brief Equivalent to RESET_DT_SPEC_GET_BY_IDX(node_id, 0). * @@ -84,6 +105,18 @@ struct reset_dt_spec { #define RESET_DT_SPEC_GET(node_id) \ RESET_DT_SPEC_GET_BY_IDX(node_id, 0) +/** + * @brief Equivalent to + * RESET_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value). + * + * @param node_id devicetree node identifier + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_GET_OR(node_id, default_value) \ + RESET_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value) + /** * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT * instance's Reset Controller property at an index. @@ -96,6 +129,21 @@ struct reset_dt_spec { #define RESET_DT_SPEC_INST_GET_BY_IDX(inst, idx) \ RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx) +/** + * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT + * instance's 'resets' property at an index, with fallback + * + * @param inst DT_DRV_COMPAT instance number + * @param idx logical index into the 'resets' property + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \ + COND_CODE_1(DT_PROP_HAS_IDX(DT_DRV_INST(inst), resets, idx), \ + (RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)), \ + (default_value)) + /** * @brief Equivalent to RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0). * @@ -106,6 +154,18 @@ struct reset_dt_spec { #define RESET_DT_SPEC_INST_GET(inst) \ RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0) +/** + * @brief Equivalent to + * RESET_DT_SPEC_INST_GET_BY_IDX_OR(node_id, 0, default_value). + * + * @param inst DT_DRV_COMPAT instance number + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_INST_GET_OR(inst, default_value) \ + RESET_DT_SPEC_INST_GET_BY_IDX_OR(inst, 0, default_value) + /** @cond INTERNAL_HIDDEN */ /** From c766d1270b946252d5642b4a249de2d89d206f5d Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1101/1389] MAINTAINERS: Add decsny to reset collaborator Add myself to reset controller collaborator Signed-off-by: Declan Snyder --- MAINTAINERS.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index fabae903e97eb1..62b4cf8d461829 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1490,6 +1490,8 @@ Release Notes: "Drivers: Reset": status: odd fixes + collaborators: + - decsny files: - drivers/reset/ - include/zephyr/drivers/reset.h From 93f2f4dc0043982d6da2ae6d0eab6aa6bc3eaaba Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1102/1389] dts: bindings: Add reset device to some NXP schema Include reset device binding in some of the NXP LPC IP bindings to be able to add the resets property. Signed-off-by: Declan Snyder --- dts/bindings/arm/nxp,lpc-flexcomm.yaml | 2 +- dts/bindings/can/nxp,lpc-mcan.yaml | 2 +- dts/bindings/counter/nxp,mrt.yaml | 2 +- dts/bindings/ipm/nxp,lpc-mailbox.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dts/bindings/arm/nxp,lpc-flexcomm.yaml b/dts/bindings/arm/nxp,lpc-flexcomm.yaml index ffc27753c3dcea..57121b489ae258 100644 --- a/dts/bindings/arm/nxp,lpc-flexcomm.yaml +++ b/dts/bindings/arm/nxp,lpc-flexcomm.yaml @@ -5,7 +5,7 @@ description: LPC Flexcomm node compatible: "nxp,lpc-flexcomm" -include: [base.yaml, pinctrl-device.yaml] +include: [base.yaml, pinctrl-device.yaml, reset-device.yaml] properties: reg: diff --git a/dts/bindings/can/nxp,lpc-mcan.yaml b/dts/bindings/can/nxp,lpc-mcan.yaml index 48aef0031396c8..bd735c88561e6a 100644 --- a/dts/bindings/can/nxp,lpc-mcan.yaml +++ b/dts/bindings/can/nxp,lpc-mcan.yaml @@ -2,7 +2,7 @@ description: NXP LPC SoC series MCAN CAN FD controller compatible: "nxp,lpc-mcan" -include: ["bosch,m_can-base.yaml", pinctrl-device.yaml] +include: ["bosch,m_can-base.yaml", pinctrl-device.yaml, "reset-device.yaml"] properties: reg: diff --git a/dts/bindings/counter/nxp,mrt.yaml b/dts/bindings/counter/nxp,mrt.yaml index e9e05b6c5b5b06..18e4543cfe3dbd 100644 --- a/dts/bindings/counter/nxp,mrt.yaml +++ b/dts/bindings/counter/nxp,mrt.yaml @@ -5,7 +5,7 @@ description: NXP Multirate Timer compatible: "nxp,mrt" -include: base.yaml +include: [base.yaml, reset-device.yaml] properties: reg: diff --git a/dts/bindings/ipm/nxp,lpc-mailbox.yaml b/dts/bindings/ipm/nxp,lpc-mailbox.yaml index 12f99a83386677..14e96d7e0db214 100644 --- a/dts/bindings/ipm/nxp,lpc-mailbox.yaml +++ b/dts/bindings/ipm/nxp,lpc-mailbox.yaml @@ -5,7 +5,7 @@ description: LPC MAILBOX compatible: "nxp,lpc-mailbox" -include: base.yaml +include: [base.yaml, reset-device.yaml] properties: reg: From c2ff40819d06c9ba7e230c5190715ab6e409541f Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1103/1389] dts: nxp: Add resets properties to LPC heritage Add resets properties to nodes on the LPC heritage syscon parts. Signed-off-by: Declan Snyder --- dts/arm/nxp/nxp_lpc51u68.dtsi | 13 ++++++++++++ dts/arm/nxp/nxp_lpc54xxx.dtsi | 13 ++++++++++++ dts/arm/nxp/nxp_lpc55S0x_common.dtsi | 15 ++++++++++++++ dts/arm/nxp/nxp_lpc55S1x_common.dtsi | 15 ++++++++++++++ dts/arm/nxp/nxp_lpc55S2x_common.dtsi | 14 +++++++++++++ dts/arm/nxp/nxp_lpc55S3x_common.dtsi | 15 ++++++++++++++ dts/arm/nxp/nxp_lpc55S6x_common.dtsi | 16 ++++++++++++++ dts/arm/nxp/nxp_rt5xx_common.dtsi | 31 ++++++++++++++++++++++++++++ dts/arm/nxp/nxp_rt6xx_common.dtsi | 24 +++++++++++++++++++++ dts/arm/nxp/nxp_rw6xx_common.dtsi | 20 ++++++++++++++++++ 10 files changed, 176 insertions(+) diff --git a/dts/arm/nxp/nxp_lpc51u68.dtsi b/dts/arm/nxp/nxp_lpc51u68.dtsi index 964e863485ba97..3c69de8dd4ac65 100644 --- a/dts/arm/nxp/nxp_lpc51u68.dtsi +++ b/dts/arm/nxp/nxp_lpc51u68.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { cpus { @@ -26,6 +27,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x40000000 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; sram0:memory@20000000 { @@ -88,6 +93,7 @@ reg = <0x40086000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -96,6 +102,7 @@ reg = <0x40087000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -104,6 +111,7 @@ reg = <0x40088000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -112,6 +120,7 @@ reg = <0x40089000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -120,6 +129,7 @@ reg = <0x4008a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -128,6 +138,7 @@ reg = <0x40096000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -136,6 +147,7 @@ reg = <0x40097000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -144,6 +156,7 @@ reg = <0x40098000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc54xxx.dtsi b/dts/arm/nxp/nxp_lpc54xxx.dtsi index a5befec1257f0a..78ffb203a84ff4 100644 --- a/dts/arm/nxp/nxp_lpc54xxx.dtsi +++ b/dts/arm/nxp/nxp_lpc54xxx.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { aliases{ @@ -41,6 +42,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x40000000 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; /* @@ -151,6 +156,7 @@ reg = <0x40086000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -159,6 +165,7 @@ reg = <0x40087000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -167,6 +174,7 @@ reg = <0x40088000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -175,6 +183,7 @@ reg = <0x40089000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -183,6 +192,7 @@ reg = <0x4008a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -191,6 +201,7 @@ reg = <0x40096000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -199,6 +210,7 @@ reg = <0x40097000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -207,6 +219,7 @@ reg = <0x40098000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; }; diff --git a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi index c2f8295e575785..4ffb014f2814dc 100644 --- a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include / { cpus { @@ -68,6 +69,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -147,6 +152,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -155,6 +161,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -163,6 +170,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -171,6 +179,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -179,6 +188,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -187,6 +197,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -195,6 +206,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -203,6 +215,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -211,6 +224,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -222,6 +236,7 @@ interrupts = <43 0>, <44 0>; interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 7)>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index 05ad85196be8f2..c9b4b3ddb89789 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include / { cpus { @@ -73,6 +74,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -152,6 +157,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -160,6 +166,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -168,6 +175,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -176,6 +184,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -184,6 +193,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -192,6 +202,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -200,6 +211,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -208,6 +220,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -217,6 +230,7 @@ interrupts = <43 0>, <44 0>; interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 7)>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; status = "disabled"; }; @@ -226,6 +240,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi index 5a5e435083309e..a751693e201a92 100644 --- a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { aliases { @@ -88,6 +89,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x1000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -179,6 +184,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -187,6 +193,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -195,6 +202,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -203,6 +211,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -211,6 +220,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -219,6 +229,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -227,6 +238,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -235,6 +247,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -249,6 +262,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index 311ad16e3ace2a..6a5621d19b7bd5 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { cpus { @@ -73,6 +74,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x1000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -179,6 +184,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; dmas = <&dma0 4>, <&dma0 5>; dma-names = "rx", "tx"; status = "disabled"; @@ -189,6 +195,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; dmas = <&dma0 6>, <&dma0 7>; dma-names = "rx", "tx"; status = "disabled"; @@ -199,6 +206,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; dmas = <&dma0 10>, <&dma0 11>; dma-names = "rx", "tx"; status = "disabled"; @@ -209,6 +217,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; dmas = <&dma0 8>, <&dma0 9>; dma-names = "rx", "tx"; status = "disabled"; @@ -219,6 +228,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; dmas = <&dma0 12>, <&dma0 13>; dma-names = "rx", "tx"; status = "disabled"; @@ -229,6 +239,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; dmas = <&dma0 14>, <&dma0 15>; dma-names = "rx", "tx"; status = "disabled"; @@ -239,6 +250,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; dmas = <&dma0 16>, <&dma0 17>; dma-names = "rx", "tx"; status = "disabled"; @@ -249,6 +261,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; dmas = <&dma0 18>, <&dma0 19>; dma-names = "rx", "tx"; status = "disabled"; @@ -259,6 +272,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; dmas = <&dma0 2>, <&dma0 3>; dma-names = "rx", "tx"; status = "disabled"; @@ -318,6 +332,7 @@ interrupts = <43 0>, <44 0>; interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 7)>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index 3178e05a54eb17..22ca5d6b0ec282 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include / { aliases { @@ -113,6 +114,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x1000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -214,6 +219,7 @@ compatible = "nxp,lpc-mailbox"; reg = <0x8b000 0xEC>; interrupts = <31 0>; + resets = <&reset NXP_SYSCON_RESET(0, 26)>; status = "disabled"; }; @@ -222,6 +228,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -230,6 +237,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -238,6 +246,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -246,6 +255,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -254,6 +264,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -262,6 +273,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -270,6 +282,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -278,6 +291,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -300,6 +314,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -429,6 +444,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&syscon MCUX_MRT_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 0)>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index fc6714b951e0cd..fc24a062e8a2af 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include / { chosen { @@ -134,6 +135,18 @@ #clock-cells = <1>; }; + rstctl0: reset@0 { + compatible = "nxp,rstctl"; + reg = <0x0 0x80>; + #reset-cells = <1>; + }; + + rstctl1: reset@20000 { + compatible = "nxp,rstctl"; + reg = <0x20000 0x80>; + #reset-cells = <1>; + }; + uuid: uuid@2f50 { compatible = "nxp,lpc-uid"; reg = <0x2f50 0x10>; @@ -214,6 +227,7 @@ reg = <0x106000 0x1000>; interrupts = <14 0>; clocks = <&clkctl1 MCUX_FLEXCOMM0_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>; status = "disabled"; }; @@ -222,6 +236,7 @@ reg = <0x107000 0x1000>; interrupts = <15 0>; clocks = <&clkctl1 MCUX_FLEXCOMM1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>; status = "disabled"; }; @@ -230,6 +245,7 @@ reg = <0x108000 0x1000>; interrupts = <16 0>; clocks = <&clkctl1 MCUX_FLEXCOMM2_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>; status = "disabled"; }; @@ -238,6 +254,7 @@ reg = <0x109000 0x1000>; interrupts = <17 0>; clocks = <&clkctl1 MCUX_FLEXCOMM3_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>; status = "disabled"; }; @@ -246,6 +263,7 @@ reg = <0x122000 0x1000>; interrupts = <18 0>; clocks = <&clkctl1 MCUX_FLEXCOMM4_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 12)>; status = "disabled"; }; @@ -254,6 +272,7 @@ reg = <0x123000 0x1000>; interrupts = <19 0>; clocks = <&clkctl1 MCUX_FLEXCOMM5_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 13)>; status = "disabled"; }; @@ -262,6 +281,7 @@ reg = <0x124000 0x1000>; interrupts = <43 0>; clocks = <&clkctl1 MCUX_FLEXCOMM6_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 14)>; status = "disabled"; }; @@ -270,6 +290,7 @@ reg = <0x125000 0x1000>; interrupts = <44 0>; clocks = <&clkctl1 MCUX_FLEXCOMM7_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 15)>; status = "disabled"; }; @@ -278,6 +299,7 @@ reg = <0x127000 0x1000>; interrupts = <21 0>; clocks = <&clkctl1 MCUX_PMIC_I2C_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 23)>; status = "disabled"; }; @@ -286,6 +308,7 @@ reg = <0x209000 0x1000>; interrupts = <60 0>; clocks = <&clkctl1 MCUX_FLEXCOMM8_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 16)>; status = "disabled"; }; @@ -294,6 +317,7 @@ reg = <0x20a000 0x1000>; interrupts = <61 0>; clocks = <&clkctl1 MCUX_FLEXCOMM9_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 17)>; status = "disabled"; }; @@ -302,6 +326,7 @@ reg = <0x20b000 0x1000>; interrupts = <62 0>; clocks = <&clkctl1 MCUX_FLEXCOMM10_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 18)>; status = "disabled"; }; @@ -310,6 +335,7 @@ reg = <0x20c000 0x1000>; interrupts = <63 0>; clocks = <&clkctl1 MCUX_FLEXCOMM11_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 19)>; status = "disabled"; }; @@ -318,6 +344,7 @@ reg = <0x20d000 0x1000>; interrupts = <64 0>; clocks = <&clkctl1 MCUX_FLEXCOMM12_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 20)>; status = "disabled"; }; @@ -326,6 +353,7 @@ reg = <0x20e000 0x1000>; interrupts = <65 0>; clocks = <&clkctl1 MCUX_FLEXCOMM13_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 21)>; status = "disabled"; }; @@ -349,6 +377,7 @@ reg = <0x126000 0x1000>; interrupts = <20 0>; clocks = <&clkctl1 MCUX_HS_SPI_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -359,6 +388,7 @@ reg = <0x128000 0x1000>; interrupts = <66 0>; clocks = <&clkctl1 MCUX_HS_SPI1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 24)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -656,6 +686,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_MRT_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(2, 8)>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index 800d61bd13855a..4b7b1524a0b229 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { chosen { @@ -118,6 +119,18 @@ #clock-cells = <1>; }; + rstctl0: reset@0 { + compatible = "nxp,rstctl"; + reg = <0x0 0x80>; + #reset-cells = <1>; + }; + + rstctl1: reset@20000 { + compatible = "nxp,rstctl"; + reg = <0x20000 0x80>; + #reset-cells = <1>; + }; + uuid: uuid@2f50 { compatible = "nxp,lpc-uid"; reg = <0x2f50 0x10>; @@ -190,6 +203,7 @@ reg = <0x106000 0x1000>; interrupts = <14 0>; clocks = <&clkctl1 MCUX_FLEXCOMM0_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>; status = "disabled"; }; @@ -198,6 +212,7 @@ reg = <0x107000 0x1000>; interrupts = <15 0>; clocks = <&clkctl1 MCUX_FLEXCOMM1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>; status = "disabled"; }; @@ -206,6 +221,7 @@ reg = <0x108000 0x1000>; interrupts = <16 0>; clocks = <&clkctl1 MCUX_FLEXCOMM2_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>; status = "disabled"; }; @@ -214,6 +230,7 @@ reg = <0x109000 0x1000>; interrupts = <17 0>; clocks = <&clkctl1 MCUX_FLEXCOMM3_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>; status = "disabled"; }; @@ -222,6 +239,7 @@ reg = <0x122000 0x1000>; interrupts = <18 0>; clocks = <&clkctl1 MCUX_FLEXCOMM4_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 12)>; status = "disabled"; }; @@ -230,6 +248,7 @@ reg = <0x123000 0x1000>; interrupts = <19 0>; clocks = <&clkctl1 MCUX_FLEXCOMM5_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 13)>; status = "disabled"; }; @@ -238,6 +257,7 @@ reg = <0x124000 0x1000>; interrupts = <43 0>; clocks = <&clkctl1 MCUX_FLEXCOMM6_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 14)>; status = "disabled"; }; @@ -246,6 +266,7 @@ reg = <0x125000 0x1000>; interrupts = <44 0>; clocks = <&clkctl1 MCUX_FLEXCOMM7_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 15)>; status = "disabled"; }; @@ -254,6 +275,7 @@ reg = <0x127000 0x1000>; interrupts = <21 0>; clocks = <&clkctl1 MCUX_PMIC_I2C_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 23)>; status = "disabled"; }; @@ -276,6 +298,7 @@ reg = <0x126000 0x1000>; interrupts = <20 0>; clocks = <&clkctl1 MCUX_HS_SPI_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -470,6 +493,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_MRT_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(2, 8)>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index ae4361e0d0dd47..6770d6455967d5 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include / { chosen { @@ -94,6 +95,18 @@ #clock-cells = <1>; }; + rstctl0: reset@0 { + compatible = "nxp,rstctl"; + reg = <0x0 0x80>; + #reset-cells = <1>; + }; + + rstctl1: reset@20000 { + compatible = "nxp,rstctl"; + reg = <0x20000 0x80>; + #reset-cells = <1>; + }; + pmu: pmu@31000 { reg = <0x31000 0x130>; compatible = "nxp,rw-pmu"; @@ -146,6 +159,7 @@ reg = <0x106000 0x1000>; interrupts = <14 0>; clocks = <&clkctl1 MCUX_FLEXCOMM0_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>; dmas = <&dma0 0>, <&dma0 1>; dma-names = "rx", "tx"; status = "disabled"; @@ -156,6 +170,7 @@ reg = <0x107000 0x1000>; interrupts = <15 0>; clocks = <&clkctl1 MCUX_FLEXCOMM1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>; dmas = <&dma0 2>, <&dma0 3>; dma-names = "rx", "tx"; status = "disabled"; @@ -166,6 +181,7 @@ reg = <0x108000 0x1000>; interrupts = <16 0>; clocks = <&clkctl1 MCUX_FLEXCOMM2_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>; dmas = <&dma0 4>, <&dma0 5>; dma-names = "rx", "tx"; status = "disabled"; @@ -176,6 +192,7 @@ reg = <0x109000 0x1000>; interrupts = <17 0>; clocks = <&clkctl1 MCUX_FLEXCOMM3_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>; dmas = <&dma0 6>, <&dma0 7>; dma-names = "rx", "tx"; status = "disabled"; @@ -186,6 +203,7 @@ reg = <0x126000 0x2000>; interrupts = <20 0>; clocks = <&clkctl1 MCUX_FLEXCOMM14_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>; dmas = <&dma0 26>, <&dma0 27>; dma-names = "rx", "tx"; status = "disabled"; @@ -290,6 +308,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_MRT_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(2, 8)>; #address-cells = <1>; #size-cells = <0>; @@ -322,6 +341,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_FREEMRT_CLK>; + resets = <&rstctl0 NXP_SYSCON_RESET(2, 26)>; #address-cells = <1>; #size-cells = <0>; From b1545da09fbc8df5a04985aac30a22d714f52486 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1104/1389] drivers: nxp: Add reset code to driver inits Add peripheral reset handling code to driver init for: - mcan - i2c flexcomm - spi flexcomm - lpc mailbox - mrt timer Signed-off-by: Declan Snyder --- drivers/can/Kconfig.mcux | 1 + drivers/can/can_mcux_mcan.c | 13 +++++++++++++ drivers/counter/Kconfig.nxp_mrt | 1 + drivers/counter/counter_nxp_mrt.c | 15 +++++++++++++++ drivers/i2c/Kconfig.mcux | 1 + drivers/i2c/i2c_mcux_flexcomm.c | 13 +++++++++++++ drivers/ipm/Kconfig.imx | 1 + drivers/ipm/ipm_mcux.c | 30 ++++++++++++++++++++++++++++++ drivers/spi/Kconfig.mcux_flexcomm | 1 + drivers/spi/spi_mcux_flexcomm.c | 15 ++++++++++++++- 10 files changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/can/Kconfig.mcux b/drivers/can/Kconfig.mcux index e995a19ab6f1a3..a0e3e00fddab08 100644 --- a/drivers/can/Kconfig.mcux +++ b/drivers/can/Kconfig.mcux @@ -59,5 +59,6 @@ config CAN_MCUX_MCAN depends on CLOCK_CONTROL select CAN_MCAN select PINCTRL + select RESET help Enable support for mcux mcan driver. diff --git a/drivers/can/can_mcux_mcan.c b/drivers/can/can_mcux_mcan.c index 2ca5d3e02771d6..5a984279ae5540 100644 --- a/drivers/can/can_mcux_mcan.c +++ b/drivers/can/can_mcux_mcan.c @@ -11,6 +11,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(can_mcux_mcan, CONFIG_CAN_LOG_LEVEL); @@ -27,6 +28,7 @@ struct mcux_mcan_config { clock_control_subsys_t clock_subsys; void (*irq_config_func)(const struct device *dev); const struct pinctrl_dev_config *pincfg; + const struct reset_dt_spec reset; }; static int mcux_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val) @@ -91,6 +93,16 @@ static int mcux_mcan_init(const struct device *dev) return -ENODEV; } + if (!device_is_ready(mcux_config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + err = reset_line_toggle(mcux_config->reset.dev, mcux_config->reset.id); + if (err) { + return err; + } + err = pinctrl_apply_state(mcux_config->pincfg, PINCTRL_STATE_DEFAULT); if (err) { return err; @@ -197,6 +209,7 @@ static const struct can_mcan_ops mcux_mcan_ops = { DT_INST_CLOCKS_CELL(n, name), \ .irq_config_func = mcux_mcan_irq_config_##n, \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .reset = RESET_DT_SPEC_INST_GET(n), \ }; \ \ static const struct can_mcan_config can_mcan_config_##n = \ diff --git a/drivers/counter/Kconfig.nxp_mrt b/drivers/counter/Kconfig.nxp_mrt index 6bd8c6dcd024e0..cf3bb84558f190 100644 --- a/drivers/counter/Kconfig.nxp_mrt +++ b/drivers/counter/Kconfig.nxp_mrt @@ -6,5 +6,6 @@ config COUNTER_NXP_MRT default y depends on DT_HAS_NXP_MRT_CHANNEL_ENABLED && \ DT_HAS_NXP_MRT_ENABLED + select RESET help Enable driver for the NXP Multirate Timer (MRT). diff --git a/drivers/counter/counter_nxp_mrt.c b/drivers/counter/counter_nxp_mrt.c index 209d0314b3e144..2ad62385d8e37d 100644 --- a/drivers/counter/counter_nxp_mrt.c +++ b/drivers/counter/counter_nxp_mrt.c @@ -21,6 +21,8 @@ #include #include #include +#include + #include #define LOG_MODULE_NAME counter_mrt @@ -55,6 +57,7 @@ struct nxp_mrt_config { void (*irq_config_func)(const struct device *dev); struct nxp_mrt_channel_data *const *data; const struct device *const *channels; + const struct reset_dt_spec reset; }; static int nxp_mrt_stop(const struct device *dev) @@ -210,6 +213,17 @@ static int nxp_mrt_init(const struct device *dev) const struct nxp_mrt_config *config = dev->config; MRT_Type *base = config->base; uint32_t num_channels = (base->MODCFG & MRT_MODCFG_NOC_MASK) >> MRT_MODCFG_NOC_SHIFT; + int ret = 0; + + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + ret = reset_line_toggle(config->reset.dev, config->reset.id); + if (ret) { + return ret; + } clock_control_on(config->clock_dev, config->clock_subsys); @@ -331,6 +345,7 @@ struct counter_driver_api nxp_mrt_api = { .irq_config_func = nxp_mrt_##n##_irq_config_func, \ .data = nxp_mrt_##n##_channel_datas, \ .channels = nxp_mrt_##n##_channels, \ + .reset = RESET_DT_SPEC_INST_GET(n), \ }; \ \ /* Init parent device in order to handle ISR and init. */ \ diff --git a/drivers/i2c/Kconfig.mcux b/drivers/i2c/Kconfig.mcux index 744f5025eb0663..f91876390147be 100644 --- a/drivers/i2c/Kconfig.mcux +++ b/drivers/i2c/Kconfig.mcux @@ -8,6 +8,7 @@ menuconfig I2C_MCUX_FLEXCOMM default y depends on DT_HAS_NXP_LPC_I2C_ENABLED select PINCTRL + select RESET help Enable the mcux flexcomm i2c driver. diff --git a/drivers/i2c/i2c_mcux_flexcomm.c b/drivers/i2c/i2c_mcux_flexcomm.c index eeb77cb68e115b..f75c65650ec072 100644 --- a/drivers/i2c/i2c_mcux_flexcomm.c +++ b/drivers/i2c/i2c_mcux_flexcomm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ struct mcux_flexcomm_config { void (*irq_config_func)(const struct device *dev); uint32_t bitrate; const struct pinctrl_dev_config *pincfg; + const struct reset_dt_spec reset; }; #ifdef CONFIG_I2C_TARGET @@ -470,6 +472,16 @@ static int mcux_flexcomm_init(const struct device *dev) i2c_master_config_t master_config; int error; + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + error = reset_line_toggle(config->reset.dev, config->reset.id); + if (error) { + return error; + } + error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (error) { return error; @@ -527,6 +539,7 @@ static const struct i2c_driver_api mcux_flexcomm_driver_api = { .irq_config_func = mcux_flexcomm_config_func_##id, \ .bitrate = DT_INST_PROP(id, clock_frequency), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + .reset = RESET_DT_SPEC_INST_GET(id), \ }; \ static struct mcux_flexcomm_data mcux_flexcomm_data_##id; \ I2C_DEVICE_DT_INST_DEFINE(id, \ diff --git a/drivers/ipm/Kconfig.imx b/drivers/ipm/Kconfig.imx index 67fbc370ac8609..743c7d9c6a55d9 100644 --- a/drivers/ipm/Kconfig.imx +++ b/drivers/ipm/Kconfig.imx @@ -5,6 +5,7 @@ config IPM_MCUX bool "MCUX IPM driver" default y depends on DT_HAS_NXP_LPC_MAILBOX_ENABLED + select RESET help Driver for MCUX mailbox diff --git a/drivers/ipm/ipm_mcux.c b/drivers/ipm/ipm_mcux.c index 2365f58aacc29c..e323dc9ec786e7 100644 --- a/drivers/ipm/ipm_mcux.c +++ b/drivers/ipm/ipm_mcux.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #define MCUX_IPM_DATA_REGS 1 #define MCUX_IPM_MAX_ID_VAL 0 @@ -36,9 +38,12 @@ #endif #endif +#define MAILBOX_USES_RESET COND_CODE_1(DT_ANY_INST_HAS_PROP_STATUS_OKAY(resets), (true), (false)) + struct mcux_mailbox_config { MAILBOX_Type *base; void (*irq_config_func)(const struct device *dev); + const struct reset_dt_spec reset; }; struct mcux_mailbox_data { @@ -143,10 +148,34 @@ static int mcux_mailbox_ipm_set_enabled(const struct device *d, int enable) return 0; } +static inline int mcux_mailbox_reset(const struct device *dev) +{ + const struct mcux_mailbox_config *config = dev->config; + int ret = 0; + + /* on some platforms, explicit reset is not needed or possible for the mailbox */ + if (!MAILBOX_USES_RESET) { + return 0; + } + + if (!device_is_ready(config->reset.dev)) { + ret = -ENODEV; + } else { + ret = reset_line_toggle(config->reset.dev, config->reset.id); + } + + return ret; +} static int mcux_mailbox_init(const struct device *dev) { const struct mcux_mailbox_config *config = dev->config; + int ret = 0; + + ret = mcux_mailbox_reset(dev); + if (ret) { + return ret; + } MAILBOX_Init(config->base); config->irq_config_func(dev); @@ -169,6 +198,7 @@ static void mcux_mailbox_config_func_0(const struct device *dev); static const struct mcux_mailbox_config mcux_mailbox_0_config = { .base = (MAILBOX_Type *)DT_INST_REG_ADDR(0), .irq_config_func = mcux_mailbox_config_func_0, + .reset = RESET_DT_SPEC_INST_GET_OR(0, {0}), }; static struct mcux_mailbox_data mcux_mailbox_0_data; diff --git a/drivers/spi/Kconfig.mcux_flexcomm b/drivers/spi/Kconfig.mcux_flexcomm index ff07a5ec03887a..68ef16aa3e814c 100644 --- a/drivers/spi/Kconfig.mcux_flexcomm +++ b/drivers/spi/Kconfig.mcux_flexcomm @@ -7,6 +7,7 @@ config SPI_MCUX_FLEXCOMM default y depends on DT_HAS_NXP_LPC_SPI_ENABLED select PINCTRL + select RESET help Enable support for mcux flexcomm spi driver. diff --git a/drivers/spi/spi_mcux_flexcomm.c b/drivers/spi/spi_mcux_flexcomm.c index cb20fcea6e3be9..411244c21a9aac 100644 --- a/drivers/spi/spi_mcux_flexcomm.c +++ b/drivers/spi/spi_mcux_flexcomm.c @@ -18,6 +18,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(spi_mcux_flexcomm, CONFIG_SPI_LOG_LEVEL); @@ -37,6 +38,7 @@ struct spi_mcux_config { uint32_t transfer_delay; uint32_t def_char; const struct pinctrl_dev_config *pincfg; + const struct reset_dt_spec reset; }; #ifdef CONFIG_SPI_MCUX_FLEXCOMM_DMA @@ -764,9 +766,19 @@ static int spi_mcux_release(const struct device *dev, static int spi_mcux_init(const struct device *dev) { - int err; const struct spi_mcux_config *config = dev->config; struct spi_mcux_data *data = dev->data; + int err = 0; + + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + err = reset_line_toggle(config->reset.dev, config->reset.id); + if (err) { + return err; + } config->irq_config_func(dev); @@ -866,6 +878,7 @@ static void spi_mcux_config_func_##id(const struct device *dev) \ .transfer_delay = DT_INST_PROP_OR(id, transfer_delay, 0), \ .def_char = DT_INST_PROP_OR(id, def_char, 0), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + .reset = RESET_DT_SPEC_INST_GET(id), \ }; \ static struct spi_mcux_data spi_mcux_data_##id = { \ SPI_CONTEXT_INIT_LOCK(spi_mcux_data_##id, ctx), \ From f128df0fca0d7d9dfa67067fba8538778da6ee17 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1105/1389] soc: lpc: Remove peripheral reset code from soc.c Remove peripheral reset code from soc.c, it should be handled by driver inits. Signed-off-by: Declan Snyder --- soc/nxp/imxrt/imxrt5xx/cm33/soc.c | 4 ---- soc/nxp/imxrt/imxrt6xx/cm33/soc.c | 4 ---- soc/nxp/lpc/lpc51u68/soc.c | 6 ------ soc/nxp/lpc/lpc54xxx/soc.c | 6 ------ soc/nxp/lpc/lpc55xxx/soc.c | 13 ------------- soc/nxp/rw/soc.c | 5 ----- 6 files changed, 38 deletions(-) diff --git a/soc/nxp/imxrt/imxrt5xx/cm33/soc.c b/soc/nxp/imxrt/imxrt5xx/cm33/soc.c index 4b420ea46d483e..9f29550b576ff9 100644 --- a/soc/nxp/imxrt/imxrt5xx/cm33/soc.c +++ b/soc/nxp/imxrt/imxrt5xx/cm33/soc.c @@ -423,10 +423,6 @@ void __weak rt5xx_clock_init(void) CLOCK_SetClkDiv(kCLOCK_DivAdcClk, 1); #endif -#if CONFIG_COUNTER_NXP_MRT - RESET_PeripheralReset(kMRT0_RST_SHIFT_RSTn); -#endif - #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(dmic0), nxp_dmic, okay) /* Using the Audio PLL as input clock leads to better clock dividers * for typical PCM sample rates ({8,16,24,32,48,96} kHz. diff --git a/soc/nxp/imxrt/imxrt6xx/cm33/soc.c b/soc/nxp/imxrt/imxrt6xx/cm33/soc.c index de658a285be9f6..bb6ea26ac45b72 100644 --- a/soc/nxp/imxrt/imxrt6xx/cm33/soc.c +++ b/soc/nxp/imxrt/imxrt6xx/cm33/soc.c @@ -321,10 +321,6 @@ static ALWAYS_INLINE void clock_init(void) flexspi_setup_clock(FLEXSPI, 1U, 9U); #endif -#if CONFIG_COUNTER_NXP_MRT - RESET_PeripheralReset(kMRT0_RST_SHIFT_RSTn); -#endif - /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; diff --git a/soc/nxp/lpc/lpc51u68/soc.c b/soc/nxp/lpc/lpc51u68/soc.c index e09800ce872f44..c4b7b58131abd1 100644 --- a/soc/nxp/lpc/lpc51u68/soc.c +++ b/soc/nxp/lpc/lpc51u68/soc.c @@ -31,17 +31,11 @@ int soc_init(void) #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm4), nxp_lpc_i2c, okay) /* attach 12 MHz clock for flexcomm4 */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); - - /* reset FLEXCOMM for I2C */ - RESET_PeripheralReset(kFC4_RST_SHIFT_RSTn); #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm5), nxp_lpc_spi, okay) /* attach 12MHz clock to flexcomm5 */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM5); - - /* reset FLEXCOMM for SPI */ - RESET_PeripheralReset(kFC5_RST_SHIFT_RSTn); #endif POWER_DisablePD(kPDRUNCFG_PD_ADC0); diff --git a/soc/nxp/lpc/lpc54xxx/soc.c b/soc/nxp/lpc/lpc54xxx/soc.c index 20f2022cd56b56..f5a353d2ad3437 100644 --- a/soc/nxp/lpc/lpc54xxx/soc.c +++ b/soc/nxp/lpc/lpc54xxx/soc.c @@ -81,17 +81,11 @@ static ALWAYS_INLINE void clock_init(void) #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm4), nxp_lpc_i2c, okay) /* attach 12 MHz clock to FLEXCOMM4 */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); - - /* reset FLEXCOMM for I2C */ - RESET_PeripheralReset(kFC4_RST_SHIFT_RSTn); #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm5), nxp_lpc_spi, okay) /* Attach 12 MHz clock to FLEXCOMM5 */ CLOCK_AttachClk(kFRO_HF_to_FLEXCOMM5); - - /* reset FLEXCOMM for SPI */ - RESET_PeripheralReset(kFC5_RST_SHIFT_RSTn); #endif #endif /* CONFIG_SOC_LPC54114_M4 */ diff --git a/soc/nxp/lpc/lpc55xxx/soc.c b/soc/nxp/lpc/lpc55xxx/soc.c index a26aae34d9b763..5072fd8266b54f 100644 --- a/soc/nxp/lpc/lpc55xxx/soc.c +++ b/soc/nxp/lpc/lpc55xxx/soc.c @@ -191,17 +191,11 @@ static ALWAYS_INLINE void clock_init(void) #endif /* attach 12 MHz clock to FLEXCOMM4 */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); - - /* reset FLEXCOMM for I2C */ - RESET_PeripheralReset(kFC4_RST_SHIFT_RSTn); #endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(hs_lspi), okay) /* Attach 12 MHz clock to HSLSPI */ CLOCK_AttachClk(kFRO_HF_DIV_to_HSLSPI); - - /* reset HSLSPI for SPI */ - RESET_PeripheralReset(kHSLSPI_RST_SHIFT_RSTn); #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt0), nxp_lpc_wwdt, okay) @@ -211,8 +205,6 @@ static ALWAYS_INLINE void clock_init(void) #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(mailbox0), nxp_lpc_mailbox, okay) CLOCK_EnableClock(kCLOCK_Mailbox); - /* Reset the MAILBOX module */ - RESET_PeripheralReset(kMAILBOX_RST_SHIFT_RSTn); #endif #if CONFIG_USB_DC_NXP_LPCIP3511 @@ -296,7 +288,6 @@ DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP) #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(can0), nxp_lpc_mcan, okay) CLOCK_SetClkDiv(kCLOCK_DivCanClk, 1U, false); CLOCK_AttachClk(kMCAN_DIV_to_MCAN); - RESET_PeripheralReset(kMCAN_RST_SHIFT_RSTn); #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(sdif), nxp_lpc_sdif, okay) && \ @@ -347,10 +338,6 @@ DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP) #endif /* SOC platform */ #endif /* DAC */ -#ifdef CONFIG_COUNTER_NXP_MRT - RESET_PeripheralReset(kMRT_RST_SHIFT_RSTn); -#endif - } /** diff --git a/soc/nxp/rw/soc.c b/soc/nxp/rw/soc.c index f319328bd37e8a..a18aff5cf8a0cd 100644 --- a/soc/nxp/rw/soc.c +++ b/soc/nxp/rw/soc.c @@ -250,11 +250,6 @@ __ramfunc void clock_init(void) #endif #endif /* CONFIG_COUNTER_MCUX_CTIMER */ -#ifdef CONFIG_COUNTER_NXP_MRT - RESET_PeripheralReset(kMRT_RST_SHIFT_RSTn); - RESET_PeripheralReset(kFREEMRT_RST_SHIFT_RSTn); -#endif - #if DT_NODE_HAS_STATUS(DT_NODELABEL(usb_otg), okay) && CONFIG_USB_DC_NXP_EHCI /* Enable system xtal from Analog */ SYSCTL2->ANA_GRP_CTRL |= SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK; From e22288e4745b54f08bfe1c21a9f6122cb4c11b91 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1106/1389] dts: nxp: Add comment reminders to some DT The RTXXX and RW61X DT are using syscon compatible depsite not having a syscon. This is a technical debt to remain aware of. The reason they use these compatibles is to use the syscon driver which is a shim to an SDK API that is somewhat similar to syscon. Signed-off-by: Declan Snyder --- dts/arm/nxp/nxp_rt5xx_common.dtsi | 2 ++ dts/arm/nxp/nxp_rt6xx_common.dtsi | 2 ++ dts/arm/nxp/nxp_rw6xx_common.dtsi | 2 ++ 3 files changed, 6 insertions(+) diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index fc24a062e8a2af..95af8ca31770ac 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -116,6 +116,7 @@ */ clkctl0: clkctl@1000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x1000 0x1000>; #clock-cells = <1>; @@ -130,6 +131,7 @@ }; clkctl1: clkctl@21000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x21000 0x1000>; #clock-cells = <1>; diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index 4b7b1524a0b229..47d4258ee8e24d 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -100,6 +100,7 @@ */ clkctl0: clkctl@1000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x1000 0x1000>; #clock-cells = <1>; @@ -114,6 +115,7 @@ }; clkctl1: clkctl@21000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x21000 0x1000>; #clock-cells = <1>; diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index 6770d6455967d5..b02f5fe281405f 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -78,6 +78,7 @@ #size-cells = <1>; clkctl0: clkctl@1000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x1000 0x1000>; #clock-cells = <1>; @@ -90,6 +91,7 @@ }; clkctl1: clkctl@21000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x21000 0x1000>; #clock-cells = <1>; From 200700ac4d5ba01c5451bdecabd554fa15d8f6dd Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1107/1389] drivers: mipi_dbi: mipi_dbi_spi: require 3 wire mode use 9 bit SPI Require that SPI config within the MIPI DBI API use 9 bit SPI mode, as 3 wire spi requires the command/data bit be packed into the start of the SPI packet. Signed-off-by: Daniel DeGrasse --- drivers/mipi_dbi/mipi_dbi_spi.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/mipi_dbi/mipi_dbi_spi.c b/drivers/mipi_dbi/mipi_dbi_spi.c index 0314fe5c31f13e..e2b3aefe53bf6b 100644 --- a/drivers/mipi_dbi/mipi_dbi_spi.c +++ b/drivers/mipi_dbi/mipi_dbi_spi.c @@ -66,21 +66,21 @@ static int mipi_dbi_spi_write_helper(const struct device *dev, if (dbi_config->mode == MIPI_DBI_MODE_SPI_3WIRE && IS_ENABLED(CONFIG_MIPI_DBI_SPI_3WIRE)) { - struct spi_config tmp_cfg; - /* We have to emulate 3 wire mode by packing the data/command - * bit into the upper bit of the SPI transfer. - * switch SPI to 9 bit mode, and write the transfer + /* 9 bit word mode must be used, as the command/data bit + * is stored before the data word. */ - memcpy(&tmp_cfg, &dbi_config->config, sizeof(tmp_cfg)); - tmp_cfg.operation &= ~SPI_WORD_SIZE_MASK; - tmp_cfg.operation |= SPI_WORD_SET(9); + if ((dbi_config->config.operation & SPI_WORD_SIZE_MASK) + != SPI_WORD_SET(9)) { + return -ENOTSUP; + } buffer.buf = &data->spi_byte; - buffer.len = 1; + buffer.len = 2; /* Send command */ if (cmd_present) { data->spi_byte = cmd; - ret = spi_write(config->spi_dev, &tmp_cfg, &buf_set); + ret = spi_write(config->spi_dev, &dbi_config->config, + &buf_set); if (ret < 0) { goto out; } @@ -88,7 +88,8 @@ static int mipi_dbi_spi_write_helper(const struct device *dev, /* Write data, byte by byte */ for (size_t i = 0; i < len; i++) { data->spi_byte = MIPI_DBI_DC_BIT | data_buf[i]; - ret = spi_write(config->spi_dev, &tmp_cfg, &buf_set); + ret = spi_write(config->spi_dev, &dbi_config->config, + &buf_set); if (ret < 0) { goto out; } From 452f45acd448f7ce9d726291346017a1f91004a1 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1108/1389] drivers: display: st7735r: convert to MIPI DBI API Convert the ST7735R display to use the MIPI DBI API. Boards and overlays using this display are also updated. Signed-off-by: Daniel DeGrasse --- .../st7735r/st7735r_ada_160x128.overlay | 60 +++++---- .../longan_nano/longan_nano-common.dtsi | 80 +++++++----- drivers/display/Kconfig.st7735r | 2 +- drivers/display/display_st7735r.c | 121 ++++++------------ dts/bindings/display/sitronix,st7735r.yaml | 19 +-- 5 files changed, 124 insertions(+), 158 deletions(-) diff --git a/boards/shields/st7735r/st7735r_ada_160x128.overlay b/boards/shields/st7735r/st7735r_ada_160x128.overlay index 42d7cd890603d2..d769b9a1a4dd55 100644 --- a/boards/shields/st7735r/st7735r_ada_160x128.overlay +++ b/boards/shields/st7735r/st7735r_ada_160x128.overlay @@ -4,38 +4,48 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,display = &st7735r_st7735r_ada_160x128; }; + + mipi_dbi_st7735r_ada_160x128 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + #address-cells = <1>; + #size-cells = <0>; + + st7735r_st7735r_ada_160x128: st7735r@0 { + compatible = "sitronix,st7735r"; + mipi-max-frequency = <20000000>; + mipi-mode = ; + reg = <0>; + width = <160>; + height = <128>; + x-offset = <0>; + y-offset = <0>; + madctl = <0x60>; + colmod = <0x55>; + vmctr1 = <0x0e>; + pwctr1 = [a2 02 84]; + pwctr2 = [c5]; + pwctr3 = [0a 00]; + pwctr4 = [8a 2a]; + pwctr5 = [8a ee]; + frmctr1 = [01 2c 2d]; + frmctr2 = [01 2c 2d]; + frmctr3 = [01 2c 2d 01 2c 2d]; + gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10]; + gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10]; + }; + }; }; &arduino_spi { status = "okay"; cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ - - st7735r_st7735r_ada_160x128: st7735r@0 { - compatible = "sitronix,st7735r"; - spi-max-frequency = <20000000>; - reg = <0>; - cmd-data-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ - reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - width = <160>; - height = <128>; - x-offset = <0>; - y-offset = <0>; - madctl = <0x60>; - colmod = <0x55>; - vmctr1 = <0x0e>; - pwctr1 = [a2 02 84]; - pwctr2 = [c5]; - pwctr3 = [0a 00]; - pwctr4 = [8a 2a]; - pwctr5 = [8a ee]; - frmctr1 = [01 2c 2d]; - frmctr2 = [01 2c 2d]; - frmctr3 = [01 2c 2d 01 2c 2d]; - gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10]; - gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10]; - }; }; diff --git a/boards/sipeed/longan_nano/longan_nano-common.dtsi b/boards/sipeed/longan_nano/longan_nano-common.dtsi index 6d272ddd53d4fd..c5e9202e94f252 100644 --- a/boards/sipeed/longan_nano/longan_nano-common.dtsi +++ b/boards/sipeed/longan_nano/longan_nano-common.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { chosen { @@ -65,6 +66,50 @@ sw0 = &button_boot0; watchdog0 = &fwdgt; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpiob 0 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + /* longan nano has LCD with st7735s controller. + * It can use with st7735r driver. + */ + lcd0: lcd@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + status = "okay"; + width = <160>; + height = <80>; + inversion-on; + rgb-is-inverted; + x-offset = <1>; + y-offset = <26>; + pwctr1 = [62 02 04]; + pwctr2 = [C0]; + pwctr3 = [0D 00]; + pwctr4 = [8D 6A]; + pwctr5 = [8D EE]; + invctr = <3>; + frmctr1 = [05 3A 3A]; + frmctr2 = [05 3A 3A]; + frmctr3 = [05 3A 3A 05 3A 3A]; + vmctr1 = <14>; + gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; + gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; + colmod = <5>; + madctl = <120>; + caset = [00 01 00 a0]; + raset = [00 1a 00 69]; + + mipi-mode = ; + mipi-max-frequency = <4000000>; + }; + }; }; &gpioa { @@ -109,41 +154,6 @@ pinctrl-names = "default"; cs-gpios = <&gpiob 2 GPIO_ACTIVE_LOW>; - - /* longan nano has LCD with st7735s controller. - * It can use with st7735r driver. - */ - lcd0: lcd@0 { - compatible = "sitronix,st7735r"; - reg = <0>; - status = "okay"; - reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>; - cmd-data-gpios = <&gpiob 0 GPIO_ACTIVE_LOW>; - width = <160>; - height = <80>; - inversion-on; - rgb-is-inverted; - x-offset = <1>; - y-offset = <26>; - pwctr1 = [62 02 04]; - pwctr2 = [C0]; - pwctr3 = [0D 00]; - pwctr4 = [8D 6A]; - pwctr5 = [8D EE]; - invctr = <3>; - frmctr1 = [05 3A 3A]; - frmctr2 = [05 3A 3A]; - frmctr3 = [05 3A 3A 05 3A 3A]; - vmctr1 = <14>; - gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; - gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; - colmod = <5>; - madctl = <120>; - caset = [00 01 00 a0]; - raset = [00 1a 00 69]; - - spi-max-frequency = <4000000>; - }; }; &spi1 { diff --git a/drivers/display/Kconfig.st7735r b/drivers/display/Kconfig.st7735r index 94153eca5859b5..387665ace45bb2 100644 --- a/drivers/display/Kconfig.st7735r +++ b/drivers/display/Kconfig.st7735r @@ -7,6 +7,6 @@ config ST7735R bool "ST7735R/ST7735S display driver" default y depends on DT_HAS_SITRONIX_ST7735R_ENABLED - select SPI + select MIPI_DBI help Enable driver for ST7735R/ST7735S display driver. diff --git a/drivers/display/display_st7735r.c b/drivers/display/display_st7735r.c index 88c282d89f88e9..1626cb5204b23e 100644 --- a/drivers/display/display_st7735r.c +++ b/drivers/display/display_st7735r.c @@ -5,6 +5,7 @@ * Copyright (c) 2019 PHYTEC Messtechnik GmbH * Copyright (c) 2020 Endian Technologies AB * Copyright (c) 2020 Kim Bøndergaard + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +15,7 @@ #include "display_st7735r.h" #include -#include +#include #include #include #include @@ -23,15 +24,14 @@ #include LOG_MODULE_REGISTER(display_st7735r, CONFIG_DISPLAY_LOG_LEVEL); -#define ST7735R_RESET_TIME K_MSEC(1) +#define ST7735R_RESET_TIME 1 #define ST7735R_EXIT_SLEEP_TIME K_MSEC(120) #define ST7735R_PIXEL_SIZE 2u struct st7735r_config { - struct spi_dt_spec bus; - struct gpio_dt_spec cmd_data; - struct gpio_dt_spec reset; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; uint16_t height; uint16_t width; uint8_t madctl; @@ -68,38 +68,13 @@ static void st7735r_set_lcd_margins(const struct device *dev, data->y_offset = y_offset; } -static void st7735r_set_cmd(const struct device *dev, int is_cmd) -{ - const struct st7735r_config *config = dev->config; - - gpio_pin_set_dt(&config->cmd_data, is_cmd); -} - static int st7735r_transmit_hold(const struct device *dev, uint8_t cmd, const uint8_t *tx_data, size_t tx_count) { const struct st7735r_config *config = dev->config; - struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; - struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; - int ret; - - st7735r_set_cmd(dev, 1); - ret = spi_write_dt(&config->bus, &tx_bufs); - if (ret < 0) { - return ret; - } - if (tx_data != NULL) { - tx_buf.buf = (void *)tx_data; - tx_buf.len = tx_count; - st7735r_set_cmd(dev, 0); - ret = spi_write_dt(&config->bus, &tx_bufs); - if (ret < 0) { - return ret; - } - } - - return 0; + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, tx_data, tx_count); } static int st7735r_transmit(const struct device *dev, uint8_t cmd, @@ -109,7 +84,7 @@ static int st7735r_transmit(const struct device *dev, uint8_t cmd, int ret; ret = st7735r_transmit_hold(dev, cmd, tx_data, tx_count); - spi_release_dt(&config->bus); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return ret; } @@ -133,11 +108,8 @@ static int st7735r_reset_display(const struct device *dev) int ret; LOG_DBG("Resetting display"); - if (config->reset.port != NULL) { - gpio_pin_set_dt(&config->reset, 1); - k_sleep(ST7735R_RESET_TIME); - gpio_pin_set_dt(&config->reset, 0); - } else { + ret = mipi_dbi_reset(config->mipi_dev, ST7735R_RESET_TIME); + if (ret != 0) { ret = st7735r_transmit(dev, ST7735R_CMD_SW_RESET, NULL, 0); if (ret < 0) { return ret; @@ -204,12 +176,12 @@ static int st7735r_write(const struct device *dev, { const struct st7735r_config *config = dev->config; const uint8_t *write_data_start = (uint8_t *) buf; - struct spi_buf tx_buf; - struct spi_buf_set tx_bufs; uint16_t write_cnt; uint16_t nbr_of_writes; uint16_t write_h; int ret; + enum display_pixel_format fmt; + struct display_buffer_descriptor mipi_desc; __ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width"); __ASSERT((desc->pitch * ST7735R_PIXEL_SIZE * desc->height) @@ -225,9 +197,24 @@ static int st7735r_write(const struct device *dev, if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * ST7735R_PIXEL_SIZE; } else { write_h = desc->height; nbr_of_writes = 1U; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * ST7735R_PIXEL_SIZE * write_h; + } + + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + + if (!(config->madctl & ST7735R_MADCTL_BGR) != !config->rgb_is_inverted) { + fmt = PIXEL_FORMAT_BGR_565; + } else { + fmt = PIXEL_FORMAT_RGB_565; } ret = st7735r_transmit_hold(dev, ST7735R_CMD_RAMWR, @@ -237,14 +224,13 @@ static int st7735r_write(const struct device *dev, goto out; } - tx_bufs.buffers = &tx_buf; - tx_bufs.count = 1; - write_data_start += (desc->pitch * ST7735R_PIXEL_SIZE); for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) { - tx_buf.buf = (void *)write_data_start; - tx_buf.len = desc->width * ST7735R_PIXEL_SIZE * write_h; - ret = spi_write_dt(&config->bus, &tx_bufs); + ret = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + write_data_start, + &mipi_desc, + fmt); if (ret < 0) { goto out; } @@ -254,7 +240,7 @@ static int st7735r_write(const struct device *dev, ret = 0; out: - spi_release_dt(&config->bus); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return ret; } @@ -445,36 +431,11 @@ static int st7735r_init(const struct device *dev) const struct st7735r_config *config = dev->config; int ret; - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); - return -ENODEV; - } - - if (config->reset.port != NULL) { - if (!gpio_is_ready_dt(&config->reset)) { - LOG_ERR("Reset GPIO port for display not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->reset, - GPIO_OUTPUT_INACTIVE); - if (ret) { - LOG_ERR("Couldn't configure reset pin"); - return ret; - } - } - - if (!gpio_is_ready_dt(&config->cmd_data)) { - LOG_ERR("cmd/DATA GPIO port not ready"); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI bus %s not ready", config->mipi_dev->name); return -ENODEV; } - ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT); - if (ret) { - LOG_ERR("Couldn't configure cmd/DATA pin"); - return ret; - } - ret = st7735r_reset_display(dev); if (ret < 0) { LOG_ERR("Couldn't reset display"); @@ -530,11 +491,13 @@ static const struct display_driver_api st7735r_api = { #define ST7735R_INIT(inst) \ const static struct st7735r_config st7735r_config_ ## inst = { \ - .bus = SPI_DT_SPEC_INST_GET( \ - inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ - .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), \ + .mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = MIPI_DBI_CONFIG_DT_INST(inst, \ + SPI_OP_MODE_MASTER | \ + ((DT_INST_PROP(inst, mipi_mode) == \ + MIPI_DBI_MODE_SPI_4WIRE) ? SPI_WORD_SET(8) : \ + SPI_WORD_SET(9)) | \ + SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ .width = DT_INST_PROP(inst, width), \ .height = DT_INST_PROP(inst, height), \ .madctl = DT_INST_PROP(inst, madctl), \ diff --git a/dts/bindings/display/sitronix,st7735r.yaml b/dts/bindings/display/sitronix,st7735r.yaml index 90ead2b8731d80..bc94281e829235 100644 --- a/dts/bindings/display/sitronix,st7735r.yaml +++ b/dts/bindings/display/sitronix,st7735r.yaml @@ -5,26 +5,9 @@ description: ST7735R/ST7735S 160x128 (max) display controller compatible: "sitronix,st7735r" -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: RESET pin. - - The RESET pin of ST7735R is active low. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - required: true - description: D/CX pin. - - The D/CX pin of ST7735R is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - x-offset: type: int required: true From 84aa3991f5e67f6516bdb46cb517a061a6b56570 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1109/1389] tests: drivers: build_all: add st7735r to test Add entry for st7735r to display build all test Signed-off-by: Daniel DeGrasse --- tests/drivers/build_all/display/app.overlay | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index 3f71e34d33b7a8..86554578ff937c 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -11,6 +11,7 @@ */ #include +#include / { test { @@ -55,6 +56,20 @@ pgc = [F0 06 0B 07 06 05 2E 33 47 3A 17 16 2E 31]; ngc = [F0 09 0D 09 08 23 2E 33 46 38 13 13 2C 32]; }; + + test_mipi_dbi_st7735r: st7735t@2 { + compatible = "sitronix,st7735r"; + mipi-max-frequency = <250000000>; + mipi-mode = ; + reg = <2>; + /* Arbitrary values */ + x-offset = <0>; + y-offset = <0>; + gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; + gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; + width = <160>; + height = <128>; + }; }; @@ -67,7 +82,7 @@ clock-frequency = <2000000>; /* one entry for every devices at spi.dtsi */ - cs-gpios = <&test_gpio 0 0 &test_gpio 0 1>; + cs-gpios = <&test_gpio 0 0 &test_gpio 0 1 &test_gpio 0 2>; test_spi_gc9x01x: gc9x01x@1 { compatible = "galaxycore,gc9x01x"; From 0f9f68086e48c9c9429eaed5afd945f6ba1a3a60 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Sun, 26 May 2024 22:39:26 +0200 Subject: [PATCH 1110/1389] docs: releases: migration-guide-3.7: add note about ST7735R migration Add note about migration of ST7735R displays to MIPI DBI API. Signed-off-by: Daniel DeGrasse --- doc/releases/migration-guide-3.7.rst | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index a89e3150d1b9c3..4c1fccd2e3a328 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -213,6 +213,49 @@ Controller Area Network (CAN) Display ======= +* ST7735R based displays now use the MIPI DBI driver class. These displays + must now be declared within a MIPI DBI driver wrapper device, which will + manage interfacing with the display. Note that the `cmd-data-gpios` pin has + changed polarity with this update, to align better with the new + `dc-gpios` name. For an example, see below: + + .. code-block:: devicetree + + /* Legacy ST7735R display definition */ + &spi0 { + st7735r: st7735r@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + spi-max-frequency = <32000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + cmd-data-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + + st7735r: st7735r@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + mipi-max-frequency = <32000000>; + mipi-mode = ; + ... + }; + }; + Enhanced Serial Peripheral Interface (eSPI) =========================================== From 1f5813b217d3996702043f73597202e1ffda65c2 Mon Sep 17 00:00:00 2001 From: Javad Rahimipetroudi Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1111/1389] driver: led: add support for TI TLC59731 RGB STRIP controller TLC59731 is a 3-Channel, 8-Bit, PWM LED Driver with TI Single-Wire interface (EasySet) protocol. Signed-off-by: Javad Rahimipetroudi --- drivers/led_strip/CMakeLists.txt | 1 + drivers/led_strip/Kconfig | 2 + drivers/led_strip/Kconfig.tlc59731 | 11 ++ drivers/led_strip/tlc59731.c | 189 ++++++++++++++++++++++++ dts/bindings/led_strip/ti,tlc59731.yaml | 13 ++ 5 files changed, 216 insertions(+) create mode 100644 drivers/led_strip/Kconfig.tlc59731 create mode 100644 drivers/led_strip/tlc59731.c create mode 100644 dts/bindings/led_strip/ti,tlc59731.yaml diff --git a/drivers/led_strip/CMakeLists.txt b/drivers/led_strip/CMakeLists.txt index aa4e95722a7163..b293782e620fb5 100644 --- a/drivers/led_strip/CMakeLists.txt +++ b/drivers/led_strip/CMakeLists.txt @@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_SPI ws2812_spi.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_I2S ws2812_i2s.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_RPI_PICO_PIO ws2812_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_TLC5971_STRIP tlc5971.c) +zephyr_library_sources_ifdef(CONFIG_TLC59731_STRIP tlc59731.c) diff --git a/drivers/led_strip/Kconfig b/drivers/led_strip/Kconfig index 269657dd0b8a0b..3be80de47298c5 100644 --- a/drivers/led_strip/Kconfig +++ b/drivers/led_strip/Kconfig @@ -35,4 +35,6 @@ source "drivers/led_strip/Kconfig.apa102" source "drivers/led_strip/Kconfig.tlc5971" +source "drivers/led_strip/Kconfig.tlc59731" + endif # LED_STRIP diff --git a/drivers/led_strip/Kconfig.tlc59731 b/drivers/led_strip/Kconfig.tlc59731 new file mode 100644 index 00000000000000..3857c08dc5f0d9 --- /dev/null +++ b/drivers/led_strip/Kconfig.tlc59731 @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Javad Rahimipetroudi +# SPDX-License-Identifier: Apache-2.0 + +config TLC59731_STRIP + bool "TLC59731 LED controller" + default y + depends on DT_HAS_TI_TLC59731_ENABLED + select GPIO + help + Enable driver for the Texas Instruments TLC59731 EasySet LED + controllers. diff --git a/drivers/led_strip/tlc59731.c b/drivers/led_strip/tlc59731.c new file mode 100644 index 00000000000000..c8501156e81436 --- /dev/null +++ b/drivers/led_strip/tlc59731.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2024 Javad Rahimipetroudi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_tlc59731 + +/** + * @file + * @brief LED driver for the TLC59731 LED driver. + * + * TLC59731 is a 3-Channel, 8-Bit, PWM LED Driver + * With Single-Wire Interface (EasySet) + * + * The EasySet protocol is based on short pulses and the time between + * them. At least one pulse must be sent every T_CYCLE, which can be + * between 1.67us and 50us. We want to go as fast as possible, but + * delays under 1us don't work very well, so we settle on 5us for the + * cycle time. + * A pulse must be high for at least 14ns. In practice, turning a GPIO on + * and immediately off again already takes longer than that, so no delay + * is needed there. + * A zero is represented by no additional pulses within a cycle. + * A one is represented by an additional pulse between 275ns and 2.5us + * (half a cycle) after the first one. We need at least some delay to get to + * 275ns, but because of the limited granularity of k_busy_wait we use a + * full 1us. After the pulse, we wait an additional T_CYCLE_1 to complete + * the cycle. This time can be slightly shorter because the second pulse + * already closes the cycle. + * Finally we need to keep the line low for T_H0 to complete the address + * for a single chip, and T_H1 to complete the write for all chips. + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(tlc59731, CONFIG_LED_STRIP_LOG_LEVEL); + +/* Pulse timing */ +#define TLC59731_DELAY 0x01 /* us */ +#define TLC59731_T_CYCLE_0 0x04 /* us */ +#define TLC59731_T_CYCLE_1 0x01 /* us */ +#define TLC59731_T_H0 (4 * TLC59731_T_CYCLE_0) +#define TLC59731_T_H1 (8 * TLC59731_T_CYCLE_0) +/* Threshould levels */ +#define TLC59731_HIGH 0x01 +#define TLC59731_LOW 0x00 + +/* Write command */ +#define TLC59731_WR 0x3A + +struct tlc59731_cfg { + struct gpio_dt_spec sdi_gpio; + size_t length; +}; + +static inline int rgb_pulse(const struct gpio_dt_spec *led_dev) +{ + int fret = 0; + + fret = gpio_pin_set_dt(led_dev, TLC59731_HIGH); + if (fret != 0) { + return fret; + } + + fret = gpio_pin_set_dt(led_dev, TLC59731_LOW); + if (fret != 0) { + return fret; + } + + return fret; +} + +static int rgb_write_bit(const struct gpio_dt_spec *led_dev, uint8_t data) +{ + rgb_pulse(led_dev); + + k_busy_wait(TLC59731_DELAY); + + if (data) { + rgb_pulse(led_dev); + k_busy_wait(TLC59731_T_CYCLE_1); + } else { + k_busy_wait(TLC59731_T_CYCLE_0); + } + + return 0; +} + +static int rgb_write_data(const struct gpio_dt_spec *led_dev, uint8_t data) +{ + int8_t idx = 7; + + while (idx >= 0) { + rgb_write_bit(led_dev, data & BIT((idx--))); + } + + return 0; +} + +static int tlc59731_led_set_color(const struct device *dev, struct led_rgb *pixel) +{ + + const struct tlc59731_cfg *tlc_conf = dev->config; + const struct gpio_dt_spec *led_gpio = &tlc_conf->sdi_gpio; + + rgb_write_data(led_gpio, TLC59731_WR); + rgb_write_data(led_gpio, pixel->r); + rgb_write_data(led_gpio, pixel->g); + rgb_write_data(led_gpio, pixel->b); + + return 0; +} + +static int tlc59731_gpio_update_rgb(const struct device *dev, struct led_rgb *pixels, + size_t num_pixels) +{ + size_t i; + int err = 0; + + for (i = 0; i < num_pixels; i++) { + err = tlc59731_led_set_color(dev, &pixels[i]); + if (err) { + break; + } + } + + return err; +} + +static size_t tlc59731_length(const struct device *dev) +{ + const struct tlc59731_cfg *config = dev->config; + + return config->length; +} + +static const struct led_strip_driver_api tlc59731_gpio_api = { + .update_rgb = tlc59731_gpio_update_rgb, + .length = tlc59731_length, +}; + +static int tlc59731_gpio_init(const struct device *dev) +{ + const struct tlc59731_cfg *tlc_conf = dev->config; + const struct gpio_dt_spec *led = &tlc_conf->sdi_gpio; + int err = 0; + + if (!device_is_ready(led->port)) { + LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name); + err = -ENODEV; + goto scape; + } + + err = gpio_pin_configure_dt(led, GPIO_OUTPUT_ACTIVE); + if (err < 0) { + LOG_ERR("%s: Unable to setup SDI port", dev->name); + err = -EIO; + goto scape; + } + + err = gpio_pin_set_dt(led, TLC59731_LOW); + if (err < 0) { + LOG_ERR("%s: Unable to set the SDI-GPIO)", dev->name); + err = -EIO; + goto scape; + } + + gpio_pin_set_dt(led, TLC59731_HIGH); + gpio_pin_set_dt(led, TLC59731_LOW); + + k_busy_wait((TLC59731_DELAY + TLC59731_T_CYCLE_0)); +scape: + return err; +} + +#define TLC59731_DEVICE(i) \ + static struct tlc59731_cfg tlc59731_cfg_##i = { \ + .sdi_gpio = GPIO_DT_SPEC_INST_GET(i, gpios), \ + .length = DT_INST_PROP(i, chain_length), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(i, tlc59731_gpio_init, NULL, NULL, &tlc59731_cfg_##i, POST_KERNEL, \ + CONFIG_LED_STRIP_INIT_PRIORITY, &tlc59731_gpio_api); +DT_INST_FOREACH_STATUS_OKAY(TLC59731_DEVICE) diff --git a/dts/bindings/led_strip/ti,tlc59731.yaml b/dts/bindings/led_strip/ti,tlc59731.yaml new file mode 100644 index 00000000000000..596bee98d165d6 --- /dev/null +++ b/dts/bindings/led_strip/ti,tlc59731.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Javad Rahimipetroudi +# SPDX-License-Identifier: Apache-2.0 + +compatible: "ti,tlc59731" +description: TLC59731 RGB LED Controller +include: [led-strip.yaml] + +properties: + gpios: + required: true + type: phandle-array + description: | + GPIO to send command data to the controller. From 114dcb9fc466d92f9cf7584293f7c83779bf7202 Mon Sep 17 00:00:00 2001 From: Javad Rahimipetroudi Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1112/1389] boards: stm32wb5mmg_dk: add RGB LED support This patch add RGB LED support for the TI TLC59731 RGB controller. Signed-off-by: Javad Rahimipetroudi --- boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst | 8 +++++++ boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst b/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst index a149ea79a3679e..51bde0110c55df 100644 --- a/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst +++ b/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst @@ -170,6 +170,14 @@ Serial Port STM32WB5MM-DK board has 2 (LP)U(S)ARTs. The Zephyr console output is assigned to USART1. Default settings are ``115200 8N1``. +LEDs +---- +STM32WB5MM-DK has two types of LEDs, The resources coming from STM32WB5MMG are +shared between the RGB and IR LEDs. It is not possible to use them +simultaneously. The selection is done by JP4 and JP5 jumpers. +To use the RGB LED, JP5 must be ON and JP4 OFF. In this configuration, +GPIO_SELECT2 (PH1) is the chip select for this RGB device on SPI1. + Programming and Debugging ************************* diff --git a/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts b/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts index 4f4fb99cea013d..6e48823ae242eb 100644 --- a/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts +++ b/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts @@ -8,6 +8,7 @@ #include #include #include +#include / { model = "STMicroelectronics STM32WB5MM Discovery Development Kit"; @@ -22,11 +23,23 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; }; + + rgb_led_strip: rgb_strip { + compatible = "ti,tlc59731"; + gpios = <&gpioa 7 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + chain-length = <1>; + color-mapping = ; + status = "disabled"; + }; + aliases { watchdog0 = &iwdg; die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; + led-strip = &rgb_led_strip; }; }; @@ -136,6 +149,15 @@ zephyr_udc0: &usb { }; }; +&gpioh { + rgb_cs: rgb_cs { + gpios = <1 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + status = "disabled"; + }; +}; + &vref { status = "okay"; }; From b84e501eea7ca7d03165953bd6f8c69666c823d7 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1113/1389] dts: bindings: video: Add bindings for NXP MIPI CSI-2 Rx Add bindings for NXP MIPI CSI-2 Rx which is a MIPI CSI-2 receiver connecting a camera sensor to the NXP CSI. Signed-off-by: Phi Bang Nguyen --- dts/bindings/video/nxp,mipi-csi2rx.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 dts/bindings/video/nxp,mipi-csi2rx.yaml diff --git a/dts/bindings/video/nxp,mipi-csi2rx.yaml b/dts/bindings/video/nxp,mipi-csi2rx.yaml new file mode 100644 index 00000000000000..1726d63b3299e1 --- /dev/null +++ b/dts/bindings/video/nxp,mipi-csi2rx.yaml @@ -0,0 +1,17 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: NXP MIPI CSI-2 Rx interface + +compatible: "nxp,mipi-csi2rx" + +include: [base.yaml] + +properties: + sensor: + required: true + type: phandle + description: the connected camera sensor From 50aa73803e4098bdee382e7a80b710fab8b30ffd Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1114/1389] drivers: video: Add NXP MIPI CSI-2 Rx driver Add driver to support NXP MIPI CSI-2 Rx which is a MIPI CSI-2 receiver connecting a camera sensor to the NXP CSI. This IP is present in the i.MX RT11XX series. Signed-off-by: Phi Bang Nguyen --- drivers/video/CMakeLists.txt | 1 + drivers/video/Kconfig | 2 + drivers/video/Kconfig.mcux_mipi_csi2rx | 10 ++ drivers/video/video_mcux_mipi_csi2rx.c | 218 +++++++++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 drivers/video/Kconfig.mcux_mipi_csi2rx create mode 100644 drivers/video/video_mcux_mipi_csi2rx.c diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index b93c5bb2f66c67..19ad0e2bc797ee 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -5,6 +5,7 @@ zephyr_library() zephyr_library_sources(video_common.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_MCUX_CSI video_mcux_csi.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_MCUX_MIPI_CSI2RX video_mcux_mipi_csi2rx.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_SW_GENERATOR video_sw_generator.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_MT9M114 mt9m114.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7725 ov7725.c) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9f44944150fc9a..787311622e0cc9 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -33,6 +33,8 @@ config VIDEO_BUFFER_POOL_ALIGN source "drivers/video/Kconfig.mcux_csi" +source "drivers/video/Kconfig.mcux_mipi_csi2rx" + source "drivers/video/Kconfig.sw_generator" source "drivers/video/Kconfig.mt9m114" diff --git a/drivers/video/Kconfig.mcux_mipi_csi2rx b/drivers/video/Kconfig.mcux_mipi_csi2rx new file mode 100644 index 00000000000000..f9bf2f19f1efec --- /dev/null +++ b/drivers/video/Kconfig.mcux_mipi_csi2rx @@ -0,0 +1,10 @@ +# NXP MIPI CSI-2 Rx driver configuration option + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_MCUX_MIPI_CSI2RX + bool "NXP MIPI CSI-2 Rx driver" + default y + depends on DT_HAS_NXP_MIPI_CSI2RX_ENABLED + select VIDEO_MCUX_CSI diff --git a/drivers/video/video_mcux_mipi_csi2rx.c b/drivers/video/video_mcux_mipi_csi2rx.c new file mode 100644 index 00000000000000..6d9dc5729edc35 --- /dev/null +++ b/drivers/video/video_mcux_mipi_csi2rx.c @@ -0,0 +1,218 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_mipi_csi2rx + +#include + +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(mipi_csi); + +/* + * Two data lanes are set by default as 2-lanes camera sensors are + * more common and more performant but single lane is also supported. + */ +#define DEFAULT_MIPI_CSI_NUM_LANES 2 +#define DEFAULT_CAMERA_FRAME_RATE 30 + +struct mipi_csi2rx_config { + const MIPI_CSI2RX_Type *base; + const struct device *sensor_dev; +}; + +struct mipi_csi2rx_data { + csi2rx_config_t csi2rxConfig; +}; + +static int mipi_csi2rx_set_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct mipi_csi2rx_config *config = dev->config; + struct mipi_csi2rx_data *drv_data = dev->data; + csi2rx_config_t csi2rxConfig = {0}; + uint8_t i = 0; + + /* + * Initialize the MIPI CSI2 + * + * From D-PHY specification, the T-HSSETTLE should in the range of 85ns+6*UI to 145ns+10*UI + * UI is Unit Interval, equal to the duration of any HS state on the Clock Lane + * + * T-HSSETTLE = csi2rxConfig.tHsSettle_EscClk * (Tperiod of RxClkInEsc) + * + * csi2rxConfig.tHsSettle_EscClk setting for camera: + * + * Resolution | frame rate | T_HS_SETTLE + * ============================================= + * 720P | 30 | 0x12 + * --------------------------------------------- + * 720P | 15 | 0x17 + * --------------------------------------------- + * VGA | 30 | 0x1F + * --------------------------------------------- + * VGA | 15 | 0x24 + * --------------------------------------------- + * QVGA | 30 | 0x1F + * --------------------------------------------- + * QVGA | 15 | 0x24 + * --------------------------------------------- + */ + static const uint32_t csi2rxHsSettle[][4] = { + { + 1280, + 720, + 30, + 0x12, + }, + { + 1280, + 720, + 15, + 0x17, + }, + { + 640, + 480, + 30, + 0x1F, + }, + { + 640, + 480, + 15, + 0x24, + }, + { + 320, + 240, + 30, + 0x1F, + }, + { + 320, + 240, + 15, + 0x24, + }, + }; + + csi2rxConfig.laneNum = DEFAULT_MIPI_CSI_NUM_LANES; + + for (i = 0; i < ARRAY_SIZE(csi2rxHsSettle); i++) { + if ((fmt->width == csi2rxHsSettle[i][0]) && (fmt->height == csi2rxHsSettle[i][1]) && + (DEFAULT_CAMERA_FRAME_RATE == csi2rxHsSettle[i][2])) { + csi2rxConfig.tHsSettle_EscClk = csi2rxHsSettle[i][3]; + break; + } + } + + if (i == ARRAY_SIZE(csi2rxHsSettle)) { + LOG_ERR("Unsupported resolution"); + return -ENOTSUP; + } + + drv_data->csi2rxConfig = csi2rxConfig; + + if (video_set_format(config->sensor_dev, ep, fmt)) { + return -EIO; + } + + return 0; +} + +static int mipi_csi2rx_get_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct mipi_csi2rx_config *config = dev->config; + + if (fmt == NULL || ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + if (video_get_format(config->sensor_dev, ep, fmt)) { + return -EIO; + } + + return 0; +} + +static int mipi_csi2rx_stream_start(const struct device *dev) +{ + const struct mipi_csi2rx_config *config = dev->config; + struct mipi_csi2rx_data *drv_data = dev->data; + + CSI2RX_Init((MIPI_CSI2RX_Type *)config->base, &drv_data->csi2rxConfig); + + if (video_stream_start(config->sensor_dev)) { + return -EIO; + } + + return 0; +} + +static int mipi_csi2rx_stream_stop(const struct device *dev) +{ + const struct mipi_csi2rx_config *config = dev->config; + + if (video_stream_stop(config->sensor_dev)) { + return -EIO; + } + + CSI2RX_Deinit((MIPI_CSI2RX_Type *)config->base); + + return 0; +} + +static int mipi_csi2rx_get_caps(const struct device *dev, enum video_endpoint_id ep, + struct video_caps *caps) +{ + const struct mipi_csi2rx_config *config = dev->config; + + if (ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + /* Just forward to sensor dev for now */ + return video_get_caps(config->sensor_dev, ep, caps); +} + +static const struct video_driver_api mipi_csi2rx_driver_api = { + .get_caps = mipi_csi2rx_get_caps, + .get_format = mipi_csi2rx_get_fmt, + .set_format = mipi_csi2rx_set_fmt, + .stream_start = mipi_csi2rx_stream_start, + .stream_stop = mipi_csi2rx_stream_stop, +}; + +static int mipi_csi2rx_init(const struct device *dev) +{ + const struct mipi_csi2rx_config *config = dev->config; + + /* Check if there is any sensor device */ + if (!device_is_ready(config->sensor_dev)) { + return -ENODEV; + } + + return 0; +} + +#define MIPI_CSI2RX_INIT(n) \ + static struct mipi_csi2rx_data mipi_csi2rx_data_##n; \ + \ + static const struct mipi_csi2rx_config mipi_csi2rx_config_##n = { \ + .base = (MIPI_CSI2RX_Type *)DT_INST_REG_ADDR(n), \ + .sensor_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, sensor)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &mipi_csi2rx_init, NULL, &mipi_csi2rx_data_##n, \ + &mipi_csi2rx_config_##n, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \ + &mipi_csi2rx_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MIPI_CSI2RX_INIT) From bc4f13d13a82bb34bf587e1daae976227607ea50 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1115/1389] soc: nxp: imxrt11xx: Enable power, clocks and muxing for MIPI CSI-2 Rx Enable power and clocks for MIPI CSI-2 Rx. Configure Video Mux to connect it to CSI. Signed-off-by: Phi Bang Nguyen --- soc/nxp/imxrt/imxrt11xx/soc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/soc/nxp/imxrt/imxrt11xx/soc.c b/soc/nxp/imxrt/imxrt11xx/soc.c index 0a1eecc2cc9210..642708af9871dc 100644 --- a/soc/nxp/imxrt/imxrt11xx/soc.c +++ b/soc/nxp/imxrt/imxrt11xx/soc.c @@ -456,6 +456,27 @@ static ALWAYS_INLINE void clock_init(void) CLOCK_SetRootClock(kCLOCK_Root_Lpspi1, &rootCfg); #endif +#ifdef CONFIG_VIDEO_MCUX_MIPI_CSI2RX + /* MIPI CSI-2 Rx connects to CSI via Video Mux */ + CLOCK_EnableClock(kCLOCK_Video_Mux); + VIDEO_MUX->VID_MUX_CTRL.SET = VIDEO_MUX_VID_MUX_CTRL_CSI_SEL_MASK; + + /* Configure MIPI CSI-2 Rx clocks */ + rootCfg.div = 8; + rootCfg.mux = kCLOCK_CSI2_ClockRoot_MuxSysPll3Out; + CLOCK_SetRootClock(kCLOCK_Root_Csi2, &rootCfg); + + rootCfg.mux = kCLOCK_CSI2_ESC_ClockRoot_MuxSysPll3Out; + CLOCK_SetRootClock(kCLOCK_Root_Csi2_Esc, &rootCfg); + + rootCfg.mux = kCLOCK_CSI2_UI_ClockRoot_MuxSysPll3Out; + CLOCK_SetRootClock(kCLOCK_Root_Csi2_Ui, &rootCfg); + + /* Enable power domain for MIPI CSI-2 */ + PGMC_BPC4->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_ON_SOFT_MASK | + PGMC_BPC_BPC_POWER_CTRL_ISO_OFF_SOFT_MASK); +#endif + #ifdef CONFIG_CAN_MCUX_FLEXCAN #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan1), okay) /* Configure CAN1 using Osc48MDiv2 */ From 8cdfe1f6f87c4f56c5f94fa28789572c5bf485f3 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1116/1389] dts: arm: nxp: Add devicetree node for MIPI CSI-2 Rx Add a node for MIPI CSI-2 Rx in i.MX RT11xx devicetree and connect it to the CSI node. Signed-off-by: Phi Bang Nguyen --- dts/arm/nxp/nxp_rt11xx.dtsi | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index 03611213830ae9..fc0a1690800107 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -808,6 +808,35 @@ reg = <0x40800000 0x4000>; interrupts = <56 1>; status = "disabled"; + source = <&mipi_csi2rx>; + + port { + csi_ep_in: endpoint { + remote-endpoint = <&mipi_csi2rx_ep_out>; + }; + }; + }; + + mipi_csi2rx: mipi_csi2rx@40810000 { + compatible = "nxp,mipi-csi2rx"; + reg = <0x40810000 0x200>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mipi_csi2rx_ep_out: endpoint { + remote-endpoint = <&csi_ep_in>; + }; + }; + + port@1 { + reg = <1>; + }; + }; }; flexcan1: can@400c4000 { From 52c41f235dfde2e3336a458d44b5a70aa0fcce5f Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1117/1389] tests: drivers: build_all: video: Add test for mipi csi2rx Add test case for mipi csi2rx driver. As this driver selects the csi driver, the csi node has to be enabled as well. Signed-off-by: Phi Bang Nguyen --- .../mimxrt1170_evk_mimxrt1176_cm7.overlay | 56 +++++++++++++++++++ tests/drivers/build_all/video/testcase.yaml | 4 ++ 2 files changed, 60 insertions(+) create mode 100644 tests/drivers/build_all/video/mimxrt1170_evk_mimxrt1176_cm7.overlay diff --git a/tests/drivers/build_all/video/mimxrt1170_evk_mimxrt1176_cm7.overlay b/tests/drivers/build_all/video/mimxrt1170_evk_mimxrt1176_cm7.overlay new file mode 100644 index 00000000000000..99542ad4c78255 --- /dev/null +++ b/tests/drivers/build_all/video/mimxrt1170_evk_mimxrt1176_cm7.overlay @@ -0,0 +1,56 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + * + * Names in this file should be chosen in a way that won't conflict + * with real-world devicetree nodes, to allow these tests to run on + * (and be extended to test) real hardware. + */ + +/ { + test { + #address-cells = <1>; + #size-cells = <1>; + + test_gpio: gpio@deadbeef { + compatible = "vnd,gpio"; + gpio-controller; + reg = <0xdeadbeef 0x1000>; + #gpio-cells = <0x2>; + status = "okay"; + }; + + test_i2c: i2c@11112222 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "vnd,i2c"; + reg = <0x11112222 0x1000>; + status = "okay"; + clock-frequency = <100000>; + + test_i2c_ov5640: ov5640@1 { + compatible = "ovti,ov5640"; + reg = <0x1>; + reset-gpios = <&test_gpio 0 0>; + powerdown-gpios = <&test_gpio 1 0>; + }; + }; + + test_csi: csi@22223333 { + compatible = "nxp,imx-csi"; + reg = <0x22223333 0x4000>; + status = "okay"; + interrupt-parent = <&nvic>; + interrupts = <56 1>; + source = <&test_mipi_csi2rx>; + }; + + test_mipi_csi2rx: mipi_csi2rx@33334444 { + compatible = "nxp,mipi-csi2rx"; + reg = <0x33334444 0x200>; + status = "okay"; + sensor = <&test_i2c_ov5640>; + }; + }; +}; diff --git a/tests/drivers/build_all/video/testcase.yaml b/tests/drivers/build_all/video/testcase.yaml index 2acb801b9c6438..49acda27c13efc 100644 --- a/tests/drivers/build_all/video/testcase.yaml +++ b/tests/drivers/build_all/video/testcase.yaml @@ -16,3 +16,7 @@ tests: platform_allow: - mimxrt1064_evk - mimxrt1170_evk/mimxrt1176/cm7 + drivers.video.mcux_mipi_csi2rx.build: + platform_allow: + - mimxrt1170_evk/mimxrt1176/cm7 + - mimxrt1170_evk@B/mimxrt1176/cm7 From d734345c283132d2d42a1324a8bc84999eb0fbc3 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1118/1389] boards: steval_stwinbx1: Remove adc support from board's yaml Leftover from review. Signed-off-by: Erwan Gouriou --- boards/st/steval_stwinbx1/steval_stwinbx1.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.yaml b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml index 12715712a0bb84..a12712dda8a1e1 100644 --- a/boards/st/steval_stwinbx1/steval_stwinbx1.yaml +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml @@ -8,7 +8,6 @@ toolchain: ram: 786 flash: 2048 supported: - - adc - counter - gpio - pwm From 5a9c82ab151e7455e454efea8e8f51c01c09c56f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1119/1389] net: doc: buf.h: Improve documentation Added missing doxygen comments. Also hide internal symbols from generated documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/buf.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/include/zephyr/net/buf.h b/include/zephyr/net/buf.h index c50e5e592451b1..2855017b282432 100644 --- a/include/zephyr/net/buf.h +++ b/include/zephyr/net/buf.h @@ -1017,10 +1017,10 @@ struct net_buf { /** Where the buffer should go when freed up. */ uint8_t pool_id; - /* Size of user data on this buffer */ + /** Size of user data on this buffer */ uint8_t user_data_size; - /* Union for convenience access to the net_buf_simple members, also + /** Union for convenience access to the net_buf_simple members, also * preserving the old API. */ union { @@ -1042,13 +1042,17 @@ struct net_buf { uint8_t *__buf; }; + /** @cond INTERNAL_HIDDEN */ struct net_buf_simple b; + /** @endcond */ }; /** System metadata for this buffer. */ uint8_t user_data[] __net_buf_align; }; +/** @cond INTERNAL_HIDDEN */ + struct net_buf_data_cb { uint8_t * __must_check (*alloc)(struct net_buf *buf, size_t *size, k_timeout_t timeout); @@ -1062,6 +1066,8 @@ struct net_buf_data_alloc { size_t max_alloc_size; }; +/** @endcond */ + /** * @brief Network buffer pool representation. * @@ -1071,7 +1077,7 @@ struct net_buf_pool { /** LIFO to place the buffer into when free */ struct k_lifo free; - /* to prevent concurrent access/modifications */ + /** To prevent concurrent access/modifications */ struct k_spinlock lock; /** Number of buffers in pool */ @@ -1080,7 +1086,7 @@ struct net_buf_pool { /** Number of uninitialized buffers */ uint16_t uninit_count; - /* Size of user data allocated to this pool */ + /** Size of user data allocated to this pool */ uint8_t user_data_size; #if defined(CONFIG_NET_BUF_POOL_USAGE) @@ -1172,12 +1178,14 @@ extern const struct net_buf_data_alloc net_buf_heap_alloc; _net_buf_##_name, _count, _ud_size, \ _destroy) +/** @cond INTERNAL_HIDDEN */ + struct net_buf_pool_fixed { uint8_t *data_pool; }; -/** @cond INTERNAL_HIDDEN */ extern const struct net_buf_data_cb net_buf_fixed_cb; + /** @endcond */ /** From 2c1c008a9ff47a4a5765b7b53a69d3b24095c578 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1120/1389] net: doc: canbus.h: Added missing @file section This will improve documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/canbus.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/canbus.h b/include/zephyr/net/canbus.h index da5b6a3e067bf1..1d7056a72ead7b 100644 --- a/include/zephyr/net/canbus.h +++ b/include/zephyr/net/canbus.h @@ -4,8 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_NET_CAN_H_ -#define ZEPHYR_INCLUDE_NET_CAN_H_ +/** @file + * @brief CAN bus socket API definitions. + */ + +#ifndef ZEPHYR_INCLUDE_NET_CANBUS_H_ +#define ZEPHYR_INCLUDE_NET_CANBUS_H_ #include #include @@ -52,4 +56,4 @@ BUILD_ASSERT(offsetof(struct canbus_api, iface_api) == 0); } #endif -#endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */ +#endif /* ZEPHYR_INCLUDE_NET_CANBUS_H_ */ From 01d8d5e7e41e9f0fc124f5958a35d4333888bca9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1121/1389] net: doc: coap: Fix doxygen documentation Fix doxygen documentation in COAP header files to improve documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/coap.h | 30 +++++++++++++++++++++++++++ include/zephyr/net/coap_client.h | 7 ++++++- include/zephyr/net/coap_link_format.h | 2 ++ include/zephyr/net/coap_mgmt.h | 10 ++++----- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index bd47f92106ef18..c6714ee9dcb5ac 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -82,12 +82,16 @@ enum coap_method { COAP_METHOD_IPATCH = 7, /**< IPATCH */ }; +/** @cond INTERNAL_HIDDEN */ + #define COAP_REQUEST_MASK 0x07 #define COAP_VERSION_1 1U #define COAP_OBSERVE_MAX_AGE 0xFFFFFF +/** @endcond */ + /** * @brief CoAP packets may be of one of these types. */ @@ -193,10 +197,14 @@ enum coap_response_code { COAP_MAKE_RESPONSE_CODE(5, 5) }; +/** @cond INTERNAL_HIDDEN */ + #define COAP_CODE_EMPTY (0) #define COAP_TOKEN_MAX_LEN 8UL +/** @endcond */ + /** * @brief Set of Content-Format option values for CoAP. * @@ -214,11 +222,15 @@ enum coap_content_format { COAP_CONTENT_FORMAT_APP_CBOR = 60 /**< application/cbor */ }; +/** @cond INTERNAL_HIDDEN */ + /* block option helper */ #define GET_BLOCK_NUM(v) ((v) >> 4) #define GET_BLOCK_SIZE(v) (((v) & 0x7)) #define GET_MORE(v) (!!((v) & 0x08)) +/** @endcond */ + struct coap_observer; struct coap_packet; struct coap_pending; @@ -251,10 +263,15 @@ typedef void (*coap_notify_t)(struct coap_resource *resource, struct coap_resource { /** Which function to be called for each CoAP method */ coap_method_t get, post, put, del, fetch, patch, ipatch; + /** Notify function to call */ coap_notify_t notify; + /** Resource path */ const char * const *path; + /** User specific opaque data */ void *user_data; + /** List of resource observers */ sys_slist_t observers; + /** Resource age */ int age; }; @@ -262,9 +279,13 @@ struct coap_resource { * @brief Represents a remote device that is observing a local resource. */ struct coap_observer { + /** Observer list node */ sys_snode_t list; + /** Observer connection end point information */ struct sockaddr addr; + /** Observer token */ uint8_t token[8]; + /** Extended token length */ uint8_t tkl; }; @@ -344,11 +365,17 @@ struct coap_pending { * also used when observing resources. */ struct coap_reply { + /** CoAP reply callback */ coap_reply_t reply; + /** User specific opaque data */ void *user_data; + /** Reply age */ int age; + /** Reply id */ uint16_t id; + /** Reply token */ uint8_t token[8]; + /** Extended token length */ uint8_t tkl; }; @@ -721,8 +748,11 @@ static inline enum coap_block_size coap_bytes_to_block_size(uint16_t bytes) * @brief Represents the current state of a block-wise transaction. */ struct coap_block_context { + /** Total size of the block-wise transaction */ size_t total_size; + /** Current size of the block-wise transaction */ size_t current; + /** Block size */ enum coap_block_size block_size; }; diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index 7779b22fca9607..a3576a244c5215 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -22,7 +22,7 @@ #include #include - +/** Maximum size of a CoAP message */ #define MAX_COAP_MSG_LEN (CONFIG_COAP_CLIENT_MESSAGE_HEADER_SIZE + \ CONFIG_COAP_CLIENT_MESSAGE_SIZE) @@ -67,12 +67,17 @@ struct coap_client_request { * @brief Representation of extra options for the CoAP client request */ struct coap_client_option { + /** Option code */ uint16_t code; #if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN) + /** Option len */ uint16_t len; + /** Buffer for the length */ uint8_t value[CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE]; #else + /** Option len */ uint8_t len; + /** Buffer for the length */ uint8_t value[12]; #endif }; diff --git a/include/zephyr/net/coap_link_format.h b/include/zephyr/net/coap_link_format.h index cabfb9ff859d92..7c7c3c5f2f3780 100644 --- a/include/zephyr/net/coap_link_format.h +++ b/include/zephyr/net/coap_link_format.h @@ -70,7 +70,9 @@ int coap_well_known_core_get_len(struct coap_resource *resources, * to a valid coap_core_metadata structure. */ struct coap_core_metadata { + /** List of attributes to add */ const char * const *attributes; + /** User specific data */ void *user_data; }; diff --git a/include/zephyr/net/coap_mgmt.h b/include/zephyr/net/coap_mgmt.h index f19eec6eb4b436..a52293a9265833 100644 --- a/include/zephyr/net/coap_mgmt.h +++ b/include/zephyr/net/coap_mgmt.h @@ -38,8 +38,6 @@ struct coap_service; struct coap_resource; struct coap_observer; -/** @endcond */ - enum net_event_coap_cmd { /* Service events */ NET_EVENT_COAP_CMD_SERVICE_STARTED = 1, @@ -49,6 +47,8 @@ enum net_event_coap_cmd { NET_EVENT_COAP_CMD_OBSERVER_REMOVED, }; +/** @endcond */ + /** * @brief coap_mgmt event raised when a service has started */ @@ -77,7 +77,7 @@ enum net_event_coap_cmd { * @brief CoAP Service event structure. */ struct net_event_coap_service { - /* The CoAP service for which the event is emitted */ + /** The CoAP service for which the event is emitted */ const struct coap_service *service; }; @@ -85,9 +85,9 @@ struct net_event_coap_service { * @brief CoAP Observer event structure. */ struct net_event_coap_observer { - /* The CoAP resource for which the event is emitted */ + /** The CoAP resource for which the event is emitted */ struct coap_resource *resource; - /* The observer that is added/removed */ + /** The observer that is added/removed */ struct coap_observer *observer; }; From 41b57b6ea17bde96987048a3b9ee54040a1671a6 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1122/1389] net: doc: conn_mgr_connectivity.h: @endcond was incorrectly placed The net_event_conn_cmd is internal so no need to generate public documentation for it. Signed-off-by: Jukka Rissanen --- include/zephyr/net/conn_mgr_connectivity.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zephyr/net/conn_mgr_connectivity.h b/include/zephyr/net/conn_mgr_connectivity.h index d083509b437bc4..048f40124de8a0 100644 --- a/include/zephyr/net/conn_mgr_connectivity.h +++ b/include/zephyr/net/conn_mgr_connectivity.h @@ -41,13 +41,13 @@ extern "C" { NET_MGMT_EVENT_BIT) #define _NET_MGMT_CONN_IF_EVENT (NET_MGMT_IFACE_BIT | _NET_MGMT_CONN_BASE) -/** @endcond */ - enum net_event_conn_cmd { NET_EVENT_CONN_CMD_IF_TIMEOUT = 1, NET_EVENT_CONN_CMD_IF_FATAL_ERROR, }; +/** @endcond */ + /** * @brief net_mgmt event raised when a connection attempt times out */ From 4118c9efdba3079a13752941a5410eac107d4e28 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1123/1389] net: doc: conn_mgr_monitor.h: Add @file documentation This improves documentation coverage metric for this file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/conn_mgr_monitor.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/zephyr/net/conn_mgr_monitor.h b/include/zephyr/net/conn_mgr_monitor.h index 94c50d90f19114..16a873b7b2f1db 100644 --- a/include/zephyr/net/conn_mgr_monitor.h +++ b/include/zephyr/net/conn_mgr_monitor.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief API for monitoring network connections and interfaces. + */ + #ifndef ZEPHYR_INCLUDE_CONN_MGR_H_ #define ZEPHYR_INCLUDE_CONN_MGR_H_ From 96ba85d32f6f28bed5315b9623f884c1213214c8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1124/1389] net: doc: dhcpv4.h: Document DHCPv4 message types The DHCPv4 message type documentation was missing. Signed-off-by: Jukka Rissanen --- include/zephyr/net/dhcpv4.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/dhcpv4.h b/include/zephyr/net/dhcpv4.h index b06a7cb0320a54..c31d5f91417822 100644 --- a/include/zephyr/net/dhcpv4.h +++ b/include/zephyr/net/dhcpv4.h @@ -54,14 +54,14 @@ enum net_dhcpv4_state { * within corresponding changes to net_dhcpv4_msg_type_name. */ enum net_dhcpv4_msg_type { - NET_DHCPV4_MSG_TYPE_DISCOVER = 1, - NET_DHCPV4_MSG_TYPE_OFFER = 2, - NET_DHCPV4_MSG_TYPE_REQUEST = 3, - NET_DHCPV4_MSG_TYPE_DECLINE = 4, - NET_DHCPV4_MSG_TYPE_ACK = 5, - NET_DHCPV4_MSG_TYPE_NAK = 6, - NET_DHCPV4_MSG_TYPE_RELEASE = 7, - NET_DHCPV4_MSG_TYPE_INFORM = 8, + NET_DHCPV4_MSG_TYPE_DISCOVER = 1, /**< Discover message */ + NET_DHCPV4_MSG_TYPE_OFFER = 2, /**< Offer message */ + NET_DHCPV4_MSG_TYPE_REQUEST = 3, /**< Request message */ + NET_DHCPV4_MSG_TYPE_DECLINE = 4, /**< Decline message */ + NET_DHCPV4_MSG_TYPE_ACK = 5, /**< Acknowledge message */ + NET_DHCPV4_MSG_TYPE_NAK = 6, /**< Negative acknowledge message */ + NET_DHCPV4_MSG_TYPE_RELEASE = 7, /**< Release message */ + NET_DHCPV4_MSG_TYPE_INFORM = 8, /**< Inform message */ }; struct net_dhcpv4_option_callback; From 12a6161f46f8153ec1d92772b0bc1c8978f9b48d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1125/1389] net: doc: dns_resolve.h: Improve documentation Couple of doxygen comments were missing. Signed-off-by: Jukka Rissanen --- include/zephyr/net/dns_resolve.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/dns_resolve.h b/include/zephyr/net/dns_resolve.h index b0d1fc7dcc9a49..fff5d4ad867d8f 100644 --- a/include/zephyr/net/dns_resolve.h +++ b/include/zephyr/net/dns_resolve.h @@ -90,9 +90,13 @@ enum dns_query_type { * Address info struct is passed to callback that gets all the results. */ struct dns_addrinfo { + /** IP address information */ struct sockaddr ai_addr; + /** Length of the ai_addr field */ socklen_t ai_addrlen; - uint8_t ai_family; + /** Address family of the address information */ + uint8_t ai_family; + /** Canonical name of the address */ char ai_canonname[DNS_MAX_NAME_SIZE + 1]; }; @@ -159,16 +163,21 @@ typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data); +/** @cond INTERNAL_HIDDEN */ + enum dns_resolve_context_state { DNS_RESOLVE_CONTEXT_ACTIVE, DNS_RESOLVE_CONTEXT_DEACTIVATING, DNS_RESOLVE_CONTEXT_INACTIVE, }; +/** @endcond */ + /** * DNS resolve context structure. */ struct dns_resolve_context { + /** List of configured DNS servers */ struct { /** DNS server information */ struct sockaddr dns_server; From 843f8bbf6cb6266e96217955e75a107c86b12ab4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1126/1389] net: doc: dsa.h: Hide internal documentation Do not generate documentation for internal symbols. Signed-off-by: Jukka Rissanen --- include/zephyr/net/dsa.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/zephyr/net/dsa.h b/include/zephyr/net/dsa.h index 479690509a3f27..1aed17e11baad2 100644 --- a/include/zephyr/net/dsa.h +++ b/include/zephyr/net/dsa.h @@ -21,6 +21,8 @@ * @{ */ +/** @cond INTERNAL_HIDDEN */ + #define NET_DSA_PORT_MAX_COUNT 8 #define DSA_STATUS_PERIOD_MS K_MSEC(1000) @@ -34,6 +36,8 @@ #define DSA_TAG_SIZE 0 #endif +/** @endcond */ + #ifdef __cplusplus extern "C" { #endif From 37d0fa46b9231cf56eb0a9b2e9f9fc04c677fc28 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1127/1389] net: doc: dummy.h: Document dummy L2 header file The dummy L2 header file was missing documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/dummy.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/zephyr/net/dummy.h b/include/zephyr/net/dummy.h index bcf250a341cb99..4c5fe0312349bc 100644 --- a/include/zephyr/net/dummy.h +++ b/include/zephyr/net/dummy.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** @file + * @brief Dummy layer 2 + * + * This is not to be included by the application. + */ #ifndef ZEPHYR_INCLUDE_NET_DUMMY_H_ #define ZEPHYR_INCLUDE_NET_DUMMY_H_ @@ -22,6 +27,7 @@ extern "C" { * @{ */ +/** Dummy L2 API operations. */ struct dummy_api { /** * The net_if_api must be placed in first position in this From bc53abe670276f326208cb79db81f4589816e3a5 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1128/1389] net: doc: ethernet.h: Document header file properly Documentation to various public features was missing. Also some of the public features were marked in hidden section. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ethernet.h | 135 ++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 30 deletions(-) diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h index 9ecc7340d03e70..30fbb200bce448 100644 --- a/include/zephyr/net/ethernet.h +++ b/include/zephyr/net/ethernet.h @@ -20,11 +20,7 @@ #include #include - -#if defined(CONFIG_NET_LLDP) #include -#endif - #include #include #include @@ -49,14 +45,15 @@ extern "C" { * @{ */ -#define NET_ETH_ADDR_LEN 6U - -/** @cond INTERNAL_HIDDEN */ +#define NET_ETH_ADDR_LEN 6U /**< Ethernet MAC address length */ +/** Ethernet address */ struct net_eth_addr { - uint8_t addr[NET_ETH_ADDR_LEN]; + uint8_t addr[NET_ETH_ADDR_LEN]; /**< Buffer storing the address */ }; +/** @cond INTERNAL_HIDDEN */ + #define NET_ETH_HDR(pkt) ((struct net_eth_hdr *)net_pkt_data(pkt)) #define NET_ETH_PTYPE_CAN 0x000C /* CAN: Controller Area Network */ @@ -108,8 +105,12 @@ struct net_eth_addr { #define ETH_P_HDLC NET_ETH_PTYPE_HDLC #endif -#define NET_ETH_MINIMAL_FRAME_SIZE 60 -#define NET_ETH_MTU 1500 +/** @endcond */ + +#define NET_ETH_MINIMAL_FRAME_SIZE 60 /**< Minimum Ethernet frame size */ +#define NET_ETH_MTU 1500 /**< Ethernet MTU size */ + +/** @cond INTERNAL_HIDDEN */ #if defined(CONFIG_NET_VLAN) #define _NET_ETH_MAX_HDR_SIZE (sizeof(struct net_eth_vlan_hdr)) @@ -134,7 +135,7 @@ struct net_eth_addr { /** @endcond */ -/** Ethernet hardware capabilities */ +/** @brief Ethernet hardware capabilities */ enum ethernet_hw_caps { /** TX Checksum offloading supported for all of IPv4, UDP, TCP */ ETHERNET_HW_TX_CHKSUM_OFFLOAD = BIT(0), @@ -181,8 +182,10 @@ enum ethernet_hw_caps { /** VLAN Tag stripping */ ETHERNET_HW_VLAN_TAG_STRIP = BIT(14), - /** DSA switch */ - ETHERNET_DSA_SLAVE_PORT = BIT(15), + /** DSA switch slave port */ + ETHERNET_DSA_SLAVE_PORT = BIT(15), + + /** DSA switch master port */ ETHERNET_DSA_MASTER_PORT = BIT(16), /** IEEE 802.1Qbv (scheduled traffic) supported */ @@ -230,11 +233,14 @@ enum ethernet_t1s_param_type { }; /** @endcond */ + +/** Ethernet T1S specific parameters */ struct ethernet_t1s_param { /** Type of T1S parameter */ enum ethernet_t1s_param_type type; union { - /* PLCA is the Physical Layer (PHY) Collision + /** + * PLCA is the Physical Layer (PHY) Collision * Avoidance technique employed with multidrop * 10Base-T1S standard. * @@ -273,6 +279,7 @@ struct ethernet_t1s_param { }; }; +/** Ethernet Qav specific parameters */ struct ethernet_qav_param { /** ID of the priority queue to use */ int queue_id; @@ -314,6 +321,7 @@ enum ethernet_gate_state_operation { /** @endcond */ +/** Ethernet Qbv specific parameters */ struct ethernet_qbv_param { /** Port id */ int port_id; @@ -325,6 +333,7 @@ struct ethernet_qbv_param { /** True if Qbv is enabled or not */ bool enabled; + /** Gate control information */ struct { /** True = open, False = closed */ bool gate_status[NET_TC_TX_COUNT]; @@ -342,7 +351,8 @@ struct ethernet_qbv_param { /** Number of entries in gate control list */ uint32_t gate_control_list_len; - /* The time values are set in one go when type is set to + /** + * The time values are set in one go when type is set to * ETHERNET_QBV_PARAM_TYPE_TIME */ struct { @@ -378,6 +388,7 @@ enum ethernet_qbu_preempt_status { /** @endcond */ +/** Ethernet Qbu specific parameters */ struct ethernet_qbu_param { /** Port id */ int port_id; @@ -390,8 +401,7 @@ struct ethernet_qbu_param { /** Release advance (nanoseconds) */ uint32_t release_advance; - /** sequence of framePreemptionAdminStatus values. - */ + /** sequence of framePreemptionAdminStatus values */ enum ethernet_qbu_preempt_status frame_preempt_statuses[NET_TC_TX_COUNT]; @@ -401,14 +411,14 @@ struct ethernet_qbu_param { /** Link partner status (from Qbr) */ bool link_partner_status; - /** Additional fragment size (from Qbr). The minimum non-final + /** + * Additional fragment size (from Qbr). The minimum non-final * fragment size is (additional_fragment_size + 1) * 64 octets */ uint8_t additional_fragment_size : 2; }; }; - /** @cond INTERNAL_HIDDEN */ enum ethernet_filter_type { @@ -427,7 +437,7 @@ enum ethernet_if_types { L2_ETH_IF_TYPE_WIFI, } __packed; - +/** Ethernet filter description */ struct ethernet_filter { /** Type of filter */ enum ethernet_filter_type type; @@ -445,6 +455,7 @@ enum ethernet_txtime_param_type { /** @endcond */ +/** Ethernet TXTIME specific parameters */ struct ethernet_txtime_param { /** Type of TXTIME parameter */ enum ethernet_txtime_param_type type; @@ -455,6 +466,7 @@ struct ethernet_txtime_param { }; /** @cond INTERNAL_HIDDEN */ + struct ethernet_config { union { bool auto_negotiation; @@ -482,8 +494,10 @@ struct ethernet_config { struct ethernet_filter filter; }; }; + /** @endcond */ +/** Ethernet L2 API operations. */ struct ethernet_api { /** * The net_if_api must be placed in first position in this @@ -491,11 +505,11 @@ struct ethernet_api { */ struct net_if_api iface_api; -#if defined(CONFIG_NET_STATISTICS_ETHERNET) /** Collect optional ethernet specific statistics. This pointer * should be set by driver if statistics needs to be collected * for that driver. */ +#if defined(CONFIG_NET_STATISTICS_ETHERNET) struct net_stats_eth *(*get_stats)(const struct device *dev); #endif @@ -518,18 +532,18 @@ struct ethernet_api { enum ethernet_config_type type, struct ethernet_config *config); -#if defined(CONFIG_NET_VLAN) /** The IP stack will call this function when a VLAN tag is enabled * or disabled. If enable is set to true, then the VLAN tag was added, * if it is false then the tag was removed. The driver can utilize * this information if needed. */ +#if defined(CONFIG_NET_VLAN) int (*vlan_setup)(const struct device *dev, struct net_if *iface, uint16_t tag, bool enable); #endif /* CONFIG_NET_VLAN */ -#if defined(CONFIG_PTP_CLOCK) /** Return ptp_clock device that is tied to this ethernet device */ +#if defined(CONFIG_PTP_CLOCK) const struct device *(*get_ptp_clock)(const struct device *dev); #endif /* CONFIG_PTP_CLOCK */ @@ -537,12 +551,13 @@ struct ethernet_api { int (*send)(const struct device *dev, struct net_pkt *pkt); }; +/** @cond INTERNAL_HIDDEN */ + /* Make sure that the network interface API is properly setup inside * Ethernet API struct (it is the first one). */ BUILD_ASSERT(offsetof(struct ethernet_api, iface_api) == 0); -/** @cond INTERNAL_HIDDEN */ struct net_eth_hdr { struct net_eth_addr dst; struct net_eth_addr src; @@ -567,7 +582,7 @@ struct ethernet_vlan { /** @endcond */ -#if defined(CONFIG_NET_LLDP) +/** Ethernet LLDP specific parameters */ struct ethernet_lldp { /** Used for track timers */ sys_snode_t node; @@ -593,7 +608,8 @@ struct ethernet_lldp { /** LLDP RX callback function */ net_lldp_recv_cb_t cb; }; -#endif /* CONFIG_NET_LLDP */ + +/** @cond INTERNAL_HIDDEN */ enum ethernet_flags { ETH_CARRIER_UP, @@ -671,8 +687,6 @@ struct ethernet_context { */ void ethernet_init(struct net_if *iface); -/** @cond INTERNAL_HIDDEN */ - #define ETHERNET_L2_CTX_TYPE struct ethernet_context /* Separate header for VLAN as some of device interfaces might not @@ -688,7 +702,15 @@ struct net_eth_vlan_hdr { uint16_t type; } __packed; +/** @endcond */ +/** + * @brief Check if the Ethernet MAC address is a broadcast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a broadcast address, false if not + */ static inline bool net_eth_is_addr_broadcast(struct net_eth_addr *addr) { if (addr->addr[0] == 0xff && @@ -703,6 +725,13 @@ static inline bool net_eth_is_addr_broadcast(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is unspecified. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is unspecified, false if not + */ static inline bool net_eth_is_addr_unspecified(struct net_eth_addr *addr) { if (addr->addr[0] == 0x00 && @@ -717,6 +746,13 @@ static inline bool net_eth_is_addr_unspecified(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is a multicast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a multicast address, false if not + */ static inline bool net_eth_is_addr_multicast(struct net_eth_addr *addr) { #if defined(CONFIG_NET_IPV6) @@ -737,16 +773,37 @@ static inline bool net_eth_is_addr_multicast(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is a group address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a group address, false if not + */ static inline bool net_eth_is_addr_group(struct net_eth_addr *addr) { return addr->addr[0] & 0x01; } +/** + * @brief Check if the Ethernet MAC address is valid. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is valid, false if not + */ static inline bool net_eth_is_addr_valid(struct net_eth_addr *addr) { return !net_eth_is_addr_unspecified(addr) && !net_eth_is_addr_group(addr); } +/** + * @brief Check if the Ethernet MAC address is a LLDP multicast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a LLDP multicast address, false if not + */ static inline bool net_eth_is_addr_lldp_multicast(struct net_eth_addr *addr) { #if defined(CONFIG_NET_GPTP) || defined(CONFIG_NET_LLDP) @@ -758,11 +815,20 @@ static inline bool net_eth_is_addr_lldp_multicast(struct net_eth_addr *addr) addr->addr[5] == 0x0e) { return true; } +#else + ARG_UNUSED(addr); #endif return false; } +/** + * @brief Check if the Ethernet MAC address is a PTP multicast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a PTP multicast address, false if not + */ static inline bool net_eth_is_addr_ptp_multicast(struct net_eth_addr *addr) { #if defined(CONFIG_NET_GPTP) @@ -774,15 +840,20 @@ static inline bool net_eth_is_addr_ptp_multicast(struct net_eth_addr *addr) addr->addr[5] == 0x00) { return true; } +#else + ARG_UNUSED(addr); #endif return false; } +/** + * @brief Return Ethernet broadcast address. + * + * @return Ethernet broadcast address. + */ const struct net_eth_addr *net_eth_broadcast_addr(void); -/** @endcond */ - /** * @brief Convert IPv4 multicast address to Ethernet address. * @@ -989,6 +1060,8 @@ static inline bool net_eth_is_vlan_interface(struct net_if *iface) } #endif +/** @cond INTERNAL_HIDDEN */ + #if !defined(CONFIG_ETH_DRIVER_RAW_MODE) #define Z_ETH_NET_DEVICE_INIT_INSTANCE(node_id, dev_id, name, instance, \ @@ -1017,6 +1090,8 @@ static inline bool net_eth_is_vlan_interface(struct net_if *iface) init_fn, pm, data, config, prio, \ api, mtu) +/** @endcond */ + /** * @brief Create an Ethernet network interface and bind it to network device. * From 0d748a571ff4dc8c2ac22150b2e42afd438d6bb4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:27 +0200 Subject: [PATCH 1129/1389] net: doc: ethernet_bridge.h: Hide internal structs from doxygen Mark internal structs as hidden to avoid generating public documentation for it. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ethernet_bridge.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/zephyr/net/ethernet_bridge.h b/include/zephyr/net/ethernet_bridge.h index aa86f63a5616b1..fa2ca54698335f 100644 --- a/include/zephyr/net/ethernet_bridge.h +++ b/include/zephyr/net/ethernet_bridge.h @@ -56,6 +56,8 @@ struct eth_bridge { STRUCT_SECTION_ITERABLE(eth_bridge, name) = \ ETH_BRIDGE_INITIALIZER(name) +/** @cond INTERNAL_HIDDEN */ + struct eth_bridge_iface_context { sys_snode_t node; struct eth_bridge *instance; @@ -67,6 +69,8 @@ struct eth_bridge_listener { struct k_fifo pkt_queue; }; +/** @endcond */ + /** * @brief Add an Ethernet network interface to a bridge * From 9ce89a2e5563c5f12687f35edda6b2f39d009fdf Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1130/1389] net: doc: gptp.h: Documentation missing for structs Add more struct documentation to gptp.h Signed-off-by: Jukka Rissanen --- include/zephyr/net/gptp.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zephyr/net/gptp.h b/include/zephyr/net/gptp.h index 049a94ec99e808..488583e4d533b6 100644 --- a/include/zephyr/net/gptp.h +++ b/include/zephyr/net/gptp.h @@ -130,6 +130,7 @@ struct gptp_port_identity { uint16_t port_number; } __packed; +/** gPTP message flags */ struct gptp_flags { union { /** Byte access. */ @@ -140,6 +141,7 @@ struct gptp_flags { }; } __packed; +/** gPTP message header */ struct gptp_hdr { /** Type of the message. */ uint8_t message_type:4; From 9165647ccb94b366d54b0257e08054659585f9ad Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1131/1389] net: doc: hostname.h: Document hostname length macro properly Max hostname length was not documented. Signed-off-by: Jukka Rissanen --- include/zephyr/net/hostname.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/zephyr/net/hostname.h b/include/zephyr/net/hostname.h index d9bac4393c287e..4e801ffbda5c55 100644 --- a/include/zephyr/net/hostname.h +++ b/include/zephyr/net/hostname.h @@ -28,17 +28,22 @@ extern "C" { (sizeof(CONFIG_NET_HOSTNAME) - 1 + \ (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE) ? sizeof("0011223344556677") - 1 : 0))) #else +/** Maximum hostname length */ #define NET_HOSTNAME_MAX_LEN \ (sizeof(CONFIG_NET_HOSTNAME) - 1 + \ (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE) ? sizeof("0011223344556677") - 1 : 0)) #endif +/** @cond INTERNAL_HIDDEN */ + #if defined(CONFIG_NET_HOSTNAME_ENABLE) #define NET_HOSTNAME_SIZE NET_HOSTNAME_MAX_LEN + 1 #else #define NET_HOSTNAME_SIZE 1 #endif +/** @endcond */ + /** * @brief Get the device hostname * From a9ada39591277fdde16280724348bfdf60f904c5 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1132/1389] net: doc: http/client.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/client.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/include/zephyr/net/http/client.h b/include/zephyr/net/http/client.h index 6a95004001f42b..71eb1b32f336f2 100644 --- a/include/zephyr/net/http/client.h +++ b/include/zephyr/net/http/client.h @@ -30,6 +30,8 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + #if !defined(HTTP_CRLF) #define HTTP_CRLF "\r\n" #endif @@ -38,10 +40,12 @@ extern "C" { #define HTTP_STATUS_STR_SIZE 32 #endif -/* Is there more data to come */ +/** @endcond */ + +/** Is there more data to come */ enum http_final_call { - HTTP_DATA_MORE = 0, - HTTP_DATA_FINAL = 1, + HTTP_DATA_MORE = 0, /**< More data will come */ + HTTP_DATA_FINAL = 1, /**< End of data */ }; struct http_request; @@ -174,7 +178,7 @@ struct http_response { */ size_t processed; - /* https://tools.ietf.org/html/rfc7230#section-3.1.2 + /** See https://tools.ietf.org/html/rfc7230#section-3.1.2 for more information. * The status-code element is a 3-digit integer code * * The reason-phrase element exists for the sole @@ -193,9 +197,9 @@ struct http_response { */ uint16_t http_status_code; - uint8_t cl_present : 1; - uint8_t body_found : 1; - uint8_t message_complete : 1; + uint8_t cl_present : 1; /**< Is Content-Length field present */ + uint8_t body_found : 1; /**< Is message body found */ + uint8_t message_complete : 1; /**< Is HTTP message parsing complete */ }; /** HTTP client internal data that the application should not touch From 0bf50570d5fc8bf84247b992f394bfec61c3e98f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1133/1389] net: doc: http/frame.h: Improve documentation Doxygen documentation was totally missing in this file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/frame.h | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/include/zephyr/net/http/frame.h b/include/zephyr/net/http/frame.h index 3e51539b4b7eb0..02d063c68660b5 100644 --- a/include/zephyr/net/http/frame.h +++ b/include/zephyr/net/http/frame.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief HTTP2 frame information. + */ + #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVER_FRAME_H_ #define ZEPHYR_INCLUDE_NET_HTTP_SERVER_FRAME_H_ @@ -13,19 +18,32 @@ extern "C" { #endif +/** HTTP2 frame types */ enum http_frame_type { + /** Data frame */ HTTP_SERVER_DATA_FRAME = 0x00, + /** Headers frame */ HTTP_SERVER_HEADERS_FRAME = 0x01, + /** Priority frame */ HTTP_SERVER_PRIORITY_FRAME = 0x02, + /** Reset stream frame */ HTTP_SERVER_RST_STREAM_FRAME = 0x03, + /** Settings frame */ HTTP_SERVER_SETTINGS_FRAME = 0x04, + /** Push promise frame */ HTTP_SERVER_PUSH_PROMISE_FRAME = 0x05, + /** Ping frame */ HTTP_SERVER_PING_FRAME = 0x06, + /** Goaway frame */ HTTP_SERVER_GOAWAY_FRAME = 0x07, + /** Window update frame */ HTTP_SERVER_WINDOW_UPDATE_FRAME = 0x08, + /** Continuation frame */ HTTP_SERVER_CONTINUATION_FRAME = 0x09 }; +/** @cond INTERNAL_HIDDEN */ + #define HTTP_SERVER_HPACK_METHOD 0 #define HTTP_SERVER_HPACK_PATH 1 @@ -39,17 +57,27 @@ enum http_frame_type { #define HTTP_SERVER_FRAME_FLAGS_OFFSET 4 #define HTTP_SERVER_FRAME_STREAM_ID_OFFSET 5 +/** @endcond */ + +/** HTTP2 settings field */ struct http_settings_field { - uint16_t id; - uint32_t value; + uint16_t id; /**< Field id */ + uint32_t value; /**< Field value */ } __packed; +/** @brief HTTP2 settings */ enum http_settings { + /** Header table size */ HTTP_SETTINGS_HEADER_TABLE_SIZE = 1, + /** Enable push */ HTTP_SETTINGS_ENABLE_PUSH = 2, + /** Maximum number of concurrent streams */ HTTP_SETTINGS_MAX_CONCURRENT_STREAMS = 3, + /** Initial window size */ HTTP_SETTINGS_INITIAL_WINDOW_SIZE = 4, + /** Max frame size */ HTTP_SETTINGS_MAX_FRAME_SIZE = 5, + /** Max header list size */ HTTP_SETTINGS_MAX_HEADER_LIST_SIZE = 6, }; From 1ab462d35178f12b34c3ebf4fefba27541f10222 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1134/1389] net: doc: http/hpack.h: Hide internal documentation Prevent internal symbols from being in generated documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/hpack.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/zephyr/net/http/hpack.h b/include/zephyr/net/http/hpack.h index 35bfa49189f130..0a85cf7c8adca9 100644 --- a/include/zephyr/net/http/hpack.h +++ b/include/zephyr/net/http/hpack.h @@ -26,6 +26,8 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + enum http_hpack_static_key { HTTP_SERVER_HPACK_INVALID = 0, HTTP_SERVER_HPACK_AUTHORITY = 1, @@ -100,6 +102,8 @@ enum http_hpack_static_key { #define HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE 0 #endif +/** @endcond */ + /** HTTP2 header field with decoding buffer. */ struct http_hpack_header_buf { /** A pointer to the decoded header field name. */ @@ -121,6 +125,8 @@ struct http_hpack_header_buf { size_t datalen; }; +/** @cond INTERNAL_HIDDEN */ + int http_hpack_huffman_decode(const uint8_t *encoded_buf, size_t encoded_len, uint8_t *buf, size_t buflen); int http_hpack_huffman_encode(const uint8_t *str, size_t str_len, @@ -130,6 +136,8 @@ int http_hpack_decode_header(const uint8_t *buf, size_t datalen, int http_hpack_encode_header(uint8_t *buf, size_t buflen, struct http_hpack_header_buf *header); +/** @endcond */ + #ifdef __cplusplus } #endif From bba4fc635af2872d0e506853f66e2de6ae4b1f19 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1135/1389] net: doc: http/method.h: Hide internal documentation Do not generate documentation for internal symbols. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/method.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zephyr/net/http/method.h b/include/zephyr/net/http/method.h index b27e3144b236b9..30f4aaeeaca7cf 100644 --- a/include/zephyr/net/http/method.h +++ b/include/zephyr/net/http/method.h @@ -58,7 +58,9 @@ enum http_method { HTTP_LINK = 31, /**< LINK */ HTTP_UNLINK = 32, /**< UNLINK */ + /** @cond INTERNAL_HIDDEN */ HTTP_METHOD_END_VALUE /* keep this the last value */ + /** @endcond */ }; #ifdef __cplusplus From 30bb18e789fdce7f6a380b95bdfdac3c3974a67a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1136/1389] net: doc: http/server.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/server.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 7bfb609384356c..3e5223427dc7d3 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -9,7 +9,10 @@ #define ZEPHYR_INCLUDE_NET_HTTP_SERVER_H_ /** + * @file server.h + * * @brief HTTP server API + * * @defgroup http_server HTTP server API * @ingroup networking * @{ @@ -196,12 +199,28 @@ BUILD_ASSERT(offsetof(struct http_resource_detail_dynamic, common) == 0); typedef int (*http_resource_websocket_cb_t)(int ws_socket, void *user_data); +/** @brief Representation of a websocket server resource */ struct http_resource_detail_websocket { + /** Common resource details. */ struct http_resource_detail common; + + /** Websocket socket value */ int ws_sock; + + /** Resource callback used by the server to interact with the + * application. + */ http_resource_websocket_cb_t cb; + + /** Data buffer used to exchanged data between server and the, + * application. + */ uint8_t *data_buffer; + + /** Length of the data in the data buffer. */ size_t data_buffer_len; + + /** A pointer to the user data registered by the application. */ void *user_data; }; @@ -335,8 +354,10 @@ struct http_client_ctx { */ struct k_work_delayable inactivity_timer; - /* Websocket security key. */ +/** @cond INTERNAL_HIDDEN */ + /** Websocket security key. */ IF_ENABLED(CONFIG_WEBSOCKET, (uint8_t ws_sec_key[HTTP_SERVER_WS_MAX_SEC_KEY_LEN])); +/** @endcond */ /** Flag indicating that headers were sent in the reply. */ bool headers_sent : 1; From 7f4ad000c6d69827ee8203036267b75eee4d7b1b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1137/1389] net: doc: http/service.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/http/service.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/http/service.h b/include/zephyr/net/http/service.h index 334444420b983b..e541c768f5636c 100644 --- a/include/zephyr/net/http/service.h +++ b/include/zephyr/net/http/service.h @@ -8,7 +8,10 @@ #define ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ /** + * @file service.h + * * @brief HTTP service API + * * @defgroup http_service HTTP service API * @ingroup networking * @{ @@ -25,8 +28,11 @@ extern "C" { #endif +/** HTTP resource description */ struct http_resource_desc { + /** Resource name */ const char *resource; + /** Detail associated with this resource */ void *detail; }; @@ -54,6 +60,8 @@ struct http_resource_desc { .detail = (void *)(_detail), \ } +/** @cond INTERNAL_HIDDEN */ + struct http_service_desc { const char *host; uint16_t *port; @@ -86,6 +94,8 @@ struct http_service_desc { (GET_ARG_N(1, GET_ARGS_LESS_N(1, __VA_ARGS__))))), ())\ } +/** @endcond */ + /** * @brief Define an HTTP service without static resources. * @@ -207,7 +217,7 @@ struct http_service_desc { /** * @brief Iterate over all HTTP services. * - * @param _it Name of iterator (of type @ref http_service_desc) + * @param _it Name of http_service_desc iterator */ #define HTTP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(http_service_desc, _it) From 2f4579125927d885b2d856a1d30c2ca7e25d66d1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1138/1389] net: doc: icmp.h: Add ICMPv4/6 packet type documentation Descriptions of both the ICMPv4 and v6 packet types were missing. Signed-off-by: Jukka Rissanen --- include/zephyr/net/icmp.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/zephyr/net/icmp.h b/include/zephyr/net/icmp.h index a5b9f6b2455c45..6d6a6b2c867dd5 100644 --- a/include/zephyr/net/icmp.h +++ b/include/zephyr/net/icmp.h @@ -5,11 +5,12 @@ */ /** @file icmp.h + * + * @brief ICMP sending and receiving. * * @defgroup icmp Send and receive IPv4 or IPv6 ICMP Echo Request messages. * @ingroup networking * @{ - * @brief ICMP sending and receiving. */ #ifndef ZEPHYR_INCLUDE_NET_ICMP_H_ @@ -27,10 +28,10 @@ extern "C" { #endif -#define NET_ICMPV4_ECHO_REQUEST 8 -#define NET_ICMPV4_ECHO_REPLY 0 -#define NET_ICMPV6_ECHO_REQUEST 128 -#define NET_ICMPV6_ECHO_REPLY 129 +#define NET_ICMPV4_ECHO_REQUEST 8 /**< ICMPv4 Echo-Request */ +#define NET_ICMPV4_ECHO_REPLY 0 /**< ICMPv4 Echo-Reply */ +#define NET_ICMPV6_ECHO_REQUEST 128 /**< ICMPv6 Echo-Request */ +#define NET_ICMPV6_ECHO_REPLY 129 /**< ICMPv6 Echo-Reply */ struct net_icmp_ctx; struct net_icmp_ip_hdr; @@ -136,7 +137,7 @@ struct net_icmp_ping_params { /** Network packet priority. */ int priority; - /* Arbitrary payload data that will be included in the Echo Reply + /** Arbitrary payload data that will be included in the Echo Reply * verbatim. May be NULL. */ const void *data; From ae2e3e2a6458eb8b28ffed6d13861d6efbc44e8c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1139/1389] net: doc: ieee802154.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ieee802154.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/ieee802154.h b/include/zephyr/net/ieee802154.h index 927a9036db3e3d..b60aa7071f3904 100644 --- a/include/zephyr/net/ieee802154.h +++ b/include/zephyr/net/ieee802154.h @@ -241,10 +241,11 @@ struct ieee802154_security_ctx { /** INTERNAL_HIDDEN @endcond */ }; +/** @brief IEEE 802.15.4 device role */ enum ieee802154_device_role { - IEEE802154_DEVICE_ROLE_ENDDEVICE, - IEEE802154_DEVICE_ROLE_COORDINATOR, - IEEE802154_DEVICE_ROLE_PAN_COORDINATOR, + IEEE802154_DEVICE_ROLE_ENDDEVICE, /**< End device */ + IEEE802154_DEVICE_ROLE_COORDINATOR, /**< Coordinator */ + IEEE802154_DEVICE_ROLE_PAN_COORDINATOR, /**< PAN coordinator */ }; /** IEEE 802.15.4 L2 context. */ From 48843d800e79d3ee4c51f57a5691aeac4f6316ca Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1140/1389] net: doc: ieee802154_ie.h: Add more info to documentation This improves documentation coverage numbers for this file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ieee802154_ie.h | 52 ++++++++++++++++++------------ 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/include/zephyr/net/ieee802154_ie.h b/include/zephyr/net/ieee802154_ie.h index 0be4c1576e5c07..a2378a38efa842 100644 --- a/include/zephyr/net/ieee802154_ie.h +++ b/include/zephyr/net/ieee802154_ie.h @@ -40,8 +40,8 @@ * @details See sections 7.4.2.1 and 7.4.3.1. */ enum ieee802154_ie_type { - IEEE802154_IE_TYPE_HEADER = 0x0, - IEEE802154_IE_TYPE_PAYLOAD, + IEEE802154_IE_TYPE_HEADER = 0x0, /**< Header type */ + IEEE802154_IE_TYPE_PAYLOAD, /**< Payload type */ }; /** @@ -51,13 +51,13 @@ enum ieee802154_ie_type { * are implemented. */ enum ieee802154_header_ie_element_id { - IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00, - IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a, - IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b, - IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d, - IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e, - IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e, - IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f, + IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00, /**< Vendor specific IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a, /**< CSL IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b, /**< RIT IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d, /**< Rendezvous time IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e, /**< Time correction IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e, /**< Header termination 1 */ + IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f, /**< Header termination 2 */ /* partial list, add additional ids as needed */ }; @@ -67,36 +67,40 @@ enum ieee802154_header_ie_element_id { /** @brief Vendor Specific Header IE, see section 7.4.2.3. */ struct ieee802154_header_ie_vendor_specific { + /** Vendor OUI */ uint8_t vendor_oui[IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN]; + /** Vendor specific information */ uint8_t *vendor_specific_info; } __packed; /** @brief Full CSL IE, see section 7.4.2.3. */ struct ieee802154_header_ie_csl_full { - uint16_t csl_phase; - uint16_t csl_period; - uint16_t csl_rendezvous_time; + uint16_t csl_phase; /**< CSL phase */ + uint16_t csl_period; /**< CSL period */ + uint16_t csl_rendezvous_time; /**< Rendezvous time */ } __packed; /** @brief Reduced CSL IE, see section 7.4.2.3. */ struct ieee802154_header_ie_csl_reduced { - uint16_t csl_phase; - uint16_t csl_period; + uint16_t csl_phase; /**< CSL phase */ + uint16_t csl_period; /**< CSL period */ } __packed; /** @brief Generic CSL IE, see section 7.4.2.3. */ struct ieee802154_header_ie_csl { union { + /** CSL full information */ struct ieee802154_header_ie_csl_full full; + /** CSL reduced information */ struct ieee802154_header_ie_csl_reduced reduced; }; } __packed; /** @brief RIT IE, see section 7.4.2.4. */ struct ieee802154_header_ie_rit { - uint8_t time_to_first_listen; - uint8_t number_of_repeat_listen; - uint16_t repeat_listen_interval; + uint8_t time_to_first_listen; /**< Time to First Listen */ + uint8_t number_of_repeat_listen; /**< Number of Repeat Listen */ + uint16_t repeat_listen_interval; /**< Repeat listen interval */ } __packed; /** @@ -104,8 +108,8 @@ struct ieee802154_header_ie_rit { * (macCslInterval is nonzero). */ struct ieee802154_header_ie_rendezvous_time_full { - uint16_t rendezvous_time; - uint16_t wakeup_interval; + uint16_t rendezvous_time; /**< Rendezvous time */ + uint16_t wakeup_interval; /**< Wakeup interval */ } __packed; /** @@ -113,22 +117,26 @@ struct ieee802154_header_ie_rendezvous_time_full { * (macCslInterval is zero). */ struct ieee802154_header_ie_rendezvous_time_reduced { - uint16_t rendezvous_time; + uint16_t rendezvous_time; /**< Rendezvous time */ } __packed; /** @brief Rendezvous Time IE, see section 7.4.2.6. */ struct ieee802154_header_ie_rendezvous_time { union { + /** Rendezvous time full information */ struct ieee802154_header_ie_rendezvous_time_full full; + /** Rendezvous time reduced information */ struct ieee802154_header_ie_rendezvous_time_reduced reduced; }; } __packed; /** @brief Time Correction IE, see section 7.4.2.7. */ struct ieee802154_header_ie_time_correction { - uint16_t time_sync_info; + uint16_t time_sync_info; /**< Time synchronization information */ } __packed; +/** @cond INTERNAL_HIDDEN */ + /* @brief Generic Header IE, see section 7.4.2.1. */ struct ieee802154_header_ie { #if CONFIG_LITTLE_ENDIAN @@ -152,6 +160,8 @@ struct ieee802154_header_ie { } content; } __packed; +/** INTERNAL_HIDDEN @endcond */ + /** @brief The header IE's header length (2 bytes). */ #define IEEE802154_HEADER_IE_HEADER_LENGTH sizeof(uint16_t) From e35d7b602e184af18f5a703a7aa86a1adc260595 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1141/1389] net: doc: ieee802154_mgmt.h: Improve documentation coverage Add missing doxygen documentation markers to improve documentation coverage percentage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ieee802154_mgmt.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/zephyr/net/ieee802154_mgmt.h b/include/zephyr/net/ieee802154_mgmt.h index 1f08c0b73c063b..5937242355878d 100644 --- a/include/zephyr/net/ieee802154_mgmt.h +++ b/include/zephyr/net/ieee802154_mgmt.h @@ -322,8 +322,8 @@ struct ieee802154_req_params { /** Result address */ union { - uint16_t short_addr; /* in CPU byte order */ - uint8_t addr[IEEE802154_MAX_ADDR_LENGTH]; /* in big endian */ + uint16_t short_addr; /**< in CPU byte order */ + uint8_t addr[IEEE802154_MAX_ADDR_LENGTH]; /**< in big endian */ }; /** length of address */ @@ -339,13 +339,13 @@ struct ieee802154_req_params { * see tables 9-9 and 9-10 in section 9.5. */ struct ieee802154_security_params { - uint8_t key[16]; /* secKeyDescriptor.secKey */ - uint8_t key_len; /* a key length of 16 bytes is mandatory for standards conformance */ - uint8_t key_mode : 2; /* secKeyIdMode */ - uint8_t level : 3; /* Used instead of a frame-specific SecurityLevel parameter when + uint8_t key[16]; /**< secKeyDescriptor.secKey */ + uint8_t key_len; /**< Key length of 16 bytes is mandatory for standards conformance */ + uint8_t key_mode : 2; /**< secKeyIdMode */ + uint8_t level : 3; /**< Used instead of a frame-specific SecurityLevel parameter when * constructing the auxiliary security header */ - uint8_t _unused : 3; + uint8_t _unused : 3; /**< unused value (ignore) */ }; #ifdef __cplusplus From 2dc25c80ca8acdb6d2493b8ff0c591dc28005013 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1142/1389] net: doc: ieee802154_radio.h: Add more documentation Added more doxygen comments to ieee802154 radio header file in order to improve documentation coverage percentage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ieee802154_radio.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/include/zephyr/net/ieee802154_radio.h b/include/zephyr/net/ieee802154_radio.h index 9912132918b55a..028a2d1ea1b491 100644 --- a/include/zephyr/net/ieee802154_radio.h +++ b/include/zephyr/net/ieee802154_radio.h @@ -233,8 +233,8 @@ enum ieee802154_phy_channel_page { * ieee802154_phy_supported_channels. */ struct ieee802154_phy_channel_range { - uint16_t from_channel; - uint16_t to_channel; + uint16_t from_channel; /**< From channel range */ + uint16_t to_channel; /**< To channel range */ }; /** @@ -533,11 +533,11 @@ enum ieee802154_hw_caps { /** Filter type, see @ref ieee802154_radio_api::filter */ enum ieee802154_filter_type { - IEEE802154_FILTER_TYPE_IEEE_ADDR, - IEEE802154_FILTER_TYPE_SHORT_ADDR, - IEEE802154_FILTER_TYPE_PAN_ID, - IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR, - IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR, + IEEE802154_FILTER_TYPE_IEEE_ADDR, /**< Address type filter */ + IEEE802154_FILTER_TYPE_SHORT_ADDR, /**< Short address type filter */ + IEEE802154_FILTER_TYPE_PAN_ID, /**< PAN id type filter */ + IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR, /**< Source address type filter */ + IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR, /**< Source short address type filter */ }; /** Driver events, see @ref IEEE802154_CONFIG_EVENT_HANDLER */ @@ -1125,15 +1125,15 @@ struct ieee802154_config { union { /** see @ref IEEE802154_CONFIG_AUTO_ACK_FPB */ struct { - bool enabled; - enum ieee802154_fpb_mode mode; + bool enabled; /**< Is auto ACK FPB enabled */ + enum ieee802154_fpb_mode mode; /**< Auto ACK FPB mode */ } auto_ack_fpb; /** see @ref IEEE802154_CONFIG_ACK_FPB */ struct { - uint8_t *addr; /* in little endian for both, short and extended address */ - bool extended; - bool enabled; + uint8_t *addr; /**< little endian for both short and extended address */ + bool extended; /**< Is extended address */ + bool enabled; /**< Is enabled */ } ack_fpb; /** see @ref IEEE802154_CONFIG_PAN_COORDINATOR */ @@ -1194,6 +1194,9 @@ struct ieee802154_config { */ net_time_t duration; + /** + * Used channel + */ uint8_t channel; } rx_slot; From d3e5466d76e5e75dddd2c9dc864a6df19aef5da7 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1143/1389] net: doc: ieee802154_radio_openthread.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ieee802154_radio_openthread.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/zephyr/net/ieee802154_radio_openthread.h b/include/zephyr/net/ieee802154_radio_openthread.h index f6f9949d328feb..e45bbc6b85b4c9 100644 --- a/include/zephyr/net/ieee802154_radio_openthread.h +++ b/include/zephyr/net/ieee802154_radio_openthread.h @@ -25,6 +25,7 @@ enum ieee802154_openthread_hw_caps { IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA = BIT(IEEE802154_HW_CAPS_BITS_PRIV_START), }; +/** @brief TX mode */ enum ieee802154_openthread_tx_mode { /** * The @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA mode allows to send @@ -93,6 +94,7 @@ enum ieee802154_openthread_config_type { /** OpenThread specific configuration data of ieee802154 driver. */ struct ieee802154_openthread_config { union { + /** Common configuration */ struct ieee802154_config common; /** ``IEEE802154_OPENTHREAD_CONFIG_MAX_EXTRA_CCA_ATTEMPTS`` @@ -134,6 +136,7 @@ enum ieee802154_openthread_attr { */ struct ieee802154_openthread_attr_value { union { + /** Common attribute value */ struct ieee802154_attr_value common; /** @brief Attribute value for @ref IEEE802154_OPENTHREAD_ATTR_T_RECCA */ From 0db7bd5264a7f55b18b081aeaa6506361dba5262 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1144/1389] net: doc: igmp.h: Improve IGMP documentation Adding doxygen comments to improve documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/igmp.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/igmp.h b/include/zephyr/net/igmp.h index ed39a31359f2b0..7dbfd78e1d8dac 100644 --- a/include/zephyr/net/igmp.h +++ b/include/zephyr/net/igmp.h @@ -27,10 +27,11 @@ extern "C" { #endif +/** IGMP parameters */ struct igmp_param { - struct in_addr *source_list; /* List of sources to include or exclude */ - size_t sources_len; /* Length of source list */ - bool include; /* Source list filter type */ + struct in_addr *source_list; /**< List of sources to include or exclude */ + size_t sources_len; /**< Length of source list */ + bool include; /**< Source list filter type */ }; /** From d77acab221c0e7fe0f247180bc678bc75504733f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1145/1389] net: doc: ipv4_autoconf.h: Improve documentaion Add missing doxygen comments to improve documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ipv4_autoconf.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/zephyr/net/ipv4_autoconf.h b/include/zephyr/net/ipv4_autoconf.h index 5fec5eb6637dba..3b686faffca5a5 100644 --- a/include/zephyr/net/ipv4_autoconf.h +++ b/include/zephyr/net/ipv4_autoconf.h @@ -13,13 +13,15 @@ /** Current state of IPv4 Autoconfiguration */ enum net_ipv4_autoconf_state { - NET_IPV4_AUTOCONF_INIT, - NET_IPV4_AUTOCONF_PROBE, - NET_IPV4_AUTOCONF_ANNOUNCE, - NET_IPV4_AUTOCONF_ASSIGNED, - NET_IPV4_AUTOCONF_RENEW, + NET_IPV4_AUTOCONF_INIT, /**< Initialization state */ + NET_IPV4_AUTOCONF_PROBE, /**< Probing state */ + NET_IPV4_AUTOCONF_ANNOUNCE, /**< Announce state */ + NET_IPV4_AUTOCONF_ASSIGNED, /**< Assigned state */ + NET_IPV4_AUTOCONF_RENEW, /**< Renew state */ }; +/** @cond INTERNAL_HIDDEN */ + /** * @brief Initialize IPv4 auto configuration engine. */ @@ -29,4 +31,6 @@ void net_ipv4_autoconf_init(void); #define net_ipv4_autoconf_init(...) #endif +/** @endcond */ + #endif /* ZEPHYR_INCLUDE_NET_IPV4_AUTOCONF_H_ */ From 4553767dbc63f3e9a1a5a0aa733d35756bf5315b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1146/1389] net: doc: lwm2m.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/lwm2m.h | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/lwm2m.h b/include/zephyr/net/lwm2m.h index 68a5ef9617ed56..0ae5314e3d0bcf 100644 --- a/include/zephyr/net/lwm2m.h +++ b/include/zephyr/net/lwm2m.h @@ -7,11 +7,6 @@ /** @file lwm2m.h * - * @defgroup lwm2m_api LwM2M high-level API - * @since 1.9 - * @version 0.8.0 - * @ingroup networking - * @{ * @brief LwM2M high-level API * * @details @@ -21,6 +16,12 @@ * * @note For more information refer to Technical Specification * OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A + * + * @defgroup lwm2m_api LwM2M high-level API + * @since 1.9 + * @version 0.8.0 + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_LWM2M_H_ @@ -283,7 +284,9 @@ struct lwm2m_ctx { struct lwm2m_time_series_elem { /** Cached data Unix timestamp */ time_t t; + /** Element value */ union { + /** @cond INTERNAL_HIDDEN */ uint8_t u8; uint16_t u16; uint32_t u32; @@ -295,6 +298,7 @@ struct lwm2m_time_series_elem { time_t time; double f; bool b; + /** @endcond */ }; }; @@ -2144,21 +2148,37 @@ void lwm2m_acknowledge(struct lwm2m_ctx *client_ctx); * lwm2m_rd_client_start() */ enum lwm2m_rd_client_event { + /** Invalid event */ LWM2M_RD_CLIENT_EVENT_NONE, + /** Bootstrap registration failure */ LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE, + /** Bootstrap registration complete */ LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE, + /** Bootstrap transfer complete */ LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE, + /** Registration failure */ LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE, + /** Registration complete */ LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, + /** Registration timeout */ LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT, + /** Registration update complete */ LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE, + /** De-registration failure */ LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE, + /** Disconnected */ LWM2M_RD_CLIENT_EVENT_DISCONNECT, + /** Queue mode RX off */ LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF, + /** Engine suspended */ LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED, + /** Network error */ LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR, + /** Registration update */ LWM2M_RD_CLIENT_EVENT_REG_UPDATE, + /** De-register */ LWM2M_RD_CLIENT_EVENT_DEREGISTER, + /** Server disabled */ LWM2M_RD_CLIENT_EVENT_SERVER_DISABLED, }; @@ -2270,9 +2290,9 @@ char *lwm2m_path_log_buf(char *buf, struct lwm2m_obj_path *path); * lwm2m_send_cb() */ enum lwm2m_send_status { - LWM2M_SEND_STATUS_SUCCESS, - LWM2M_SEND_STATUS_FAILURE, - LWM2M_SEND_STATUS_TIMEOUT, + LWM2M_SEND_STATUS_SUCCESS, /**< Succeed */ + LWM2M_SEND_STATUS_FAILURE, /**< Failure */ + LWM2M_SEND_STATUS_TIMEOUT, /**< Timeout */ }; /** From 131af38aacf51b552c75a961f7b8c7aa2ff0aa92 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1147/1389] net: doc: lwm2m_path.h: Add missing @file specifier This will improve document coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/lwm2m_path.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/zephyr/net/lwm2m_path.h b/include/zephyr/net/lwm2m_path.h index cd42c4942dad4e..ad012c8aba865a 100644 --- a/include/zephyr/net/lwm2m_path.h +++ b/include/zephyr/net/lwm2m_path.h @@ -8,7 +8,10 @@ #define ZEPHYR_INCLUDE_NET_LWM2M_PATH_H_ /** + * @file lwm2m.h + * * @brief LwM2M path helper macros + * * @defgroup lwm2m_path_helpers LwM2M path helper macros * @ingroup lwm2m_api * @{ From 1c38c47ec82690119dc03b4629616fd0f0cc121e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:28 +0200 Subject: [PATCH 1148/1389] net: doc: mdio.h: Add missing doxygen comments Some defines were missing proper doxygen comment. Signed-off-by: Jukka Rissanen --- include/zephyr/net/mdio.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/mdio.h b/include/zephyr/net/mdio.h index 8d1998f7cec93e..6ed13c1a6fd387 100644 --- a/include/zephyr/net/mdio.h +++ b/include/zephyr/net/mdio.h @@ -110,7 +110,7 @@ enum mdio_opcode { #define MDIO_AN_T1_ADV_M 0x0203U /** BASE-T1 Auto-negotiation advertisement register [47:32] */ #define MDIO_AN_T1_ADV_H 0x0204U -/* BASE-T1 PMA/PMD control register */ +/** BASE-T1 PMA/PMD control register */ #define MDIO_PMA_PMD_BT1_CTRL 0x0834U /* BASE-T1 Auto-negotiation Control register */ @@ -152,9 +152,9 @@ enum mdio_opcode { #define MDIO_AN_T1_ADV_M_MST BIT(4) /* BASE-T1 Auto-negotiation Advertisement register [47:32] */ -/* 10BASE-T1L High Level Transmit Operating Mode Request */ +/** 10BASE-T1L High Level Transmit Operating Mode Request */ #define MDIO_AN_T1_ADV_H_10L_TX_HI_REQ BIT(12) -/* 10BASE-T1L High Level Transmit Operating Mode Ability */ +/** 10BASE-T1L High Level Transmit Operating Mode Ability */ #define MDIO_AN_T1_ADV_H_10L_TX_HI BIT(13) /* BASE-T1 PMA/PMD control register */ From 285983117302f453614e62ead59c0862308d802d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1149/1389] net: doc: mii.h: Add missing doxygen comments Some defines were missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/mii.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/mii.h b/include/zephyr/net/mii.h index fc2a65bc306b46..371f19665c22a5 100644 --- a/include/zephyr/net/mii.h +++ b/include/zephyr/net/mii.h @@ -131,8 +131,9 @@ #define MII_ADVERTISE_10_FULL (1 << 6) /** try for 10 Mb/s half duplex support */ #define MII_ADVERTISE_10_HALF (1 << 5) -/** Selector Field */ +/** Selector Field Mask */ #define MII_ADVERTISE_SEL_MASK (0x1F << 0) +/** Selector Field */ #define MII_ADVERTISE_SEL_IEEE_802_3 0x01 /* 1000BASE-T Control Register bit definitions */ @@ -141,6 +142,7 @@ /** try for 1000BASE-T half duplex support */ #define MII_ADVERTISE_1000_HALF (1 << 8) +/** Advertise all speeds */ #define MII_ADVERTISE_ALL (MII_ADVERTISE_10_HALF | MII_ADVERTISE_10_FULL |\ MII_ADVERTISE_100_HALF | MII_ADVERTISE_100_FULL |\ MII_ADVERTISE_SEL_IEEE_802_3) From 7ea023b15f3cca82b64f0a909b9ac7a3b3a04d64 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1150/1389] net: doc: mqtt.h: Improve documentation Some doxygen comments were missing. Signed-off-by: Jukka Rissanen --- include/zephyr/net/mqtt.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index 5bbc9f794834fa..2514fc709c2c63 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -6,16 +6,17 @@ /** @file mqtt.h * - * @defgroup mqtt_socket MQTT Client library - * @since 1.14 - * @version 0.8.0 - * @ingroup networking - * @{ * @brief MQTT Client Implementation * * @note The implementation assumes TCP module is enabled. * * @note By default the implementation uses MQTT version 3.1.1. + * + * @defgroup mqtt_socket MQTT Client library + * @since 1.14 + * @version 0.8.0 + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_MQTT_H_ @@ -417,15 +418,16 @@ struct mqtt_transport { */ enum mqtt_transport_type type; + /** Use either unsecured TCP or secured TLS transport */ union { - /* TCP socket transport for MQTT */ + /** TCP socket transport for MQTT */ struct { /** Socket descriptor. */ int sock; } tcp; #if defined(CONFIG_MQTT_LIB_TLS) - /* TLS socket transport for MQTT */ + /** TLS socket transport for MQTT */ struct { /** Socket descriptor. */ int sock; @@ -559,7 +561,7 @@ struct mqtt_client { */ uint8_t clean_session : 1; - /* Userdata */ + /** User specific opaque data */ void *user_data; }; From 8dbff6548e634136651ff41a151c9bd44341bafc Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1151/1389] net: doc: mqtt_sn.h: Reshuffle doxygen comment Moving doxygen comment to proper place. Signed-off-by: Jukka Rissanen --- include/zephyr/net/mqtt_sn.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/mqtt_sn.h b/include/zephyr/net/mqtt_sn.h index cb1a6d3373123a..102cb5e692a7a5 100644 --- a/include/zephyr/net/mqtt_sn.h +++ b/include/zephyr/net/mqtt_sn.h @@ -6,15 +6,15 @@ /** @file mqtt_sn.h * - * @defgroup mqtt_sn_socket MQTT-SN Client library - * @ingroup networking - * @{ * @brief MQTT-SN Client Implementation * * @details * MQTT-SN Client's Application interface is defined in this header. * Targets protocol version 1.2. * + * @defgroup mqtt_sn_socket MQTT-SN Client library + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_MQTT_SN_H_ From bdf1cb3ddfec601ed80b85b30a7aa1493079fa33 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1152/1389] net: doc: net_context.h: Improve documentation Some doxygen comments were missing. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_context.h | 45 +++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/include/zephyr/net/net_context.h b/include/zephyr/net/net_context.h index 34dffdfe73729b..8e85af1fde97a1 100644 --- a/include/zephyr/net/net_context.h +++ b/include/zephyr/net/net_context.h @@ -35,6 +35,8 @@ extern "C" { /** Is this context used or not */ #define NET_CONTEXT_IN_USE BIT(0) +/** @cond INTERNAL_HIDDEN */ + /** State of the context (bits 1 & 2 in the flags) */ enum net_context_state { NET_CONTEXT_IDLE = 0, @@ -46,6 +48,8 @@ enum net_context_state { NET_CONTEXT_LISTENING = 3, }; +/** @endcond */ + /** * The address family, connection type and IP protocol are * stored into a bit field to save space. @@ -65,7 +69,7 @@ enum net_context_state { /** Is the socket closing / closed */ #define NET_CONTEXT_CLOSING_SOCK BIT(10) -/* Context is bound to a specific interface */ +/** Context is bound to a specific interface */ #define NET_CONTEXT_BOUND_TO_IFACE BIT(11) struct net_context; @@ -478,9 +482,13 @@ static inline void net_context_set_closing(struct net_context *context, } } +/** @cond INTERNAL_HIDDEN */ + #define NET_CONTEXT_STATE_SHIFT 1 #define NET_CONTEXT_STATE_MASK 0x03 +/** @endcond */ + /** * @brief Get state for this network context. * @@ -1258,24 +1266,25 @@ int net_context_recv(struct net_context *context, int net_context_update_recv_wnd(struct net_context *context, int32_t delta); +/** @brief Network context options. These map to BSD socket option values. */ enum net_context_option { - NET_OPT_PRIORITY = 1, - NET_OPT_TXTIME = 2, - NET_OPT_SOCKS5 = 3, - NET_OPT_RCVTIMEO = 4, - NET_OPT_SNDTIMEO = 5, - NET_OPT_RCVBUF = 6, - NET_OPT_SNDBUF = 7, - NET_OPT_DSCP_ECN = 8, - NET_OPT_REUSEADDR = 9, - NET_OPT_REUSEPORT = 10, - NET_OPT_IPV6_V6ONLY = 11, - NET_OPT_RECV_PKTINFO = 12, - NET_OPT_MCAST_TTL = 13, - NET_OPT_MCAST_HOP_LIMIT = 14, - NET_OPT_UNICAST_HOP_LIMIT = 15, - NET_OPT_TTL = 16, - NET_OPT_ADDR_PREFERENCES = 17, + NET_OPT_PRIORITY = 1, /**< Context priority */ + NET_OPT_TXTIME = 2, /**< TX time */ + NET_OPT_SOCKS5 = 3, /**< SOCKS5 */ + NET_OPT_RCVTIMEO = 4, /**< Receive timeout */ + NET_OPT_SNDTIMEO = 5, /**< Send timeout */ + NET_OPT_RCVBUF = 6, /**< Receive buffer */ + NET_OPT_SNDBUF = 7, /**< Send buffer */ + NET_OPT_DSCP_ECN = 8, /**< DSCP ECN */ + NET_OPT_REUSEADDR = 9, /**< Re-use address */ + NET_OPT_REUSEPORT = 10, /**< Re-use port */ + NET_OPT_IPV6_V6ONLY = 11, /**< Share IPv4 and IPv6 port space */ + NET_OPT_RECV_PKTINFO = 12, /**< Receive packet information */ + NET_OPT_MCAST_TTL = 13, /**< IPv4 multicast TTL */ + NET_OPT_MCAST_HOP_LIMIT = 14, /**< IPv6 multicast hop limit */ + NET_OPT_UNICAST_HOP_LIMIT = 15, /**< IPv6 unicast hop limit */ + NET_OPT_TTL = 16, /**< IPv4 unicast TTL */ + NET_OPT_ADDR_PREFERENCES = 17, /**< IPv6 address preference */ }; /** From 803b9a3cdc6543c7a18396970ed17997b6864f9c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1153/1389] net: doc: net_event.h: Document network events Add documentation to events that are triggered by the network stack. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_event.h | 182 ++++++++++++++++++++++----------- 1 file changed, 123 insertions(+), 59 deletions(-) diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index 3d2be01fd9002f..b149934f8bcacf 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -41,18 +41,6 @@ enum net_event_if_cmd { NET_EVENT_IF_CMD_ADMIN_UP, }; -#define NET_EVENT_IF_DOWN \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_DOWN) - -#define NET_EVENT_IF_UP \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_UP) - -#define NET_EVENT_IF_ADMIN_DOWN \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_DOWN) - -#define NET_EVENT_IF_ADMIN_UP \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_UP) - /* IPv6 Events */ #define _NET_IPV6_LAYER NET_MGMT_LAYER_L3 #define _NET_IPV6_CORE_CODE 0x060 @@ -88,175 +76,239 @@ enum net_event_ipv6_cmd { NET_EVENT_IPV6_CMD_PE_FILTER_DEL, }; +/* IPv4 Events*/ +#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 +#define _NET_IPV4_CORE_CODE 0x004 +#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \ + NET_MGMT_IFACE_BIT | \ + NET_MGMT_LAYER(_NET_IPV4_LAYER) | \ + NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE)) + +enum net_event_ipv4_cmd { + NET_EVENT_IPV4_CMD_ADDR_ADD = 1, + NET_EVENT_IPV4_CMD_ADDR_DEL, + NET_EVENT_IPV4_CMD_MADDR_ADD, + NET_EVENT_IPV4_CMD_MADDR_DEL, + NET_EVENT_IPV4_CMD_ROUTER_ADD, + NET_EVENT_IPV4_CMD_ROUTER_DEL, + NET_EVENT_IPV4_CMD_DHCP_START, + NET_EVENT_IPV4_CMD_DHCP_BOUND, + NET_EVENT_IPV4_CMD_DHCP_STOP, + NET_EVENT_IPV4_CMD_MCAST_JOIN, + NET_EVENT_IPV4_CMD_MCAST_LEAVE, +}; + +/* L4 network events */ +#define _NET_L4_LAYER NET_MGMT_LAYER_L4 +#define _NET_L4_CORE_CODE 0x114 +#define _NET_EVENT_L4_BASE (NET_MGMT_EVENT_BIT | \ + NET_MGMT_IFACE_BIT | \ + NET_MGMT_LAYER(_NET_L4_LAYER) | \ + NET_MGMT_LAYER_CODE(_NET_L4_CORE_CODE)) + +enum net_event_l4_cmd { + NET_EVENT_L4_CMD_CONNECTED = 1, + NET_EVENT_L4_CMD_DISCONNECTED, + NET_EVENT_L4_CMD_DNS_SERVER_ADD, + NET_EVENT_L4_CMD_DNS_SERVER_DEL, + NET_EVENT_L4_CMD_HOSTNAME_CHANGED, + NET_EVENT_L4_CMD_CAPTURE_STARTED, + NET_EVENT_L4_CMD_CAPTURE_STOPPED, +}; + +/** @endcond */ + +/** Event emitted when the network interface goes down. */ +#define NET_EVENT_IF_DOWN \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_DOWN) + +/** Event emitted when the network interface goes up. */ +#define NET_EVENT_IF_UP \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_UP) + +/** Event emitted when the network interface is taken down manually. */ +#define NET_EVENT_IF_ADMIN_DOWN \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_DOWN) + +/** Event emitted when the network interface goes up manually. */ +#define NET_EVENT_IF_ADMIN_UP \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_UP) + +/** Event emitted when an IPv6 address is added to the system. */ #define NET_EVENT_IPV6_ADDR_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD) +/** Event emitted when an IPv6 address is removed from the system. */ #define NET_EVENT_IPV6_ADDR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEL) +/** Event emitted when an IPv6 multicast address is added to the system. */ #define NET_EVENT_IPV6_MADDR_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_ADD) +/** Event emitted when an IPv6 multicast address is removed from the system. */ #define NET_EVENT_IPV6_MADDR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_DEL) +/** Event emitted when an IPv6 prefix is added to the system. */ #define NET_EVENT_IPV6_PREFIX_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_ADD) +/** Event emitted when an IPv6 prefix is removed from the system. */ #define NET_EVENT_IPV6_PREFIX_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_DEL) +/** Event emitted when an IPv6 multicast group is joined. */ #define NET_EVENT_IPV6_MCAST_JOIN \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MCAST_JOIN) +/** Event emitted when an IPv6 multicast group is left. */ #define NET_EVENT_IPV6_MCAST_LEAVE \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MCAST_LEAVE) +/** Event emitted when an IPv6 router is added to the system. */ #define NET_EVENT_IPV6_ROUTER_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_ADD) +/** Event emitted when an IPv6 router is removed from the system. */ #define NET_EVENT_IPV6_ROUTER_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_DEL) +/** Event emitted when an IPv6 route is added to the system. */ #define NET_EVENT_IPV6_ROUTE_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_ADD) +/** Event emitted when an IPv6 route is removed from the system. */ #define NET_EVENT_IPV6_ROUTE_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_DEL) +/** Event emitted when an IPv6 duplicate address detection succeeds. */ #define NET_EVENT_IPV6_DAD_SUCCEED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_SUCCEED) +/** Event emitted when an IPv6 duplicate address detection fails. */ #define NET_EVENT_IPV6_DAD_FAILED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_FAILED) +/** Event emitted when an IPv6 neighbor is added to the system. */ #define NET_EVENT_IPV6_NBR_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_ADD) +/** Event emitted when an IPv6 neighbor is removed from the system. */ #define NET_EVENT_IPV6_NBR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_DEL) +/** Event emitted when an IPv6 DHCP client starts. */ #define NET_EVENT_IPV6_DHCP_START \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_START) +/** Event emitted when an IPv6 DHCP client address is bound. */ #define NET_EVENT_IPV6_DHCP_BOUND \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_BOUND) +/** Event emitted when an IPv6 DHCP client is stopped. */ #define NET_EVENT_IPV6_DHCP_STOP \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_STOP) +/** IPv6 address is deprecated. */ #define NET_EVENT_IPV6_ADDR_DEPRECATED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEPRECATED) +/** IPv6 Privacy extension is enabled. */ #define NET_EVENT_IPV6_PE_ENABLED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_ENABLED) +/** IPv6 Privacy extension is disabled. */ #define NET_EVENT_IPV6_PE_DISABLED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_DISABLED) +/** IPv6 Privacy extension filter is added. */ #define NET_EVENT_IPV6_PE_FILTER_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_FILTER_ADD) +/** IPv6 Privacy extension filter is removed. */ #define NET_EVENT_IPV6_PE_FILTER_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_FILTER_DEL) -/* IPv4 Events*/ -#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 -#define _NET_IPV4_CORE_CODE 0x004 -#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \ - NET_MGMT_IFACE_BIT | \ - NET_MGMT_LAYER(_NET_IPV4_LAYER) | \ - NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE)) - -enum net_event_ipv4_cmd { - NET_EVENT_IPV4_CMD_ADDR_ADD = 1, - NET_EVENT_IPV4_CMD_ADDR_DEL, - NET_EVENT_IPV4_CMD_MADDR_ADD, - NET_EVENT_IPV4_CMD_MADDR_DEL, - NET_EVENT_IPV4_CMD_ROUTER_ADD, - NET_EVENT_IPV4_CMD_ROUTER_DEL, - NET_EVENT_IPV4_CMD_DHCP_START, - NET_EVENT_IPV4_CMD_DHCP_BOUND, - NET_EVENT_IPV4_CMD_DHCP_STOP, - NET_EVENT_IPV4_CMD_MCAST_JOIN, - NET_EVENT_IPV4_CMD_MCAST_LEAVE, -}; - +/** Event emitted when an IPv4 address is added to the system. */ #define NET_EVENT_IPV4_ADDR_ADD \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_ADD) +/** Event emitted when an IPv4 address is removed from the system. */ #define NET_EVENT_IPV4_ADDR_DEL \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_DEL) +/** Event emitted when an IPv4 multicast address is added to the system. */ #define NET_EVENT_IPV4_MADDR_ADD \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MADDR_ADD) +/** Event emitted when an IPv4 multicast address is removed from the system. */ #define NET_EVENT_IPV4_MADDR_DEL \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MADDR_DEL) +/** Event emitted when an IPv4 router is added to the system. */ #define NET_EVENT_IPV4_ROUTER_ADD \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ROUTER_ADD) +/** Event emitted when an IPv4 router is removed from the system. */ #define NET_EVENT_IPV4_ROUTER_DEL \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ROUTER_DEL) +/** Event emitted when an IPv4 DHCP client is started. */ #define NET_EVENT_IPV4_DHCP_START \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_DHCP_START) +/** Event emitted when an IPv4 DHCP client address is bound. */ #define NET_EVENT_IPV4_DHCP_BOUND \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_DHCP_BOUND) +/** Event emitted when an IPv4 DHCP client is stopped. */ #define NET_EVENT_IPV4_DHCP_STOP \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_DHCP_STOP) +/** Event emitted when an IPv4 multicast group is joined. */ #define NET_EVENT_IPV4_MCAST_JOIN \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MCAST_JOIN) +/** Event emitted when an IPv4 multicast group is left. */ #define NET_EVENT_IPV4_MCAST_LEAVE \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MCAST_LEAVE) - -/* L4 network events */ -#define _NET_L4_LAYER NET_MGMT_LAYER_L4 -#define _NET_L4_CORE_CODE 0x114 -#define _NET_EVENT_L4_BASE (NET_MGMT_EVENT_BIT | \ - NET_MGMT_IFACE_BIT | \ - NET_MGMT_LAYER(_NET_L4_LAYER) | \ - NET_MGMT_LAYER_CODE(_NET_L4_CORE_CODE)) - -enum net_event_l4_cmd { - NET_EVENT_L4_CMD_CONNECTED = 1, - NET_EVENT_L4_CMD_DISCONNECTED, - NET_EVENT_L4_CMD_DNS_SERVER_ADD, - NET_EVENT_L4_CMD_DNS_SERVER_DEL, - NET_EVENT_L4_CMD_HOSTNAME_CHANGED, - NET_EVENT_L4_CMD_CAPTURE_STARTED, - NET_EVENT_L4_CMD_CAPTURE_STOPPED, -}; - -#define NET_EVENT_L4_CONNECTED \ +/** Event emitted when the system is considered to be connected. + * The connected in this context means that the network interface is up, + * and the interface has either IPv4 or IPv6 address assigned to it. + */ +#define NET_EVENT_L4_CONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CONNECTED) +/** Event emitted when the system is no longer connected. + * Typically this means that network connectivity is lost either by + * the network interface is going down, or the interface has no longer + * an IP address etc. + */ #define NET_EVENT_L4_DISCONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DISCONNECTED) +/** Event emitted when a DNS server is added to the system. */ #define NET_EVENT_DNS_SERVER_ADD \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DNS_SERVER_ADD) +/** Event emitted when a DNS server is removed from the system. */ #define NET_EVENT_DNS_SERVER_DEL \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DNS_SERVER_DEL) +/** Event emitted when the system hostname is changed. */ #define NET_EVENT_HOSTNAME_CHANGED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_HOSTNAME_CHANGED) +/** Network packet capture is started. */ #define NET_EVENT_CAPTURE_STARTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CAPTURE_STARTED) +/** Network packet capture is stopped. */ #define NET_EVENT_CAPTURE_STOPPED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CAPTURE_STOPPED) -/** @endcond */ - /** * @brief Network Management event information structure * Used to pass information on network events like @@ -268,6 +320,7 @@ enum net_event_l4_cmd { * information. */ struct net_event_ipv6_addr { + /** IPv6 address related to this event */ struct in6_addr addr; }; @@ -281,8 +334,10 @@ struct net_event_ipv6_addr { * @note: idx will be '-1' in case of NET_EVENT_IPV6_NBR_DEL event. */ struct net_event_ipv6_nbr { + /** Neighbor IPv6 address */ struct in6_addr addr; - int idx; /* NBR index*/ + /** Neighbor index in cache */ + int idx; }; /** @@ -294,8 +349,11 @@ struct net_event_ipv6_nbr { * information. */ struct net_event_ipv6_route { + /** IPv6 address of the next hop */ struct in6_addr nexthop; - struct in6_addr addr; /* addr/prefix */ + /** IPv6 address or prefix of the route */ + struct in6_addr addr; + /** IPv6 prefix length */ uint8_t prefix_len; }; @@ -308,8 +366,11 @@ struct net_event_ipv6_route { * information. */ struct net_event_ipv6_prefix { - struct in6_addr addr; /* prefix */ + /** IPv6 prefix */ + struct in6_addr addr; + /** IPv6 prefix length */ uint8_t len; + /** IPv6 prefix lifetime in seconds */ uint32_t lifetime; }; @@ -320,6 +381,7 @@ struct net_event_ipv6_prefix { * information. */ struct net_event_l4_hostname { + /** New hostname */ char hostname[NET_HOSTNAME_SIZE]; }; @@ -334,7 +396,9 @@ struct net_event_l4_hostname { * This is only available if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT is >0. */ struct net_event_ipv6_pe_filter { + /** IPv6 address of privacy extension filter */ struct in6_addr prefix; + /** IPv6 filter deny or allow list */ bool is_deny_list; }; From 3ec68861f5ea37364a9929adf1b42a98989a1d59 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1154/1389] net: doc: net_if.h: Improve documentation Add missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_if.h | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 9c27e08d2c26a7..b1a2ca8925a135 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -263,15 +263,15 @@ enum net_if_flag { /** @endcond */ }; -/** Network interface operational status (RFC 2863). */ +/** @brief Network interface operational status (RFC 2863). */ enum net_if_oper_state { - NET_IF_OPER_UNKNOWN, - NET_IF_OPER_NOTPRESENT, - NET_IF_OPER_DOWN, - NET_IF_OPER_LOWERLAYERDOWN, - NET_IF_OPER_TESTING, - NET_IF_OPER_DORMANT, - NET_IF_OPER_UP, + NET_IF_OPER_UNKNOWN, /**< Initial (unknown) value */ + NET_IF_OPER_NOTPRESENT, /**< Hardware missing */ + NET_IF_OPER_DOWN, /**< Interface is down */ + NET_IF_OPER_LOWERLAYERDOWN, /**< Lower layer interface is down */ + NET_IF_OPER_TESTING, /**< Training mode */ + NET_IF_OPER_DORMANT, /**< Waiting external action */ + NET_IF_OPER_UP, /**< Interface is up */ } __packed; #if defined(CONFIG_NET_OFFLOAD) @@ -290,6 +290,7 @@ struct net_offload; #endif /* @endcond */ +/** IPv6 configuration */ struct net_if_ipv6 { /** Unicast IP addresses */ struct net_if_addr unicast[NET_IF_MAX_IPV6_ADDR]; @@ -336,6 +337,7 @@ struct net_if_ipv6 { }; #if defined(CONFIG_NET_DHCPV6) && defined(CONFIG_NET_NATIVE_IPV6) +/** DHCPv6 configuration */ struct net_if_dhcpv6 { /** Used for timer list. */ sys_snode_t node; @@ -420,6 +422,7 @@ struct net_if_addr_ipv4 { struct in_addr netmask; }; +/** IPv4 configuration */ struct net_if_ipv4 { /** Unicast IP addresses */ struct net_if_addr_ipv4 unicast[NET_IF_MAX_IPV4_ADDR]; @@ -633,7 +636,7 @@ struct net_if_dev { /** Interface's private L2 data pointer */ void *l2_data; - /* For internal use */ + /** For internal use */ ATOMIC_DEFINE(flags, NET_IF_NUM_FLAGS); /** The hardware link address */ @@ -689,7 +692,10 @@ struct net_if { int tx_pending; #endif + /** Mutex protecting this network interface instance */ struct k_mutex lock; + + /** Mutex used when sending data */ struct k_mutex tx_lock; /** Network interface specific flags */ @@ -698,14 +704,17 @@ struct net_if { */ uint8_t pe_enabled : 1; - /* If PE is enabled, then this tells whether public addresses + /** If PE is enabled, then this tells whether public addresses * are preferred over temporary ones for this interface. */ uint8_t pe_prefer_public : 1; + /** Unused bit flags (ignore) */ uint8_t _unused : 6; }; +/** @cond INTERNAL_HIDDEN */ + static inline void net_if_lock(struct net_if *iface) { NET_ASSERT(iface); @@ -745,6 +754,8 @@ static inline void net_if_tx_unlock(struct net_if *iface) k_mutex_unlock(&iface->tx_lock); } +/** @endcond */ + /** * @brief Set a value in network interface flags * @@ -1820,6 +1831,8 @@ uint8_t net_if_ipv6_get_hop_limit(struct net_if *iface); */ void net_if_ipv6_set_hop_limit(struct net_if *iface, uint8_t hop_limit); +/** @cond INTERNAL_HIDDEN */ + /* The old hop limit setter function is deprecated because the naming * of it was incorrect. The API name was missing "_if_" so this function * should not be used. @@ -1831,6 +1844,8 @@ static inline void net_ipv6_set_hop_limit(struct net_if *iface, net_if_ipv6_set_hop_limit(iface, hop_limit); } +/** @endcond */ + /** * @brief Get IPv6 multicast hop limit specified for a given interface. This is the * default value but can be overridden by the user. From 37405789f95f3396def5c3433fe9b36597df65b8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1155/1389] net: doc: net_ip.h: Improve documention Add doxygen documentation and hide internal documentation from generated documents. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_ip.h | 193 +++++++++++++++++++++++------------- 1 file changed, 122 insertions(+), 71 deletions(-) diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index 4c9acb85ac76e7..413d3efb094498 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -138,26 +138,26 @@ enum net_sock_type { /** IPv6 address struct */ struct in6_addr { union { - uint8_t s6_addr[16]; - uint16_t s6_addr16[8]; /* In big endian */ - uint32_t s6_addr32[4]; /* In big endian */ + uint8_t s6_addr[16]; /**< IPv6 address buffer */ + uint16_t s6_addr16[8]; /**< In big endian */ + uint32_t s6_addr32[4]; /**< In big endian */ }; }; -/* Binary size of the IPv6 address */ +/** Binary size of the IPv6 address */ #define NET_IPV6_ADDR_SIZE 16 /** IPv4 address struct */ struct in_addr { union { - uint8_t s4_addr[4]; - uint16_t s4_addr16[2]; /* In big endian */ - uint32_t s4_addr32[1]; /* In big endian */ - uint32_t s_addr; /* In big endian, for POSIX compatibility. */ + uint8_t s4_addr[4]; /**< IPv4 address buffer */ + uint16_t s4_addr16[2]; /**< In big endian */ + uint32_t s4_addr32[1]; /**< In big endian */ + uint32_t s_addr; /**< In big endian, for POSIX compatibility. */ }; }; -/* Binary size of the IPv4 address */ +/** Binary size of the IPv4 address */ #define NET_IPV4_ADDR_SIZE 4 /** Socket address family type */ @@ -176,51 +176,56 @@ typedef size_t socklen_t; /** Socket address struct for IPv6. */ struct sockaddr_in6 { - sa_family_t sin6_family; /* AF_INET6 */ - uint16_t sin6_port; /* Port number */ - struct in6_addr sin6_addr; /* IPv6 address */ - uint8_t sin6_scope_id; /* interfaces for a scope */ -}; - -struct sockaddr_in6_ptr { - sa_family_t sin6_family; /* AF_INET6 */ - uint16_t sin6_port; /* Port number */ - struct in6_addr *sin6_addr; /* IPv6 address */ - uint8_t sin6_scope_id; /* interfaces for a scope */ + sa_family_t sin6_family; /**< AF_INET6 */ + uint16_t sin6_port; /**< Port number */ + struct in6_addr sin6_addr; /**< IPv6 address */ + uint8_t sin6_scope_id; /**< Interfaces for a scope */ }; /** Socket address struct for IPv4. */ struct sockaddr_in { - sa_family_t sin_family; /* AF_INET */ - uint16_t sin_port; /* Port number */ - struct in_addr sin_addr; /* IPv4 address */ -}; - -struct sockaddr_in_ptr { - sa_family_t sin_family; /* AF_INET */ - uint16_t sin_port; /* Port number */ - struct in_addr *sin_addr; /* IPv4 address */ + sa_family_t sin_family; /**< AF_INET */ + uint16_t sin_port; /**< Port number */ + struct in_addr sin_addr; /**< IPv4 address */ }; /** Socket address struct for packet socket. */ struct sockaddr_ll { - sa_family_t sll_family; /* Always AF_PACKET */ - uint16_t sll_protocol; /* Physical-layer protocol */ - int sll_ifindex; /* Interface number */ - uint16_t sll_hatype; /* ARP hardware type */ - uint8_t sll_pkttype; /* Packet type */ - uint8_t sll_halen; /* Length of address */ - uint8_t sll_addr[8]; /* Physical-layer address, big endian */ + sa_family_t sll_family; /**< Always AF_PACKET */ + uint16_t sll_protocol; /**< Physical-layer protocol */ + int sll_ifindex; /**< Interface number */ + uint16_t sll_hatype; /**< ARP hardware type */ + uint8_t sll_pkttype; /**< Packet type */ + uint8_t sll_halen; /**< Length of address */ + uint8_t sll_addr[8]; /**< Physical-layer address, big endian */ +}; + +/** @cond INTERNAL_HIDDEN */ + +/** Socket address struct for IPv6 where address is a pointer */ +struct sockaddr_in6_ptr { + sa_family_t sin6_family; /**< AF_INET6 */ + uint16_t sin6_port; /**< Port number */ + struct in6_addr *sin6_addr; /**< IPv6 address */ + uint8_t sin6_scope_id; /**< interfaces for a scope */ +}; + +/** Socket address struct for IPv4 where address is a pointer */ +struct sockaddr_in_ptr { + sa_family_t sin_family; /**< AF_INET */ + uint16_t sin_port; /**< Port number */ + struct in_addr *sin_addr; /**< IPv4 address */ }; +/** Socket address struct for packet socket where address is a pointer */ struct sockaddr_ll_ptr { - sa_family_t sll_family; /* Always AF_PACKET */ - uint16_t sll_protocol; /* Physical-layer protocol */ - int sll_ifindex; /* Interface number */ - uint16_t sll_hatype; /* ARP hardware type */ - uint8_t sll_pkttype; /* Packet type */ - uint8_t sll_halen; /* Length of address */ - uint8_t *sll_addr; /* Physical-layer address, big endian */ + sa_family_t sll_family; /**< Always AF_PACKET */ + uint16_t sll_protocol; /**< Physical-layer protocol */ + int sll_ifindex; /**< Interface number */ + uint16_t sll_hatype; /**< ARP hardware type */ + uint8_t sll_pkttype; /**< Packet type */ + uint8_t sll_halen; /**< Length of address */ + uint8_t *sll_addr; /**< Physical-layer address, big endian */ }; struct sockaddr_can_ptr { @@ -228,31 +233,37 @@ struct sockaddr_can_ptr { int can_ifindex; }; +/** @endcond */ + #if !defined(HAVE_IOVEC) +/** IO vector array element */ struct iovec { - void *iov_base; - size_t iov_len; + void *iov_base; /**< Pointer to data */ + size_t iov_len; /**< Length of the data */ }; #endif +/** Message struct */ struct msghdr { - void *msg_name; /* optional socket address, big endian */ - socklen_t msg_namelen; /* size of socket address */ - struct iovec *msg_iov; /* scatter/gather array */ - size_t msg_iovlen; /* number of elements in msg_iov */ - void *msg_control; /* ancillary data */ - size_t msg_controllen; /* ancillary data buffer len */ - int msg_flags; /* flags on received message */ + void *msg_name; /**< Optional socket address, big endian */ + socklen_t msg_namelen; /**< Size of socket address */ + struct iovec *msg_iov; /**< Scatter/gather array */ + size_t msg_iovlen; /**< Number of elements in msg_iov */ + void *msg_control; /**< Ancillary data */ + size_t msg_controllen; /**< Ancillary data buffer len */ + int msg_flags; /**< Flags on received message */ }; +/** Control message ancillary data */ struct cmsghdr { - socklen_t cmsg_len; /* Number of bytes, including header */ - int cmsg_level; /* Originating protocol */ - int cmsg_type; /* Protocol-specific type */ - /* Flexible array member to force alignment of cmsghdr */ - z_max_align_t cmsg_data[]; + socklen_t cmsg_len; /**< Number of bytes, including header */ + int cmsg_level; /**< Originating protocol */ + int cmsg_type; /**< Protocol-specific type */ + z_max_align_t cmsg_data[]; /**< Flexible array member to force alignment of cmsghdr */ }; +/** @cond INTERNAL_HIDDEN */ + /* Alignment for headers and data. These are arch specific but define * them here atm if not found alredy. */ @@ -263,13 +274,24 @@ struct cmsghdr { #define ALIGN_D(x) ROUND_UP(x, __alignof__(z_max_align_t)) #endif +/** @endcond */ + #if !defined(CMSG_FIRSTHDR) +/** + * Returns a pointer to the first cmsghdr in the ancillary data buffer + * associated with the passed msghdr. It returns NULL if there isn't + * enough space for a cmsghdr in the buffer. + */ #define CMSG_FIRSTHDR(msghdr) \ ((msghdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ (struct cmsghdr *)((msghdr)->msg_control) : NULL) #endif #if !defined(CMSG_NXTHDR) +/** + * Returns the next valid cmsghdr after the passed cmsghdr. It returns NULL + * when there isn't enough space left in the buffer. + */ #define CMSG_NXTHDR(msghdr, cmsg) \ (((cmsg) == NULL) ? CMSG_FIRSTHDR(msghdr) : \ (((uint8_t *)(cmsg) + ALIGN_H((cmsg)->cmsg_len) + \ @@ -281,14 +303,30 @@ struct cmsghdr { #endif #if !defined(CMSG_DATA) +/** + * Returns a pointer to the data portion of a cmsghdr. The pointer returned + * cannot be assumed to be suitably aligned for accessing arbitrary payload + * data types. Applications should not cast it to a pointer type matching + * the payload, but should instead use memcpy(3) to copy data to or from a + * suitably declared object. + */ #define CMSG_DATA(cmsg) ((uint8_t *)(cmsg) + ALIGN_D(sizeof(struct cmsghdr))) #endif #if !defined(CMSG_SPACE) +/** + * Returns the number of bytes an ancillary element with payload of the passed + * data length occupies. + */ #define CMSG_SPACE(length) (ALIGN_D(sizeof(struct cmsghdr)) + ALIGN_H(length)) #endif #if !defined(CMSG_LEN) +/** + * Returns the value to store in the cmsg_len member of the cmsghdr structure, + * taking into account any necessary alignment. + * It takes the data length as an argument. + */ #define CMSG_LEN(length) (ALIGN_D(sizeof(struct cmsghdr)) + length) #endif @@ -345,8 +383,10 @@ struct cmsghdr { /** Generic sockaddr struct. Must be cast to proper type. */ struct sockaddr { - sa_family_t sa_family; + sa_family_t sa_family; /**< Address family */ +/** @cond INTERNAL_HIDDEN */ char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)]; +/** @endcond */ }; /** @cond INTERNAL_HIDDEN */ @@ -376,15 +416,30 @@ struct net_addr { }; }; +/** A pointer to IPv6 any address (all values zero) */ +extern const struct in6_addr in6addr_any; + +/** A pointer to IPv6 loopback address (::1) */ +extern const struct in6_addr in6addr_loopback; + +/** @endcond */ + +/** IPv6 address initializer */ #define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0 } } } + +/** IPv6 loopback address initializer */ #define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 1 } } } -extern const struct in6_addr in6addr_any; -extern const struct in6_addr in6addr_loopback; +/** IPv4 any address */ +#define INADDR_ANY 0 -/** @endcond */ +/** IPv4 address initializer */ +#define INADDR_ANY_INIT { { { INADDR_ANY } } } + +/** IPv6 loopback address initializer */ +#define INADDR_LOOPBACK_INIT { { { 127, 0, 0, 1 } } } /** Max length of the IPv4 address as a string. Defined by POSIX. */ #define INET_ADDRSTRLEN 16 @@ -399,13 +454,9 @@ extern const struct in6_addr in6addr_loopback; #define NET_IPV6_ADDR_LEN sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx") #define NET_IPV4_ADDR_LEN sizeof("xxx.xxx.xxx.xxx") -#define INADDR_ANY 0 -#define INADDR_ANY_INIT { { { INADDR_ANY } } } - -#define INADDR_LOOPBACK_INIT { { { 127, 0, 0, 1 } } } - /** @endcond */ +/** @brief IP Maximum Transfer Unit */ enum net_ip_mtu { /** IPv6 MTU length. We must be able to receive this size IPv6 packet * without fragmentation. @@ -422,7 +473,7 @@ enum net_ip_mtu { NET_IPV4_MTU = 576, }; -/** Network packet priority settings described in IEEE 802.1Q Annex I.1 */ +/** @brief Network packet priority settings described in IEEE 802.1Q Annex I.1 */ enum net_priority { NET_PRIORITY_BK = 1, /**< Background (lowest) */ NET_PRIORITY_BE = 0, /**< Best effort (default) */ @@ -434,9 +485,9 @@ enum net_priority { NET_PRIORITY_NC = 7 /**< Network control (highest) */ } __packed; -#define NET_MAX_PRIORITIES 8 /* How many priority values there are */ +#define NET_MAX_PRIORITIES 8 /**< How many priority values there are */ -/** IPv6/IPv4 network connection tuple */ +/** @brief IPv6/IPv4 network connection tuple */ struct net_tuple { struct net_addr *remote_addr; /**< IPv6/IPv4 remote address */ struct net_addr *local_addr; /**< IPv6/IPv4 local address */ @@ -445,7 +496,7 @@ struct net_tuple { enum net_ip_protocol ip_proto; /**< IP protocol */ }; -/** What is the current state of the network address */ +/** @brief What is the current state of the network address */ enum net_addr_state { NET_ADDR_ANY_STATE = -1, /**< Default (invalid) address type */ NET_ADDR_TENTATIVE = 0, /**< Tentative address */ @@ -453,7 +504,7 @@ enum net_addr_state { NET_ADDR_DEPRECATED, /**< Deprecated address */ } __packed; -/** How the network address is assigned to network interface */ +/** @brief How the network address is assigned to network interface */ enum net_addr_type { /** Default value. This is not a valid value. */ NET_ADDR_ANY = 0, From 4b0cfe1c02d41f3caf26826d7cdfbefc6e33d2b5 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1156/1389] net: doc: net_mgmt.h: Fix net_mgmt documentation Some documentation was missing in net_mgmt.h header file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_mgmt.h | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/net_mgmt.h b/include/zephyr/net/net_mgmt.h index f90bc8e1836464..55c65b122ec246 100644 --- a/include/zephyr/net/net_mgmt.h +++ b/include/zephyr/net/net_mgmt.h @@ -90,14 +90,33 @@ typedef int (*net_mgmt_request_handler_t)(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len); +/** + * @brief Generate a network management event. + * + * @param _mgmt_request Management event identifier + * @param _iface Network interface + * @param _data Any additional data for the event + * @param _len Length of the additional data. + */ #define net_mgmt(_mgmt_request, _iface, _data, _len) \ net_mgmt_##_mgmt_request(_mgmt_request, _iface, _data, _len) +/** + * @brief Declare a request handler function for the given network event. + * + * @param _mgmt_request Management event identifier + */ #define NET_MGMT_DEFINE_REQUEST_HANDLER(_mgmt_request) \ extern int net_mgmt_##_mgmt_request(uint32_t mgmt_request, \ struct net_if *iface, \ void *data, size_t len) +/** + * @brief Create a request handler function for the given network event. + * + * @param _mgmt_request Management event identifier + * @param _func Function for handling this event + */ #define NET_MGMT_REGISTER_REQUEST_HANDLER(_mgmt_request, _func) \ FUNC_ALIAS(_func, net_mgmt_##_mgmt_request, int) @@ -258,7 +277,7 @@ void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb); * @param mgmt_event The actual network event code to notify * @param iface a valid pointer on a struct net_if if only the event is * based on an iface. NULL otherwise. - * @param info a valid pointer on the information you want to pass along + * @param info A valid pointer on the information you want to pass along * with the event. NULL otherwise. Note the data pointed there is * normalized by the related event. * @param length size of the data pointed by info pointer. @@ -266,10 +285,20 @@ void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb); * Note: info and length are disabled if CONFIG_NET_MGMT_EVENT_INFO * is not defined. */ -#ifdef CONFIG_NET_MGMT_EVENT +#if defined(CONFIG_NET_MGMT_EVENT) void net_mgmt_event_notify_with_info(uint32_t mgmt_event, struct net_if *iface, const void *info, size_t length); +#else +#define net_mgmt_event_notify_with_info(...) +#endif +/** + * @brief Used by the system to notify an event without any additional information. + * @param mgmt_event The actual network event code to notify + * @param iface A valid pointer on a struct net_if if only the event is + * based on an iface. NULL otherwise. + */ +#if defined(CONFIG_NET_MGMT_EVENT) static inline void net_mgmt_event_notify(uint32_t mgmt_event, struct net_if *iface) { @@ -277,7 +306,6 @@ static inline void net_mgmt_event_notify(uint32_t mgmt_event, } #else #define net_mgmt_event_notify(...) -#define net_mgmt_event_notify_with_info(...) #endif /** From 60da01d86a6e4f795055d8d2fecbd7a9b3c84492 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1157/1389] net: doc: net_pkt.h: Improve net_pkt documenation Add more documentation to net_pkt.h Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_pkt.h | 103 ++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/net_pkt.h b/include/zephyr/net/net_pkt.h index 18eba376fe7251..4c5b592fde4ab6 100644 --- a/include/zephyr/net/net_pkt.h +++ b/include/zephyr/net/net_pkt.h @@ -46,6 +46,8 @@ extern "C" { struct net_context; +/** @cond INTERNAL_HIDDEN */ + /* buffer cursor used in net_pkt */ struct net_pkt_cursor { /** Current net_buf pointer by the cursor */ @@ -54,6 +56,8 @@ struct net_pkt_cursor { uint8_t *pos; }; +/** @endcond */ + /** * @brief Network packet. * @@ -72,8 +76,8 @@ struct net_pkt { /** buffer holding the packet */ union { - struct net_buf *frags; - struct net_buf *buffer; + struct net_buf *frags; /**< buffer fragment */ + struct net_buf *buffer; /**< alias to a buffer fragment */ }; /** Internal buffer iterator used for reading/writing */ @@ -1401,9 +1405,13 @@ static inline void net_pkt_set_remote_address(struct net_pkt *pkt, #define NET_PKT_SLAB_DEFINE(name, count) \ K_MEM_SLAB_DEFINE(name, sizeof(struct net_pkt), count, 4) +/** @cond INTERNAL_HIDDEN */ + /* Backward compatibility macro */ #define NET_PKT_TX_SLAB_DEFINE(name, count) NET_PKT_SLAB_DEFINE(name, count) +/** @endcond */ + /** * @brief Create a data fragment net_buf pool * @@ -1855,9 +1863,13 @@ struct net_pkt *net_pkt_rx_alloc(k_timeout_t timeout); struct net_pkt *net_pkt_alloc_on_iface(struct net_if *iface, k_timeout_t timeout); +/** @cond INTERNAL_HIDDEN */ + /* Same as above but specifically for RX packet */ struct net_pkt *net_pkt_rx_alloc_on_iface(struct net_if *iface, k_timeout_t timeout); +/** @endcond */ + #endif /** @@ -1918,12 +1930,17 @@ struct net_pkt *net_pkt_alloc_with_buffer(struct net_if *iface, enum net_ip_protocol proto, k_timeout_t timeout); +/** @cond INTERNAL_HIDDEN */ + /* Same as above but specifically for RX packet */ struct net_pkt *net_pkt_rx_alloc_with_buffer(struct net_if *iface, size_t size, sa_family_t family, enum net_ip_protocol proto, k_timeout_t timeout); + +/** @endcond */ + #endif /** @@ -2140,7 +2157,18 @@ struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, */ int net_pkt_read(struct net_pkt *pkt, void *data, size_t length); -/* Read uint8_t data data a net_pkt */ +/** + * @brief Read a byte (uint8_t) from a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The destination uint8_t where to copy the data + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_read_u8(struct net_pkt *pkt, uint8_t *data) { return net_pkt_read(pkt, data, 1); @@ -2203,13 +2231,35 @@ int net_pkt_read_be32(struct net_pkt *pkt, uint32_t *data); */ int net_pkt_write(struct net_pkt *pkt, const void *data, size_t length); -/* Write uint8_t data into a net_pkt. */ +/** + * @brief Write a byte (uint8_t) data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint8_t value to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_u8(struct net_pkt *pkt, uint8_t data) { return net_pkt_write(pkt, &data, sizeof(uint8_t)); } -/* Write uint16_t big endian data into a net_pkt. */ +/** + * @brief Write a uint16_t big endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint16_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_be16(struct net_pkt *pkt, uint16_t data) { uint16_t data_be16 = htons(data); @@ -2217,7 +2267,18 @@ static inline int net_pkt_write_be16(struct net_pkt *pkt, uint16_t data) return net_pkt_write(pkt, &data_be16, sizeof(uint16_t)); } -/* Write uint32_t big endian data into a net_pkt. */ +/** + * @brief Write a uint32_t big endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint32_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_be32(struct net_pkt *pkt, uint32_t data) { uint32_t data_be32 = htonl(data); @@ -2225,7 +2286,18 @@ static inline int net_pkt_write_be32(struct net_pkt *pkt, uint32_t data) return net_pkt_write(pkt, &data_be32, sizeof(uint32_t)); } -/* Write uint32_t little endian data into a net_pkt. */ +/** + * @brief Write a uint32_t little endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint32_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_le32(struct net_pkt *pkt, uint32_t data) { uint32_t data_le32 = sys_cpu_to_le32(data); @@ -2233,7 +2305,18 @@ static inline int net_pkt_write_le32(struct net_pkt *pkt, uint32_t data) return net_pkt_write(pkt, &data_le32, sizeof(uint32_t)); } -/* Write uint16_t little endian data into a net_pkt. */ +/** + * @brief Write a uint16_t little endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint16_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_le16(struct net_pkt *pkt, uint16_t data) { uint16_t data_le16 = sys_cpu_to_le16(data); @@ -2311,6 +2394,8 @@ bool net_pkt_is_contiguous(struct net_pkt *pkt, size_t size); */ size_t net_pkt_get_contiguous_len(struct net_pkt *pkt); +/** @cond INTERNAL_HIDDEN */ + struct net_pkt_data_access { #if !defined(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS) void *data; @@ -2343,6 +2428,8 @@ struct net_pkt_data_access { #endif /* CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS */ +/** @endcond */ + /** * @brief Get data from a network packet in a contiguous way * From e409ac674129e1ecb129abc2cea86d9dcd44667c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1158/1389] net: doc: net_pkt_filter.h: Improve documentation Add more documentation to net_pkt_filter.h header file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_pkt_filter.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/net_pkt_filter.h b/include/zephyr/net/net_pkt_filter.h index aa1ad89b0e619e..753ca347eb45c6 100644 --- a/include/zephyr/net/net_pkt_filter.h +++ b/include/zephyr/net/net_pkt_filter.h @@ -46,7 +46,7 @@ struct npf_test { /** @brief filter rule structure */ struct npf_rule { - sys_snode_t node; + sys_snode_t node; /**< Slist rule list node */ enum net_verdict result; /**< result if all tests pass */ uint32_t nb_tests; /**< number of tests for this rule */ struct npf_test *tests[]; /**< pointers to @ref npf_test instances */ @@ -59,8 +59,8 @@ extern struct npf_rule npf_default_drop; /** @brief rule set for a given test location */ struct npf_rule_list { - sys_slist_t rule_head; - struct k_spinlock lock; + sys_slist_t rule_head; /**< List head */ + struct k_spinlock lock; /**< Lock protecting the list access */ }; /** @brief rule list applied to outgoing packets */ @@ -107,6 +107,8 @@ bool npf_remove_rule(struct npf_rule_list *rules, struct npf_rule *rule); */ bool npf_remove_all_rules(struct npf_rule_list *rules); +/** @cond INTERNAL_HIDDEN */ + /* convenience shortcuts */ #define npf_insert_send_rule(rule) npf_insert_rule(&npf_send_rules, rule) #define npf_insert_recv_rule(rule) npf_insert_rule(&npf_recv_rules, rule) @@ -138,6 +140,8 @@ bool npf_remove_all_rules(struct npf_rule_list *rules); #define npf_remove_all_ipv6_recv_rules() npf_remove_all_rules(&npf_ipv6_recv_rules) #endif /* CONFIG_NET_PKT_FILTER_IPV6_HOOK */ +/** @endcond */ + /** * @brief Statically define one packet filter rule * From ae0d545de8541688074c629da1fd1d32039cc3cf Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1159/1389] net: doc: net_stats.h: Improve statistics documentation Lot of statistics variables were not documented at all. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_stats.h | 187 +++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 11 deletions(-) diff --git a/include/zephyr/net/net_stats.h b/include/zephyr/net/net_stats.h index f5a567fcdbc411..5a2ac84eaa2163 100644 --- a/include/zephyr/net/net_stats.h +++ b/include/zephyr/net/net_stats.h @@ -186,8 +186,13 @@ struct net_stats_udp { * @brief IPv6 neighbor discovery statistics */ struct net_stats_ipv6_nd { + /** Number of dropped IPv6 neighbor discovery packets. */ net_stats_t drop; + + /** Number of received IPv6 neighbor discovery packets. */ net_stats_t recv; + + /** Number of sent IPv6 neighbor discovery packets. */ net_stats_t sent; }; @@ -195,13 +200,13 @@ struct net_stats_ipv6_nd { * @brief IPv6 multicast listener daemon statistics */ struct net_stats_ipv6_mld { - /** Number of received IPv6 MLD queries */ + /** Number of received IPv6 MLD queries. */ net_stats_t recv; - /** Number of sent IPv6 MLD reports */ + /** Number of sent IPv6 MLD reports. */ net_stats_t sent; - /** Number of dropped IPv6 MLD packets */ + /** Number of dropped IPv6 MLD packets. */ net_stats_t drop; }; @@ -223,7 +228,10 @@ struct net_stats_ipv4_igmp { * @brief Network packet transfer times for calculating average TX time */ struct net_stats_tx_time { + /** Sum of network packet transfer times. */ uint64_t sum; + + /** Number of network packets transferred. */ net_stats_t count; }; @@ -231,10 +239,15 @@ struct net_stats_tx_time { * @brief Network packet receive times for calculating average RX time */ struct net_stats_rx_time { + /** Sum of network packet receive times. */ uint64_t sum; + + /** Number of network packets received. */ net_stats_t count; }; +/** @cond INTERNAL_HIDDEN */ + #if NET_TC_TX_COUNT == 0 #define NET_TC_TX_STATS_COUNT 1 #else @@ -247,29 +260,43 @@ struct net_stats_rx_time { #define NET_TC_RX_STATS_COUNT NET_TC_RX_COUNT #endif +/** @endcond */ + /** * @brief Traffic class statistics */ struct net_stats_tc { + /** TX statistics for each traffic class */ struct { + /** Helper for calculating average TX time statistics */ struct net_stats_tx_time tx_time; #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) + /** Detailed TX time statistics inside network stack */ struct net_stats_tx_time tx_time_detail[NET_PKT_DETAIL_STATS_COUNT]; #endif + /** Number of packets sent for this traffic class */ net_stats_t pkts; + /** Number of bytes sent for this traffic class */ net_stats_t bytes; + /** Priority of this traffic class */ uint8_t priority; } sent[NET_TC_TX_STATS_COUNT]; + /** RX statistics for each traffic class */ struct { + /** Helper for calculating average RX time statistics */ struct net_stats_rx_time rx_time; #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) + /** Detailed RX time statistics inside network stack */ struct net_stats_rx_time rx_time_detail[NET_PKT_DETAIL_STATS_COUNT]; #endif + /** Number of packets received for this traffic class */ net_stats_t pkts; + /** Number of bytes received for this traffic class */ net_stats_t bytes; + /** Priority of this traffic class */ uint8_t priority; } recv[NET_TC_RX_STATS_COUNT]; }; @@ -279,9 +306,13 @@ struct net_stats_tc { * @brief Power management statistics */ struct net_stats_pm { + /** Total suspend time */ uint64_t overall_suspend_time; + /** How many times we were suspended */ net_stats_t suspend_count; + /** How long the last suspend took */ uint32_t last_suspend_time; + /** Network interface last suspend start time */ uint32_t start_time; }; @@ -367,6 +398,7 @@ struct net_stats { #endif #if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) + /** Power management statistics */ struct net_stats_pm pm; #endif }; @@ -375,26 +407,61 @@ struct net_stats { * @brief Ethernet error statistics */ struct net_stats_eth_errors { + /** Number of RX length errors */ net_stats_t rx_length_errors; + + /** Number of RX overrun errors */ net_stats_t rx_over_errors; + + /** Number of RX CRC errors */ net_stats_t rx_crc_errors; + + /** Number of RX frame errors */ net_stats_t rx_frame_errors; + + /** Number of RX net_pkt allocation errors */ net_stats_t rx_no_buffer_count; + + /** Number of RX missed errors */ net_stats_t rx_missed_errors; + + /** Number of RX long length errors */ net_stats_t rx_long_length_errors; + + /** Number of RX short length errors */ net_stats_t rx_short_length_errors; + + /** Number of RX buffer align errors */ net_stats_t rx_align_errors; + + /** Number of RX DMA failed errors */ net_stats_t rx_dma_failed; + + /** Number of RX net_buf allocation errors */ net_stats_t rx_buf_alloc_failed; + /** Number of TX aborted errors */ net_stats_t tx_aborted_errors; + + /** Number of TX carrier errors */ net_stats_t tx_carrier_errors; + + /** Number of TX FIFO errors */ net_stats_t tx_fifo_errors; + + /** Number of TX heartbeat errors */ net_stats_t tx_heartbeat_errors; + + /** Number of TX window errors */ net_stats_t tx_window_errors; + + /** Number of TX DMA failed errors */ net_stats_t tx_dma_failed; + /** Number of uncorrected ECC errors */ net_stats_t uncorr_ecc_errors; + + /** Number of corrected ECC errors */ net_stats_t corr_ecc_errors; }; @@ -402,9 +469,16 @@ struct net_stats_eth_errors { * @brief Ethernet flow control statistics */ struct net_stats_eth_flow { + /** Number of RX XON flow control */ net_stats_t rx_flow_control_xon; + + /** Number of RX XOFF flow control */ net_stats_t rx_flow_control_xoff; + + /** Number of TX XON flow control */ net_stats_t tx_flow_control_xon; + + /** Number of TX XOFF flow control */ net_stats_t tx_flow_control_xoff; }; @@ -412,7 +486,10 @@ struct net_stats_eth_flow { * @brief Ethernet checksum statistics */ struct net_stats_eth_csum { + /** Number of good RX checksum offloading */ net_stats_t rx_csum_offload_good; + + /** Number of failed RX checksum offloading */ net_stats_t rx_csum_offload_errors; }; @@ -420,8 +497,13 @@ struct net_stats_eth_csum { * @brief Ethernet hardware timestamp statistics */ struct net_stats_eth_hw_timestamp { + /** Number of RX hardware timestamp cleared */ net_stats_t rx_hwtstamp_cleared; + + /** Number of RX hardware timestamp timeout */ net_stats_t tx_hwtstamp_timeouts; + + /** Number of RX hardware timestamp skipped */ net_stats_t tx_hwtstamp_skipped; }; @@ -430,8 +512,8 @@ struct net_stats_eth_hw_timestamp { * @brief Ethernet vendor specific statistics */ struct net_stats_eth_vendor { - const char * const key; - uint32_t value; + const char * const key; /**< Key name of vendor statistics */ + uint32_t value; /**< Value of the statistics key */ }; #endif @@ -439,20 +521,48 @@ struct net_stats_eth_vendor { * @brief All Ethernet specific statistics */ struct net_stats_eth { + /** Total number of bytes received and sent */ struct net_stats_bytes bytes; + + /** Total number of packets received and sent */ struct net_stats_pkts pkts; + + /** Total number of broadcast packets received and sent */ struct net_stats_pkts broadcast; + + /** Total number of multicast packets received and sent */ struct net_stats_pkts multicast; + + /** Total number of errors in RX and TX */ struct net_stats_pkts errors; + + /** Total number of errors in RX and TX */ struct net_stats_eth_errors error_details; + + /** Total number of flow control errors in RX and TX */ struct net_stats_eth_flow flow_control; + + /** Total number of checksum errors in RX and TX */ struct net_stats_eth_csum csum; + + /** Total number of hardware timestamp errors in RX and TX */ struct net_stats_eth_hw_timestamp hw_timestamp; + + /** Total number of collisions */ net_stats_t collisions; + + /** Total number of dropped TX packets */ net_stats_t tx_dropped; + + /** Total number of TX timeout errors */ net_stats_t tx_timeout_count; + + /** Total number of TX queue restarts */ net_stats_t tx_restart_queue; + + /** Total number of RX unknown protocol packets */ net_stats_t unknown_protocol; + #ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR /** Array is terminated with an entry containing a NULL key */ struct net_stats_eth_vendor *vendor; @@ -463,7 +573,10 @@ struct net_stats_eth { * @brief All PPP specific statistics */ struct net_stats_ppp { + /** Total number of bytes received and sent */ struct net_stats_bytes bytes; + + /** Total number of packets received and sent */ struct net_stats_pkts pkts; /** Number of received and dropped PPP frames. */ @@ -488,18 +601,33 @@ struct net_stats_sta_mgmt { * @brief All Wi-Fi specific statistics */ struct net_stats_wifi { + /** Total number of beacon errors */ struct net_stats_sta_mgmt sta_mgmt; + + /** Total number of bytes received and sent */ struct net_stats_bytes bytes; + + /** Total number of packets received and sent */ struct net_stats_pkts pkts; + + /** Total number of broadcast packets received and sent */ struct net_stats_pkts broadcast; + + /** Total number of multicast packets received and sent */ struct net_stats_pkts multicast; + + /** Total number of errors in RX and TX */ struct net_stats_pkts errors; + + /** Total number of unicast packets received and sent */ struct net_stats_pkts unicast; }; #if defined(CONFIG_NET_STATISTICS_USER_API) /* Management part definitions */ +/** @cond INTERNAL_HIDDEN */ + #define _NET_STATS_LAYER NET_MGMT_LAYER_L3 #define _NET_STATS_CODE 0x101 #define _NET_STATS_BASE (NET_MGMT_LAYER(_NET_STATS_LAYER) | \ @@ -522,96 +650,133 @@ enum net_request_stats_cmd { NET_REQUEST_STATS_CMD_GET_WIFI, }; +/** @endcond */ + +/** Request all network statistics */ #define NET_REQUEST_STATS_GET_ALL \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ALL) -NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ALL); - +/** Request all processing error statistics */ #define NET_REQUEST_STATS_GET_PROCESSING_ERROR \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR) -NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR); - +/** Request number of received and sent bytes */ #define NET_REQUEST_STATS_GET_BYTES \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_BYTES) -NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES); - +/** Request IP error statistics */ #define NET_REQUEST_STATS_GET_IP_ERRORS \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IP_ERRORS) +/** @cond INTERNAL_HIDDEN */ + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ALL); +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR); +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IP_ERRORS); +/** @endcond */ + #if defined(CONFIG_NET_STATISTICS_IPV4) +/** Request IPv4 statistics */ #define NET_REQUEST_STATS_GET_IPV4 \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV4) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV4); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_IPV4 */ #if defined(CONFIG_NET_STATISTICS_IPV6) +/** Request IPv6 statistics */ #define NET_REQUEST_STATS_GET_IPV6 \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV6) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_IPV6 */ #if defined(CONFIG_NET_STATISTICS_IPV6_ND) +/** Request IPv6 neighbor discovery statistics */ #define NET_REQUEST_STATS_GET_IPV6_ND \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV6_ND) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6_ND); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_IPV6_ND */ #if defined(CONFIG_NET_STATISTICS_ICMP) +/** Request ICMPv4 and ICMPv6 statistics */ #define NET_REQUEST_STATS_GET_ICMP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ICMP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ICMP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_ICMP */ #if defined(CONFIG_NET_STATISTICS_UDP) +/** Request UDP statistics */ #define NET_REQUEST_STATS_GET_UDP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_UDP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_UDP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_UDP */ #if defined(CONFIG_NET_STATISTICS_TCP) +/** Request TCP statistics */ #define NET_REQUEST_STATS_GET_TCP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_TCP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_TCP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_TCP */ #if defined(CONFIG_NET_STATISTICS_ETHERNET) +/** Request Ethernet statistics */ #define NET_REQUEST_STATS_GET_ETHERNET \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ETHERNET) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ETHERNET); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_ETHERNET */ #if defined(CONFIG_NET_STATISTICS_PPP) +/** Request PPP statistics */ #define NET_REQUEST_STATS_GET_PPP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PPP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PPP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_PPP */ #endif /* CONFIG_NET_STATISTICS_USER_API */ #if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) +/** Request network power management statistics */ #define NET_REQUEST_STATS_GET_PM \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PM) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PM); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_POWER_MANAGEMENT */ #if defined(CONFIG_NET_STATISTICS_WIFI) +/** Request Wi-Fi statistics */ #define NET_REQUEST_STATS_GET_WIFI \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_WIFI) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_WIFI); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_WIFI */ /** From aab52a1eef3294f9c79a3a6ed46264f424b30953 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1160/1389] net: doc: net_timeout.h: Fix doxygen comments Some of the already documented variables were missing proper doxygen comment. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_timeout.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/net_timeout.h b/include/zephyr/net/net_timeout.h index fb40ec93616014..87d312648f48ee 100644 --- a/include/zephyr/net/net_timeout.h +++ b/include/zephyr/net/net_timeout.h @@ -61,12 +61,13 @@ struct net_timeout { */ sys_snode_t node; - /* Time at which the timer was last set. + /** Time at which the timer was last set. * - * This usually corresponds to the low 32 bits of k_uptime_get(). */ + * This usually corresponds to the low 32 bits of k_uptime_get(). + */ uint32_t timer_start; - /* Portion of remaining timeout that does not exceed + /** Portion of remaining timeout that does not exceed * NET_TIMEOUT_MAX_VALUE. * * This value is updated in parallel with timer_start and wrap_counter @@ -74,7 +75,7 @@ struct net_timeout { */ uint32_t timer_timeout; - /* Timer wrap count. + /** Timer wrap count. * * This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that * have yet to pass. It is also updated along with timer_start and From eb189928cb4dc8bdfcc4912ea38c97a970bb8a3a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1161/1389] net: doc: offloaded_netdev.h: Fix doxygen comment The get_type API function was missing doxygen comment. Signed-off-by: Jukka Rissanen --- include/zephyr/net/offloaded_netdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/net/offloaded_netdev.h b/include/zephyr/net/offloaded_netdev.h index ce90cf77bf3750..009a0666515e0a 100644 --- a/include/zephyr/net/offloaded_netdev.h +++ b/include/zephyr/net/offloaded_netdev.h @@ -58,7 +58,7 @@ struct offloaded_if_api { /** Enable or disable the device (in response to admin state change) */ int (*enable)(const struct net_if *iface, bool state); - /* Types of offloaded net device */ + /** Types of offloaded net device */ enum offloaded_net_if_types (*get_type)(void); }; From eaaeee5eb07621fbf15e1c5bf9cb67e2eb239fc4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1162/1389] net: doc: openthread.h: Hide internal symbol No need to show internal symbols in generated documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/openthread.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/zephyr/net/openthread.h b/include/zephyr/net/openthread.h index 81c2629d6c0254..0d933df460f772 100644 --- a/include/zephyr/net/openthread.h +++ b/include/zephyr/net/openthread.h @@ -199,8 +199,12 @@ int openthread_api_mutex_try_lock(struct openthread_context *ot_context); */ void openthread_api_mutex_unlock(struct openthread_context *ot_context); +/** @cond INTERNAL_HIDDEN */ + #define OPENTHREAD_L2_CTX_TYPE struct openthread_context +/** @endcond */ + #ifdef __cplusplus } #endif From 3a67da961d8e95bf5e131bcff68e0ec64c574583 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1163/1389] net: doc: phy.h: Add missing documentation Couple of cabatility checking macros were missing documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/phy.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/zephyr/net/phy.h b/include/zephyr/net/phy.h index 38c6d1f5bbe715..160b31df23797f 100644 --- a/include/zephyr/net/phy.h +++ b/include/zephyr/net/phy.h @@ -42,8 +42,31 @@ enum phy_link_speed { LINK_FULL_1000BASE_T = BIT(5), }; +/** + * @brief Check if phy link is full duplex. + * + * @param x Link capabilities + * + * @return True if link is full duplex, false if not. + */ #define PHY_LINK_IS_FULL_DUPLEX(x) (x & (BIT(1) | BIT(3) | BIT(5))) + +/** + * @brief Check if phy link speed is 1 Gbit/sec. + * + * @param x Link capabilities + * + * @return True if link is 1 Gbit/sec, false if not. + */ #define PHY_LINK_IS_SPEED_1000M(x) (x & (BIT(4) | BIT(5))) + +/** + * @brief Check if phy link speed is 100 Mbit/sec. + * + * @param x Link capabilities + * + * @return True if link is 1 Mbit/sec, false if not. + */ #define PHY_LINK_IS_SPEED_100M(x) (x & (BIT(2) | BIT(3))) /** @brief Link state */ From eb9610e968fc1c3bbc50080b4452342f2ca6c457 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1164/1389] net: doc: ppp.h: Improve PPP documentation Some of the symbols in ppp.h were not documented. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ppp.h | 57 +++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/include/zephyr/net/ppp.h b/include/zephyr/net/ppp.h index 36c6bf64eebf31..da31eca01a18c0 100644 --- a/include/zephyr/net/ppp.h +++ b/include/zephyr/net/ppp.h @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief PPP (Point-to-Point Protocol) + */ #ifndef ZEPHYR_INCLUDE_NET_PPP_H_ #define ZEPHYR_INCLUDE_NET_PPP_H_ @@ -103,6 +107,8 @@ enum ppp_phase { PPP_TERMINATE, }; +/** @cond INTERNAL_HIDDEN */ + /** * PPP states, RFC 1661 ch. 4.2 */ @@ -136,10 +142,13 @@ enum ppp_packet_type { PPP_DISCARD_REQ = 11 }; +/** @endcond */ + /** * LCP option types from RFC 1661 ch. 6 */ enum lcp_option_type { + /** Reserved option value (do not use) */ LCP_OPTION_RESERVED = 0, /** Maximum-Receive-Unit */ @@ -168,6 +177,7 @@ enum lcp_option_type { * IPCP option types from RFC 1332 */ enum ipcp_option_type { + /** Reserved IPCP option value (do not use) */ IPCP_OPTION_RESERVED = 0, /** IP Addresses */ @@ -198,6 +208,7 @@ enum ipcp_option_type { * IPV6CP option types from RFC 5072 */ enum ipv6cp_option_type { + /** Reserved IPV6CP option value (do not use) */ IPV6CP_OPTION_RESERVED = 0, /** Interface identifier */ @@ -225,6 +236,7 @@ struct ppp_fsm { /** Timeout timer */ struct k_work_delayable timer; + /** FSM callbacks */ struct { /** Acknowledge Configuration Information */ int (*config_info_ack)(struct ppp_fsm *fsm, @@ -284,6 +296,7 @@ struct ppp_fsm { struct net_pkt *pkt); } cb; + /** My options */ struct { /** Options information */ const struct ppp_my_option_info *info; @@ -329,6 +342,8 @@ struct ppp_fsm { uint8_t ack_received : 1; }; +/** @cond INTERNAL_HIDDEN */ + #define PPP_MY_OPTION_ACKED BIT(0) #define PPP_MY_OPTION_REJECTED BIT(1) @@ -336,6 +351,16 @@ struct ppp_my_option_data { uint32_t flags; }; +#define IPCP_NUM_MY_OPTIONS 3 +#define IPV6CP_NUM_MY_OPTIONS 1 + +enum ppp_flags { + PPP_CARRIER_UP, +}; + +/** @endcond */ + +/** Link control protocol options */ struct lcp_options { /** Magic number */ uint32_t magic; @@ -354,26 +379,24 @@ struct lcp_options { #define LCP_NUM_MY_OPTIONS 1 #endif +/** IPv4 control protocol options */ struct ipcp_options { /** IPv4 address */ struct in_addr address; + + /** Primary DNS server address */ struct in_addr dns1_address; + + /** Secondary DNS server address */ struct in_addr dns2_address; }; -#define IPCP_NUM_MY_OPTIONS 3 - +/** IPv6 control protocol options */ struct ipv6cp_options { /** Interface identifier */ uint8_t iid[PPP_INTERFACE_IDENTIFIER_LEN]; }; -#define IPV6CP_NUM_MY_OPTIONS 1 - -enum ppp_flags { - PPP_CARRIER_UP, -}; - /** PPP L2 context specific to certain network interface */ struct ppp_context { /** Flags representing PPP state, which are accessed from multiple @@ -384,6 +407,7 @@ struct ppp_context { /** PPP startup worker. */ struct k_work_delayable startup; + /** LCP options */ struct { /** Finite state machine for LCP */ struct ppp_fsm fsm; @@ -402,6 +426,7 @@ struct ppp_context { } lcp; #if defined(CONFIG_NET_IPV4) + /** ICMP options */ struct { /** Finite state machine for IPCP */ struct ppp_fsm fsm; @@ -418,6 +443,7 @@ struct ppp_context { #endif #if defined(CONFIG_NET_IPV6) + /** IPV6CP options */ struct { /** Finite state machine for IPV6CP */ struct ppp_fsm fsm; @@ -434,6 +460,7 @@ struct ppp_context { #endif #if defined(CONFIG_NET_L2_PPP_PAP) + /** PAP options */ struct { /** Finite state machine for PAP */ struct ppp_fsm fsm; @@ -441,7 +468,9 @@ struct ppp_context { #endif #if defined(CONFIG_NET_SHELL) + /** Network shell PPP command internal data */ struct { + /** Ping command internal data */ struct { /** Callback to be called when Echo-Reply is received. */ @@ -544,22 +573,26 @@ enum net_event_ppp_cmd { NET_EVENT_PPP_CMD_PHASE_DEAD, }; +struct net_if; + +/** @endcond */ + +/** Event emitted when PPP carrier is on */ #define NET_EVENT_PPP_CARRIER_ON \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_ON) +/** Event emitted when PPP carrier is off */ #define NET_EVENT_PPP_CARRIER_OFF \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_OFF) +/** Event emitted when PPP goes into running phase */ #define NET_EVENT_PPP_PHASE_RUNNING \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_RUNNING) +/** Event emitted when PPP goes into dead phase */ #define NET_EVENT_PPP_PHASE_DEAD \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_DEAD) -struct net_if; - -/** @endcond */ - /** * @brief Raise CARRIER_ON event when PPP is connected. * From 49e601fdbf02ea8c8ee86280ea3d4dbbae42e269 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1165/1389] net: doc: ptp_time.h: Improve documentation Fix the documentation in ptp_time.h to improve the documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/ptp_time.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/zephyr/net/ptp_time.h b/include/zephyr/net/ptp_time.h index 99c5037e7ba0b2..269325cdde19da 100644 --- a/include/zephyr/net/ptp_time.h +++ b/include/zephyr/net/ptp_time.h @@ -109,6 +109,8 @@ extern "C" { struct net_ptp_time { /** Seconds encoded on 48 bits. */ union { + +/** @cond INTERNAL_HIDDEN */ struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; @@ -120,6 +122,9 @@ struct net_ptp_time { uint32_t low; #endif } _sec; +/** @endcond */ + + /** Second value. */ uint64_t second; }; @@ -147,6 +152,8 @@ struct net_ptp_time { struct net_ptp_extended_time { /** Seconds encoded on 48 bits. */ union { + +/** @cond INTERNAL_HIDDEN */ struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; @@ -158,11 +165,16 @@ struct net_ptp_extended_time { uint32_t low; #endif } _sec; +/** @endcond */ + + /** Second value. */ uint64_t second; }; /** Fractional nanoseconds on 48 bits. */ union { + +/** @cond INTERNAL_HIDDEN */ struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; @@ -174,6 +186,9 @@ struct net_ptp_extended_time { uint32_t low; #endif } _fns; +/** @endcond */ + + /** Fractional nanoseconds value. */ uint64_t fract_nsecond; }; } __packed; From 428023929d73d4fe068c60d9fdd8cc8424235aae Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1166/1389] net: doc: sntp.h: Improve documentation Fix doxygen documentation in sntp.h header file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/sntp.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/sntp.h b/include/zephyr/net/sntp.h index a1c8a59e0e8568..68a733d355d505 100644 --- a/include/zephyr/net/sntp.h +++ b/include/zephyr/net/sntp.h @@ -5,6 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief SNTP (Simple Network Time Protocol) + */ + #ifndef ZEPHYR_INCLUDE_NET_SNTP_H_ #define ZEPHYR_INCLUDE_NET_SNTP_H_ @@ -23,21 +28,24 @@ extern "C" { /** Time as returned by SNTP API, fractional seconds since 1 Jan 1970 */ struct sntp_time { - uint64_t seconds; - uint32_t fraction; + uint64_t seconds; /**< Second value */ + uint32_t fraction; /**< Fractional seconds value */ #if defined(CONFIG_SNTP_UNCERTAINTY) - uint64_t uptime_us; - uint32_t uncertainty_us; + uint64_t uptime_us; /**< Uptime in microseconds */ + uint32_t uncertainty_us; /**< Uncertainty in microseconds */ #endif }; /** SNTP context */ struct sntp_ctx { + +/** @cond INTERNAL_HIDDEN */ struct { struct zsock_pollfd fds[1]; int nfds; int fd; } sock; +/** @endcond */ /** Timestamp when the request was sent from client to server. * This is used to check if the originated timestamp in the server From 6d108a71b32dba3fedd3f242d4277fb089e9c3bc Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1167/1389] net: doc: socket.h: Hide internal documentation Some of the internal macros can be hidden from generated documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 54e534caf080b9..1ec1a9a12dfb4e 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -554,6 +554,8 @@ static inline ssize_t zsock_recv(int sock, void *buf, size_t max_len, */ __syscall int zsock_fcntl_impl(int sock, int cmd, int flags); +/** @cond INTERNAL_HIDDEN */ + /* * Need this wrapper because newer GCC versions got too smart and "typecheck" * even macros. @@ -571,6 +573,8 @@ static inline int zsock_fcntl_wrapper(int sock, int cmd, ...) #define zsock_fcntl zsock_fcntl_wrapper +/** @endcond */ + /** * @brief Control underlying socket parameters * @@ -590,6 +594,8 @@ static inline int zsock_fcntl_wrapper(int sock, int cmd, ...) */ __syscall int zsock_ioctl_impl(int sock, unsigned long request, va_list ap); +/** @cond INTERNAL_HIDDEN */ + static inline int zsock_ioctl_wrapper(int sock, unsigned long request, ...) { int ret; @@ -604,6 +610,8 @@ static inline int zsock_ioctl_wrapper(int sock, unsigned long request, ...) #define zsock_ioctl zsock_ioctl_wrapper +/** @endcond */ + /** * @brief Efficiently poll multiple sockets for events * From 422d2f699a1c56ccca80e236e9a9559bbd5bb80a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:29 +0200 Subject: [PATCH 1168/1389] net: doc: socket_net_mgmt.h: Hide internal docs No need to generate documentation for internal data. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket_net_mgmt.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/zephyr/net/socket_net_mgmt.h b/include/zephyr/net/socket_net_mgmt.h index c2c07a93b15c1e..3c173f96a6f6c7 100644 --- a/include/zephyr/net/socket_net_mgmt.h +++ b/include/zephyr/net/socket_net_mgmt.h @@ -29,6 +29,8 @@ extern "C" { * @{ */ +/** @cond INTERNAL_HIDDEN */ + /* Protocols of the protocol family PF_NET_MGMT */ #define NET_MGMT_EVENT_PROTO 0x01 @@ -36,6 +38,8 @@ extern "C" { #define SOL_NET_MGMT_BASE 100 #define SOL_NET_MGMT_RAW (SOL_NET_MGMT_BASE + 1) +/** @endcond */ + /** * struct sockaddr_nm - The sockaddr structure for NET_MGMT sockets * From aeed08c8bb39eac2dc13330da6ea0a6adb33eb72 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1169/1389] net: doc: socket_offload.h: Improve documentation Fix the socket_offload.h header file documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket_offload.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/zephyr/net/socket_offload.h b/include/zephyr/net/socket_offload.h index d0f2d29cfe4025..988d0fb686b348 100644 --- a/include/zephyr/net/socket_offload.h +++ b/include/zephyr/net/socket_offload.h @@ -26,9 +26,11 @@ extern "C" { * POSIX socket API standard for arguments, return values and setting of errno. */ struct socket_dns_offload { + /** DNS getaddrinfo offloaded implementation API */ int (*getaddrinfo)(const char *node, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res); + /** DNS freeaddrinfo offloaded implementation API */ void (*freeaddrinfo)(struct zsock_addrinfo *res); }; @@ -39,12 +41,16 @@ struct socket_dns_offload { */ void socket_offload_dns_register(const struct socket_dns_offload *ops); +/** @cond INTERNAL_HIDDEN */ + int socket_offload_getaddrinfo(const char *node, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res); void socket_offload_freeaddrinfo(struct zsock_addrinfo *res); +/** @endcond */ + #ifdef __cplusplus } #endif From 88beaec1d91d104dce1f4659ef7fda3483e5502b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1170/1389] net: doc: socket_select.h: Hide internal data from documentation No need to generate public documentation for internal data. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket_select.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/zephyr/net/socket_select.h b/include/zephyr/net/socket_select.h index 1e7507711a1188..d4cfef32cbcd9b 100644 --- a/include/zephyr/net/socket_select.h +++ b/include/zephyr/net/socket_select.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** @file socket_select.h + * + * @brief BSD select support functions. + */ + #ifndef ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_ #define ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_ @@ -21,10 +26,13 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + typedef struct zsock_fd_set { uint32_t bitset[(CONFIG_POSIX_MAX_FDS + 31) / 32]; } zsock_fd_set; +/** @endcond */ /** * @brief Legacy function to poll multiple sockets for events @@ -106,6 +114,8 @@ void ZSOCK_FD_CLR(int fd, zsock_fd_set *set); */ void ZSOCK_FD_SET(int fd, zsock_fd_set *set); +/** @cond INTERNAL_HIDDEN */ + #ifdef CONFIG_NET_SOCKETS_POSIX_NAMES #define fd_set zsock_fd_set @@ -140,6 +150,8 @@ static inline void FD_SET(int fd, zsock_fd_set *set) #endif /* CONFIG_NET_SOCKETS_POSIX_NAMES */ +/** @endcond */ + #ifdef __cplusplus } #endif From 3c8ed3fd96cdfd130bf76203b7198e85d9a047d7 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1171/1389] net: doc: socket_service.h: Hide internal documentation Do not add internal symbols to generated documentation. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket_service.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/zephyr/net/socket_service.h b/include/zephyr/net/socket_service.h index a4e21f00a33354..b1037bf07c3c3d 100644 --- a/include/zephyr/net/socket_service.h +++ b/include/zephyr/net/socket_service.h @@ -75,6 +75,8 @@ struct net_socket_service_desc { int *idx; }; +/** @cond INTERNAL_HIDDEN */ + #define __z_net_socket_svc_get_name(_svc_id) __z_net_socket_service_##_svc_id #define __z_net_socket_svc_get_idx(_svc_id) __z_net_socket_service_idx_##_svc_id #define __z_net_socket_svc_get_owner __FILE__ ":" STRINGIFY(__LINE__) @@ -110,6 +112,8 @@ extern void net_socket_service_callback(struct k_work *work); .idx = &__z_net_socket_svc_get_idx(_name), \ } +/** @endcond */ + /** * @brief Statically define a network socket service. * The user callback is called asynchronously for this service meaning that From ae0084ac42c438f289e9fd213ae57fac3cc8cf6e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1172/1389] net: doc: socket_types.h: Hide internal data from documentation No need to generate documentation for internal data. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket_types.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/zephyr/net/socket_types.h b/include/zephyr/net/socket_types.h index 6195315e51acae..0727dd77bdf318 100644 --- a/include/zephyr/net/socket_types.h +++ b/include/zephyr/net/socket_types.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief socket types definitionis + */ + #ifndef ZEPHYR_INCLUDE_NET_SOCKET_TYPES_H_ #define ZEPHYR_INCLUDE_NET_SOCKET_TYPES_H_ @@ -16,6 +21,7 @@ #include +/** @cond INTERNAL_HIDDEN */ #ifdef CONFIG_NEWLIB_LIBC @@ -52,6 +58,8 @@ extern "C" { } #endif +/** @endcond */ + /** * @} */ From d069ffc147fbd55bbd508edce96a13c19200ff6b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1173/1389] net: doc: socketcan.h: Improve documentation Add missing doxygen documentation to socketcan.h header file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socketcan.h | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/include/zephyr/net/socketcan.h b/include/zephyr/net/socketcan.h index c4916487d9971b..dd2a7049288d75 100644 --- a/include/zephyr/net/socketcan.h +++ b/include/zephyr/net/socketcan.h @@ -28,9 +28,11 @@ extern "C" { * @{ */ -/* Protocols of the protocol family PF_CAN */ +/** Protocols of the protocol family PF_CAN */ #define CAN_RAW 1 +/** @cond INTERNAL_HIDDEN */ + /* SocketCAN options */ #define SOL_CAN_BASE 100 #define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW) @@ -39,28 +41,35 @@ enum { CAN_RAW_FILTER = 1, }; +/** @endcond */ + /* SocketCAN MTU size compatible with Linux */ #ifdef CONFIG_CAN_FD_MODE +/** SocketCAN max data length */ #define SOCKETCAN_MAX_DLEN 64U +/** CAN FD frame MTU */ #define CANFD_MTU (sizeof(struct socketcan_frame)) +/** CAN frame MTU */ #define CAN_MTU (CANFD_MTU - 56U) #else /* CONFIG_CAN_FD_MODE */ +/** SocketCAN max data length */ #define SOCKETCAN_MAX_DLEN 8U +/** CAN frame MTU */ #define CAN_MTU (sizeof(struct socketcan_frame)) #endif /* !CONFIG_CAN_FD_MODE */ /* CAN FD specific flags from Linux Kernel (include/uapi/linux/can.h) */ -#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ -#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ -#define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */ +#define CANFD_BRS 0x01 /**< Bit rate switch (second bitrate for payload data) */ +#define CANFD_ESI 0x02 /**< Error state indicator of the transmitting node */ +#define CANFD_FDF 0x04 /**< Mark CAN FD for dual use of struct canfd_frame */ /** * struct sockaddr_can - The sockaddr structure for CAN sockets * */ struct sockaddr_can { - sa_family_t can_family; - int can_ifindex; + sa_family_t can_family; /**< Address family */ + int can_ifindex; /**< SocketCAN network interface index */ }; /** From c6d9caae627dc4bd24272a5087b3a60ed9625014 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1174/1389] net: doc: socketutils.h: Add missing @file section This will improve documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/socketutils.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/zephyr/net/socketutils.h b/include/zephyr/net/socketutils.h index 7a7b862a7a707f..b118f7531d9cec 100644 --- a/include/zephyr/net/socketutils.h +++ b/include/zephyr/net/socketutils.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Socket utility functions. + */ + #ifndef ZEPHYR_INCLUDE_NET_SOCKETUTILS_H_ #define ZEPHYR_INCLUDE_NET_SOCKETUTILS_H_ From ae06c7d4eb2238042964d93ac2f464befa0ce13b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1175/1389] net: doc: tftp.h: Fix the @file section The @brief was in wrong place. Signed-off-by: Jukka Rissanen --- include/zephyr/net/tftp.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/tftp.h b/include/zephyr/net/tftp.h index 61db441e54843e..eb3df0cc0c1d2f 100644 --- a/include/zephyr/net/tftp.h +++ b/include/zephyr/net/tftp.h @@ -5,11 +5,12 @@ */ /** @file tftp.h + * + * @brief TFTP Client Implementation * * @defgroup tftp_client TFTP Client library * @ingroup networking * @{ - * @brief TFTP Client Implementation */ #ifndef ZEPHYR_INCLUDE_NET_TFTP_H_ From 3f326eb8d95b09ff864a6b3365ad681c295517db Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1176/1389] net: doc: trickle.h: Add missing doxygen comments The trickle.h was missing couple of doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/trickle.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/zephyr/net/trickle.h b/include/zephyr/net/trickle.h index fb6ee8f74be881..9d46ffa0b91ffe 100644 --- a/include/zephyr/net/trickle.h +++ b/include/zephyr/net/trickle.h @@ -60,11 +60,11 @@ struct net_trickle { uint8_t k; /**< Redundancy constant */ uint8_t c; /**< Consistency counter */ - bool double_to; + bool double_to; /**< Flag telling if the internval is doubled */ - struct k_work_delayable timer; + struct k_work_delayable timer; /**< Internal timer struct */ net_trickle_cb_t cb; /**< Callback to be called when timer expires */ - void *user_data; + void *user_data; /**< User specific opaque data */ }; /** @cond INTERNAL_HIDDEN */ From 88e21001dc0b4e7c2e47b388ac7e2a1ecb7749e7 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1177/1389] net: doc: virtual.h: Add missing doxygen comment The virtual API was not properly documented. Signed-off-by: Jukka Rissanen --- include/zephyr/net/virtual.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/zephyr/net/virtual.h b/include/zephyr/net/virtual.h index d64bab155772b5..806665296f9258 100644 --- a/include/zephyr/net/virtual.h +++ b/include/zephyr/net/virtual.h @@ -81,6 +81,7 @@ struct virtual_interface_config { #endif /** @endcond */ +/** Virtual L2 API operations. */ struct virtual_interface_api { /** * The net_if_api must be placed in first position in this From d7df93afdf552c6d2085b93acf034b97dd59a2a8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1178/1389] net: doc: websocket.h: Add missing doxygen comments Opcodes were not documented. Also removed init function from public documentation as it is not needed there. Signed-off-by: Jukka Rissanen --- include/zephyr/net/websocket.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/include/zephyr/net/websocket.h b/include/zephyr/net/websocket.h index 606957e9fd57af..3b2d9dddd678b8 100644 --- a/include/zephyr/net/websocket.h +++ b/include/zephyr/net/websocket.h @@ -38,13 +38,14 @@ extern "C" { #define WEBSOCKET_FLAG_PING 0x00000010 /**< Ping message */ #define WEBSOCKET_FLAG_PONG 0x00000020 /**< Pong message */ +/** @brief Websocket option codes */ enum websocket_opcode { - WEBSOCKET_OPCODE_CONTINUE = 0x00, - WEBSOCKET_OPCODE_DATA_TEXT = 0x01, - WEBSOCKET_OPCODE_DATA_BINARY = 0x02, - WEBSOCKET_OPCODE_CLOSE = 0x08, - WEBSOCKET_OPCODE_PING = 0x09, - WEBSOCKET_OPCODE_PONG = 0x0A, + WEBSOCKET_OPCODE_CONTINUE = 0x00, /**< Message continues */ + WEBSOCKET_OPCODE_DATA_TEXT = 0x01, /**< Textual data */ + WEBSOCKET_OPCODE_DATA_BINARY = 0x02, /**< Binary data */ + WEBSOCKET_OPCODE_CLOSE = 0x08, /**< Closing connection */ + WEBSOCKET_OPCODE_PING = 0x09, /**< Ping message */ + WEBSOCKET_OPCODE_PONG = 0x0A, /**< Pong message */ }; /** @@ -212,6 +213,8 @@ int websocket_register(int http_sock, uint8_t *recv_buf, size_t recv_buf_len); */ int websocket_unregister(int ws_sock); +/** @cond INTERNAL_HIDDEN */ + #if defined(CONFIG_WEBSOCKET_CLIENT) void websocket_init(void); #else @@ -220,6 +223,8 @@ static inline void websocket_init(void) } #endif +/** @endcond */ + #ifdef __cplusplus } #endif From e264a3d5aac2f471e35f4474ac50062ec52c857c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1179/1389] net: doc: wifi.h: Improve documentation Add missing doxygen comments and improve documentation coverage. Signed-off-by: Jukka Rissanen --- include/zephyr/net/wifi.h | 64 +++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index ebfc76d2192d10..5f47209b83fc61 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -22,16 +22,21 @@ #include /* for ARRAY_SIZE */ +/** Length of the country code string */ #define WIFI_COUNTRY_CODE_LEN 2 +/** @cond INTERNAL_HIDDEN */ + #define WIFI_LISTEN_INTERVAL_MIN 0 #define WIFI_LISTEN_INTERVAL_MAX 65535 +/** @endcond */ + #ifdef __cplusplus extern "C" { #endif -/** IEEE 802.11 security types. */ +/** @brief IEEE 802.11 security types. */ enum wifi_security_type { /** No security. */ WIFI_SECURITY_TYPE_NONE = 0, @@ -52,15 +57,17 @@ enum wifi_security_type { /** WPA/WPA2/WPA3 PSK security. */ WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL, +/** @cond INTERNAL_HIDDEN */ __WIFI_SECURITY_TYPE_AFTER_LAST, WIFI_SECURITY_TYPE_MAX = __WIFI_SECURITY_TYPE_AFTER_LAST - 1, WIFI_SECURITY_TYPE_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly security type name. */ const char *wifi_security_txt(enum wifi_security_type security); -/** IEEE 802.11w - Management frame protection. */ +/** @brief IEEE 802.11w - Management frame protection. */ enum wifi_mfp_options { /** MFP disabled. */ WIFI_MFP_DISABLE = 0, @@ -69,9 +76,11 @@ enum wifi_mfp_options { /** MFP required. */ WIFI_MFP_REQUIRED, +/** @cond INTERNAL_HIDDEN */ __WIFI_MFP_AFTER_LAST, WIFI_MFP_MAX = __WIFI_MFP_AFTER_LAST - 1, WIFI_MFP_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly MFP name.*/ @@ -99,17 +108,25 @@ enum wifi_frequency_bands { /** Helper function to get user-friendly frequency band name. */ const char *wifi_band_txt(enum wifi_frequency_bands band); +/** Max SSID length */ #define WIFI_SSID_MAX_LEN 32 +/** Minimum PSK length */ #define WIFI_PSK_MIN_LEN 8 +/** Maximum PSK length */ #define WIFI_PSK_MAX_LEN 64 +/** Max SAW password length */ #define WIFI_SAE_PSWD_MAX_LEN 128 +/** MAC address length */ #define WIFI_MAC_ADDR_LEN 6 +/** Minimum channel number */ #define WIFI_CHANNEL_MIN 1 +/** Maximum channel number */ #define WIFI_CHANNEL_MAX 233 +/** Any channel number */ #define WIFI_CHANNEL_ANY 255 -/** Wi-Fi interface states. +/** @brief Wi-Fi interface states. * * Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc */ @@ -135,9 +152,11 @@ enum wifi_iface_state { /** All authentication completed, ready to pass data. */ WIFI_STATE_COMPLETED, +/** @cond INTERNAL_HIDDEN */ __WIFI_STATE_AFTER_LAST, WIFI_STATE_MAX = __WIFI_STATE_AFTER_LAST - 1, WIFI_STATE_UNKNOWN +/** @endcond */ }; /* We rely on the strict order of the enum values, so, let's check it */ @@ -155,7 +174,7 @@ BUILD_ASSERT(WIFI_STATE_DISCONNECTED < WIFI_STATE_INTERFACE_DISABLED && /** Helper function to get user-friendly interface state name. */ const char *wifi_state_txt(enum wifi_iface_state state); -/** Wi-Fi interface modes. +/** @brief Wi-Fi interface modes. * * Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc */ @@ -173,15 +192,17 @@ enum wifi_iface_mode { /** 802.11s Mesh mode. */ WIFI_MODE_MESH = 5, +/** @cond INTERNAL_HIDDEN */ __WIFI_MODE_AFTER_LAST, WIFI_MODE_MAX = __WIFI_MODE_AFTER_LAST - 1, WIFI_MODE_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly interface mode name. */ const char *wifi_mode_txt(enum wifi_iface_mode mode); -/** Wi-Fi link operating modes +/** @brief Wi-Fi link operating modes * * As per https://en.wikipedia.org/wiki/Wi-Fi#Versions_and_generations. */ @@ -205,15 +226,17 @@ enum wifi_link_mode { /** 802.11be. */ WIFI_7, +/** @cond INTERNAL_HIDDEN */ __WIFI_LINK_MODE_AFTER_LAST, WIFI_LINK_MODE_MAX = __WIFI_LINK_MODE_AFTER_LAST - 1, WIFI_LINK_MODE_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly link mode name. */ const char *wifi_link_mode_txt(enum wifi_link_mode link_mode); -/** Wi-Fi scanning types. */ +/** @brief Wi-Fi scanning types. */ enum wifi_scan_type { /** Active scanning (default). */ WIFI_SCAN_TYPE_ACTIVE = 0, @@ -221,7 +244,7 @@ enum wifi_scan_type { WIFI_SCAN_TYPE_PASSIVE, }; -/** Wi-Fi power save states. */ +/** @brief Wi-Fi power save states. */ enum wifi_ps { /** Power save disabled. */ WIFI_PS_DISABLED = 0, @@ -232,7 +255,7 @@ enum wifi_ps { /** Helper function to get user-friendly ps name. */ const char *wifi_ps_txt(enum wifi_ps ps_name); -/** Wi-Fi power save modes. */ +/** @brief Wi-Fi power save modes. */ enum wifi_ps_mode { /** Legacy power save mode. */ WIFI_PS_MODE_LEGACY = 0, @@ -246,11 +269,12 @@ enum wifi_ps_mode { /** Helper function to get user-friendly ps mode name. */ const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode); -/* Interface index Min and Max values */ +/** Network interface index min value */ #define WIFI_INTERFACE_INDEX_MIN 1 +/** Network interface index max value */ #define WIFI_INTERFACE_INDEX_MAX 255 -/** Wifi operational mode */ +/** @brief Wifi operational mode */ enum wifi_operational_modes { /** STA mode setting enable */ WIFI_STA_MODE = BIT(0), @@ -266,7 +290,7 @@ enum wifi_operational_modes { WIFI_SOFTAP_MODE = BIT(5), }; -/** Mode filter settings */ +/** @brief Mode filter settings */ enum wifi_filter { /** Support management, data and control packet sniffing */ WIFI_PACKET_FILTER_ALL = BIT(0), @@ -278,7 +302,7 @@ enum wifi_filter { WIFI_PACKET_FILTER_CTRL = BIT(3), }; -/** Wi-Fi Target Wake Time (TWT) operations. */ +/** @brief Wi-Fi Target Wake Time (TWT) operations. */ enum wifi_twt_operation { /** TWT setup operation */ WIFI_TWT_SETUP = 0, @@ -289,7 +313,7 @@ enum wifi_twt_operation { /** Helper function to get user-friendly twt operation name. */ const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation); -/** Wi-Fi Target Wake Time (TWT) negotiation types. */ +/** @brief Wi-Fi Target Wake Time (TWT) negotiation types. */ enum wifi_twt_negotiation_type { /** TWT individual negotiation */ WIFI_TWT_INDIVIDUAL = 0, @@ -302,7 +326,7 @@ enum wifi_twt_negotiation_type { /** Helper function to get user-friendly twt negotiation type name. */ const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation); -/** Wi-Fi Target Wake Time (TWT) setup commands. */ +/** @brief Wi-Fi Target Wake Time (TWT) setup commands. */ enum wifi_twt_setup_cmd { /** TWT setup request */ WIFI_TWT_SETUP_CMD_REQUEST = 0, @@ -325,7 +349,7 @@ enum wifi_twt_setup_cmd { /** Helper function to get user-friendly twt setup cmd name. */ const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup); -/** Wi-Fi Target Wake Time (TWT) negotiation status. */ +/** @brief Wi-Fi Target Wake Time (TWT) negotiation status. */ enum wifi_twt_setup_resp_status { /** TWT response received for TWT request */ WIFI_TWT_RESP_RECEIVED = 0, @@ -333,7 +357,7 @@ enum wifi_twt_setup_resp_status { WIFI_TWT_RESP_NOT_RECEIVED, }; -/** Target Wake Time (TWT) error codes. */ +/** @brief Target Wake Time (TWT) error codes. */ enum wifi_twt_fail_reason { /** Unspecified error */ WIFI_TWT_FAIL_UNSPECIFIED, @@ -359,7 +383,7 @@ enum wifi_twt_fail_reason { WIFI_TWT_FAIL_FLOW_ALREADY_EXISTS, }; -/** Wi-Fi Target Wake Time (TWT) teradown status. */ +/** @brief Wi-Fi Target Wake Time (TWT) teradown status. */ enum wifi_twt_teardown_status { /** TWT teardown success */ WIFI_TWT_TEARDOWN_SUCCESS = 0, @@ -400,7 +424,7 @@ static inline const char *wifi_twt_get_err_code_str(int16_t err_no) return ""; } -/** Wi-Fi power save parameters. */ +/** @brief Wi-Fi power save parameters. */ enum wifi_ps_param_type { /** Power save state. */ WIFI_PS_PARAM_STATE, @@ -414,7 +438,7 @@ enum wifi_ps_param_type { WIFI_PS_PARAM_TIMEOUT, }; -/** Wi-Fi power save modes. */ +/** @brief Wi-Fi power save modes. */ enum wifi_ps_wakeup_mode { /** DTIM based wakeup. */ WIFI_PS_WAKEUP_MODE_DTIM = 0, @@ -425,7 +449,7 @@ enum wifi_ps_wakeup_mode { /** Helper function to get user-friendly ps wakeup mode name. */ const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); -/** Wi-Fi power save error codes. */ +/** @brief Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { /** Unspecified error */ WIFI_PS_PARAM_FAIL_UNSPECIFIED, From f98859f612c983538917f5c272ccc39360297d28 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1180/1389] net: doc: wifi_mgmt.h: Improve documentation Add missing doxygen comments for wifi_mgmt.h header file. Signed-off-by: Jukka Rissanen --- include/zephyr/net/wifi_mgmt.h | 123 +++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 36 deletions(-) diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 70fd5978fba67f..0442a91c2f2fba 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -28,6 +28,8 @@ extern "C" { /* Management part definitions */ +/** @cond INTERNAL_HIDDEN */ + #define _NET_WIFI_LAYER NET_MGMT_LAYER_L2 #define _NET_WIFI_CODE 0x156 #define _NET_WIFI_BASE (NET_MGMT_IFACE_BIT | \ @@ -50,7 +52,9 @@ extern "C" { #define WIFI_MGMT_BAND_STR_SIZE_MAX 8 #define WIFI_MGMT_SCAN_MAX_BSS_CNT 65535 -/** Wi-Fi management commands */ +/** @endcond */ + +/** @brief Wi-Fi management commands */ enum net_request_wifi_cmd { /** Scan for Wi-Fi networks */ NET_REQUEST_WIFI_CMD_SCAN = 1, @@ -84,88 +88,109 @@ enum net_request_wifi_cmd { NET_REQUEST_WIFI_CMD_VERSION, /** Set RTS threshold */ NET_REQUEST_WIFI_CMD_RTS_THRESHOLD, + +/** @cond INTERNAL_HIDDEN */ NET_REQUEST_WIFI_CMD_MAX +/** @endcond */ }; +/** Request a Wi-Fi scan */ #define NET_REQUEST_WIFI_SCAN \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_SCAN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN); +/** Request a Wi-Fi connect */ #define NET_REQUEST_WIFI_CONNECT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_CONNECT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT); +/** Request a Wi-Fi disconnect */ #define NET_REQUEST_WIFI_DISCONNECT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_DISCONNECT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT); +/** Request a Wi-Fi access point enable */ #define NET_REQUEST_WIFI_AP_ENABLE \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_ENABLE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE); +/** Request a Wi-Fi access point disable */ #define NET_REQUEST_WIFI_AP_DISABLE \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_DISABLE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE); +/** Request a Wi-Fi network interface status */ #define NET_REQUEST_WIFI_IFACE_STATUS \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_IFACE_STATUS) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS); -#define NET_REQUEST_WIFI_PS \ +/** Request a Wi-Fi power save */ +#define NET_REQUEST_WIFI_PS \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PS) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS); -#define NET_REQUEST_WIFI_TWT \ +/** Request a Wi-Fi TWT */ +#define NET_REQUEST_WIFI_TWT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_TWT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT); +/** Request a Wi-Fi power save configuration */ #define NET_REQUEST_WIFI_PS_CONFIG \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PS_CONFIG) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG); + +/** Request a Wi-Fi regulatory domain */ #define NET_REQUEST_WIFI_REG_DOMAIN \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_REG_DOMAIN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN); -#define NET_REQUEST_WIFI_MODE \ +/** Request current Wi-Fi mode */ +#define NET_REQUEST_WIFI_MODE \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_MODE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE); -#define NET_REQUEST_WIFI_PACKET_FILTER \ +/** Request Wi-Fi packet filter */ +#define NET_REQUEST_WIFI_PACKET_FILTER \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PACKET_FILTER) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER); -#define NET_REQUEST_WIFI_CHANNEL \ +/** Request a Wi-Fi channel */ +#define NET_REQUEST_WIFI_CHANNEL \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_CHANNEL) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL); +/** Request a Wi-Fi access point to disconnect a station */ #define NET_REQUEST_WIFI_AP_STA_DISCONNECT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_STA_DISCONNECT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_STA_DISCONNECT); -#define NET_REQUEST_WIFI_VERSION \ +/** Request a Wi-Fi version */ +#define NET_REQUEST_WIFI_VERSION \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_VERSION) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_VERSION); -#define NET_REQUEST_WIFI_RTS_THRESHOLD \ +/** Request a Wi-Fi RTS threashold */ +#define NET_REQUEST_WIFI_RTS_THRESHOLD \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_RTS_THRESHOLD) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD); -/** Wi-Fi management events */ + +/** @brief Wi-Fi management events */ enum net_event_wifi_cmd { /** Scan results available */ NET_EVENT_WIFI_CMD_SCAN_RESULT = 1, @@ -197,46 +222,59 @@ enum net_event_wifi_cmd { NET_EVENT_WIFI_CMD_AP_STA_DISCONNECTED, }; +/** Event emitted for Wi-Fi scan result */ #define NET_EVENT_WIFI_SCAN_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_SCAN_RESULT) +/** Event emitted when Wi-Fi scan is done */ #define NET_EVENT_WIFI_SCAN_DONE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_SCAN_DONE) +/** Event emitted for Wi-Fi connect result */ #define NET_EVENT_WIFI_CONNECT_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_CONNECT_RESULT) +/** Event emitted for Wi-Fi disconnect result */ #define NET_EVENT_WIFI_DISCONNECT_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_RESULT) -#define NET_EVENT_WIFI_IFACE_STATUS \ +/** Event emitted for Wi-Fi network interface status */ +#define NET_EVENT_WIFI_IFACE_STATUS \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_IFACE_STATUS) +/** Event emitted for Wi-Fi TWT information */ #define NET_EVENT_WIFI_TWT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_TWT) +/** Event emitted for Wi-Fi TWT sleep state */ #define NET_EVENT_WIFI_TWT_SLEEP_STATE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_TWT_SLEEP_STATE) +/** Event emitted for Wi-Fi raw scan result */ #define NET_EVENT_WIFI_RAW_SCAN_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_RAW_SCAN_RESULT) +/** Event emitted Wi-Fi disconnect is completed */ #define NET_EVENT_WIFI_DISCONNECT_COMPLETE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_COMPLETE) +/** Event emitted for Wi-Fi access point enable result */ #define NET_EVENT_WIFI_AP_ENABLE_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_ENABLE_RESULT) +/** Event emitted for Wi-Fi access point disable result */ #define NET_EVENT_WIFI_AP_DISABLE_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT) +/** Event emitted when Wi-Fi station is connected in AP mode */ #define NET_EVENT_WIFI_AP_STA_CONNECTED \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_STA_CONNECTED) +/** Event emitted Wi-Fi station is disconnected from AP */ #define NET_EVENT_WIFI_AP_STA_DISCONNECTED \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_STA_DISCONNECTED) -/** Wi-Fi version */ +/** @brief Wi-Fi version */ struct wifi_version { /** Driver version */ const char *drv_version; @@ -306,7 +344,7 @@ struct wifi_scan_params { struct wifi_band_channel band_chan[WIFI_MGMT_SCAN_CHAN_MAX_MANUAL]; }; -/** Wi-Fi scan result, each result is provided to the net_mgmt_event_callback +/** @brief Wi-Fi scan result, each result is provided to the net_mgmt_event_callback * via its info attribute (see net_mgmt.h) */ struct wifi_scan_result { @@ -330,7 +368,7 @@ struct wifi_scan_result { uint8_t mac_length; }; -/** Wi-Fi connect request parameters */ +/** @brief Wi-Fi connect request parameters */ struct wifi_connect_req_params { /** SSID */ const uint8_t *ssid; @@ -358,7 +396,7 @@ struct wifi_connect_req_params { int timeout; }; -/** Wi-Fi connect result codes. To be overlaid on top of \ref wifi_status +/** @brief Wi-Fi connect result codes. To be overlaid on top of \ref wifi_status * in the connect result event for detailed status. */ enum wifi_conn_status { @@ -385,7 +423,7 @@ enum wifi_conn_status { WIFI_STATUS_DISCONN_FIRST_STATUS = WIFI_STATUS_CONN_LAST_STATUS, }; -/** Wi-Fi disconnect reason codes. To be overlaid on top of \ref wifi_status +/** @brief Wi-Fi disconnect reason codes. To be overlaid on top of \ref wifi_status * in the disconnect result event for detailed reason. */ enum wifi_disconn_reason { @@ -399,7 +437,7 @@ enum wifi_disconn_reason { WIFI_REASON_DISCONN_INACTIVITY, }; -/** Wi-Fi AP mode result codes. To be overlaid on top of \ref wifi_status +/** @brief Wi-Fi AP mode result codes. To be overlaid on top of \ref wifi_status * in the AP mode enable or disable result event for detailed status. */ enum wifi_ap_status { @@ -421,17 +459,21 @@ enum wifi_ap_status { WIFI_STATUS_AP_OP_NOT_PERMITTED, }; -/** Generic Wi-Fi status for commands and events */ +/** @brief Generic Wi-Fi status for commands and events */ struct wifi_status { union { + /** Status value */ int status; + /** Connection status */ enum wifi_conn_status conn_status; + /** Disconnection reason status */ enum wifi_disconn_reason disconn_reason; + /** Access point status */ enum wifi_ap_status ap_status; }; }; -/** Wi-Fi interface status */ +/** @brief Wi-Fi interface status */ struct wifi_iface_status { /** Interface state, see enum wifi_iface_state */ int state; @@ -463,11 +505,11 @@ struct wifi_iface_status { bool twt_capable; }; -/** Wi-Fi power save parameters */ +/** @brief Wi-Fi power save parameters */ struct wifi_ps_params { - /* Power save state */ + /** Power save state */ enum wifi_ps enabled; - /* Listen interval */ + /** Listen interval */ unsigned short listen_interval; /** Wi-Fi power save wakeup mode */ enum wifi_ps_wakeup_mode wakeup_mode; @@ -488,7 +530,7 @@ struct wifi_ps_params { enum wifi_config_ps_param_fail_reason fail_reason; }; -/** Wi-Fi TWT parameters */ +/** @brief Wi-Fi TWT parameters */ struct wifi_twt_params { /** TWT operation, see enum wifi_twt_operation */ enum wifi_twt_operation operation; @@ -519,7 +561,7 @@ struct wifi_twt_params { bool announce; /** Wake up time */ uint32_t twt_wake_interval; - /* Wake ahead notification is sent earlier than + /** Wake ahead notification is sent earlier than * TWT Service period (SP) start based on this duration. * This should give applications ample time to * prepare the data before TWT SP starts. @@ -536,6 +578,8 @@ struct wifi_twt_params { enum wifi_twt_fail_reason fail_reason; }; +/** @cond INTERNAL_HIDDEN */ + /* Flow ID is only 3 bits */ #define WIFI_MAX_TWT_FLOWS 8 #define WIFI_MAX_TWT_INTERVAL_US (LONG_MAX - 1) @@ -543,7 +587,9 @@ struct wifi_twt_params { #define WIFI_MAX_TWT_WAKE_INTERVAL_US 262144 #define WIFI_MAX_TWT_WAKE_AHEAD_DURATION_US (LONG_MAX - 1) -/** Wi-Fi TWT flow information */ +/** @endcond */ + +/** @brief Wi-Fi TWT flow information */ struct wifi_twt_flow_info { /** Interval = Wake up time + Sleeping time */ uint64_t twt_interval; @@ -563,11 +609,11 @@ struct wifi_twt_flow_info { bool announce; /** Wake up time */ uint32_t twt_wake_interval; - /* wake ahead duration */ + /** Wake ahead duration */ uint32_t twt_wake_ahead_duration; }; -/** Wi-Fi power save configuration */ +/** @brief Wi-Fi power save configuration */ struct wifi_ps_config { /** Number of TWT flows */ char num_twt_flows; @@ -577,7 +623,7 @@ struct wifi_ps_config { struct wifi_ps_params ps_params; }; -/** Generic get/set operation for any command*/ +/** @brief Generic get/set operation for any command*/ enum wifi_mgmt_op { /** Get operation */ WIFI_MGMT_GET = 0, @@ -585,9 +631,10 @@ enum wifi_mgmt_op { WIFI_MGMT_SET = 1, }; +/** Max regulatory channel number */ #define MAX_REG_CHAN_NUM 42 -/** Per-channel regulatory attributes */ +/** @brief Per-channel regulatory attributes */ struct wifi_reg_chan_info { /** Center frequency in MHz */ unsigned short center_frequency; @@ -601,9 +648,9 @@ struct wifi_reg_chan_info { unsigned short dfs:1; } __packed; -/** Regulatory domain information or configuration */ +/** @brief Regulatory domain information or configuration */ struct wifi_reg_domain { - /* Regulatory domain operation */ + /** Regulatory domain operation */ enum wifi_mgmt_op oper; /** Ignore all other regulatory hints over this one */ bool force; @@ -615,7 +662,7 @@ struct wifi_reg_domain { struct wifi_reg_chan_info *chan_info; }; -/** Wi-Fi TWT sleep states */ +/** @brief Wi-Fi TWT sleep states */ enum wifi_twt_sleep_state { /** TWT sleep state: sleeping */ WIFI_TWT_STATE_SLEEP = 0, @@ -624,7 +671,7 @@ enum wifi_twt_sleep_state { }; #if defined(CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS) || defined(__DOXYGEN__) -/** Wi-Fi raw scan result */ +/** @brief Wi-Fi raw scan result */ struct wifi_raw_scan_result { /** RSSI */ int8_t rssi; @@ -637,7 +684,7 @@ struct wifi_raw_scan_result { }; #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ -/** AP mode - connected STA details */ +/** @brief AP mode - connected STA details */ struct wifi_ap_sta_info { /** Link mode, see enum wifi_link_mode */ enum wifi_link_mode link_mode; @@ -649,6 +696,8 @@ struct wifi_ap_sta_info { bool twt_capable; }; +/** @cond INTERNAL_HIDDEN */ + /* for use in max info size calculations */ union wifi_mgmt_events { struct wifi_scan_result scan_result; @@ -661,7 +710,9 @@ union wifi_mgmt_events { struct wifi_ap_sta_info ap_sta_info; }; -/** Wi-Fi mode setup */ +/** @endcond */ + +/** @brief Wi-Fi mode setup */ struct wifi_mode_info { /** Mode setting for a specific mode of operation */ uint8_t mode; @@ -671,7 +722,7 @@ struct wifi_mode_info { enum wifi_mgmt_op oper; }; -/** Wi-Fi filter setting for monitor, prmoiscuous, TX-injection modes */ +/** @brief Wi-Fi filter setting for monitor, prmoiscuous, TX-injection modes */ struct wifi_filter_info { /** Filter setting */ uint8_t filter; @@ -683,7 +734,7 @@ struct wifi_filter_info { enum wifi_mgmt_op oper; }; -/** Wi-Fi channel setting for monitor and TX-injection modes */ +/** @brief Wi-Fi channel setting for monitor and TX-injection modes */ struct wifi_channel_info { /** Channel value to set */ uint16_t channel; From 98f873f9775b0e3a589509ef217d112d44cdf8a2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1181/1389] net: doc: wifi_nm.h: Hide internal data from documentation No need to generate documentation for internal data in wifi_nm.h Signed-off-by: Jukka Rissanen --- include/zephyr/net/wifi_nm.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/zephyr/net/wifi_nm.h b/include/zephyr/net/wifi_nm.h index dd97fcdd8b6163..615d49157572a4 100644 --- a/include/zephyr/net/wifi_nm.h +++ b/include/zephyr/net/wifi_nm.h @@ -42,6 +42,8 @@ struct wifi_nm_instance { struct net_if *mgd_ifaces[CONFIG_WIFI_NM_MAX_MANAGED_INTERFACES]; }; +/** @cond INTERNAL_HIDDEN */ + #define WIFI_NM_NAME(name) wifi_nm_##name #define DEFINE_WIFI_NM_INSTANCE(_name, _ops) \ @@ -51,6 +53,8 @@ struct wifi_nm_instance { .mgd_ifaces = { NULL }, \ } +/** @endcond */ + /** * @brief Get a Network manager instance for a given name * From 3c4fdf7472c07f85d2b0491a8b1a324bbfdd7d1a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1182/1389] net: doc: wifi_utils.h: Add missing doxygen documentation The wifi_utils.h was missing couple of doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/wifi_utils.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/zephyr/net/wifi_utils.h b/include/zephyr/net/wifi_utils.h index 537db787648281..511d2033532281 100644 --- a/include/zephyr/net/wifi_utils.h +++ b/include/zephyr/net/wifi_utils.h @@ -28,7 +28,10 @@ extern "C" { * @{ */ +/** Maximum length of the band specification string */ #define WIFI_UTILS_MAX_BAND_STR_LEN 3 + +/** Maximum length of the channel specification string */ #define WIFI_UTILS_MAX_CHAN_STR_LEN 4 /** From 803da2e2c884ee1eafcaf0c41c2138f8cf4d0732 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1183/1389] net: doc: zperf.h: Add missing doxygen comments The zperp.h header file was missing doxygen comments. Signed-off-by: Jukka Rissanen --- include/zephyr/net/zperf.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/include/zephyr/net/zperf.h b/include/zephyr/net/zperf.h index 21ce74bb33b7d9..c97c9d014395b8 100644 --- a/include/zephyr/net/zperf.h +++ b/include/zephyr/net/zperf.h @@ -24,6 +24,8 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + enum zperf_status { ZPERF_SESSION_STARTED, ZPERF_SESSION_PERIODIC_RESULT, @@ -51,17 +53,20 @@ struct zperf_download_params { char if_name[IFNAMSIZ]; }; +/** @endcond */ + +/** Performance results */ struct zperf_results { - uint32_t nb_packets_sent; - uint32_t nb_packets_rcvd; - uint32_t nb_packets_lost; - uint32_t nb_packets_outorder; - uint64_t total_len; - uint64_t time_in_us; - uint32_t jitter_in_us; - uint64_t client_time_in_us; - uint32_t packet_size; - uint32_t nb_packets_errors; + uint32_t nb_packets_sent; /**< Number of packets sent */ + uint32_t nb_packets_rcvd; /**< Number of packets received */ + uint32_t nb_packets_lost; /**< Number of packets lost */ + uint32_t nb_packets_outorder; /**< Number of packets out of order */ + uint64_t total_len; /**< Total length of the transferred data */ + uint64_t time_in_us; /**< Total time of the transfer in microseconds */ + uint32_t jitter_in_us; /**< Jitter in microseconds */ + uint64_t client_time_in_us; /**< Client connection time in microseconds */ + uint32_t packet_size; /**< Packet size */ + uint32_t nb_packets_errors; /**< Number of packet errors */ }; /** From b4bab0ac0021b351da610a0e2ce3bd1f2b9779dc Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1184/1389] kernel: Predicate _cpus_active on CONFIG_PM This value isn't used outside of the PM subsystem, so don't build it. More important than the four bytes of .bss was the use of an atomic_inc(). Some platforms are forced to use CONFIG_ATOMIC_OPERATIONS_C (but in almost all cases are single-core devices that won't use atomics at runtime). There, this turns into a function call that pulls in the whole atomics implementation. Signed-off-by: Andy Ross --- kernel/init.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/init.c b/kernel/init.c index eaffb6ce763b37..00765f5483a89b 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -46,8 +46,9 @@ BUILD_ASSERT(CONFIG_MP_NUM_CPUS == CONFIG_MP_MAX_NUM_CPUS, __pinned_bss struct z_kernel _kernel; -__pinned_bss -atomic_t _cpus_active; +#ifdef CONFIG_PM +__pinned_bss atomic_t _cpus_active; +#endif /* init/main and idle threads */ K_THREAD_PINNED_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE); @@ -512,11 +513,13 @@ void z_init_cpu(int id) CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE; #endif +#ifdef CONFIG_PM /* * Increment number of CPUs active. The pm subsystem * will keep track of this from here. */ atomic_inc(&_cpus_active); +#endif #ifdef CONFIG_OBJ_CORE_SYSTEM k_obj_core_init_and_link(K_OBJ_CORE(&_kernel.cpus[id]), &obj_type_cpu); From ce2a7b5258e6ba796b3cc88dcb5af189c9bfa094 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1185/1389] kernel: move memory domain kconfigs into its own file This moves memory domain related kconfigs into its own file Kconfig.mem_domain. Signed-off-by: Daniel Leung --- kernel/Kconfig | 54 +------------------------------------ kernel/Kconfig.mem_domain | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 53 deletions(-) create mode 100644 kernel/Kconfig.mem_domain diff --git a/kernel/Kconfig b/kernel/Kconfig index 767c04f94fe47c..c65ec351fcb3e0 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -943,59 +943,7 @@ config BOUNDS_CHECK_BYPASS_MITIGATION macros do nothing. endmenu - -menu "Memory Domains" - -config MAX_DOMAIN_PARTITIONS - int "Maximum number of partitions per memory domain" - default 16 - range 0 255 - depends on USERSPACE - help - Configure the maximum number of partitions per memory domain. - -config ARCH_MEM_DOMAIN_DATA - bool - depends on USERSPACE - help - This hidden option is selected by the target architecture if - architecture-specific data is needed on a per memory domain basis. - If so, the architecture defines a 'struct arch_mem_domain' which is - embedded within every struct k_mem_domain. The architecture - must also define the arch_mem_domain_init() function to set this up - when a memory domain is created. - - Typical uses might be a set of page tables for that memory domain. - -config ARCH_MEM_DOMAIN_SYNCHRONOUS_API - bool - depends on USERSPACE - help - This hidden option is selected by the target architecture if - modifying a memory domain's partitions at runtime, or changing - a memory domain's thread membership requires synchronous calls - into the architecture layer. - - If enabled, the architecture layer must implement the following - APIs: - - arch_mem_domain_thread_add - arch_mem_domain_thread_remove - arch_mem_domain_partition_remove - arch_mem_domain_partition_add - - It's important to note that although supervisor threads can be - members of memory domains, they have no implications on supervisor - thread access to memory. Memory domain APIs may only be invoked from - supervisor mode. - - For these reasons, on uniprocessor systems unless memory access - policy is managed in separate software constructions like page - tables, these APIs don't need to be implemented as the underlying - memory management hardware will be reprogrammed on context switch - anyway. -endmenu - +rsource "Kconfig.mem_domain" rsource "Kconfig.smp" config TICKLESS_KERNEL diff --git a/kernel/Kconfig.mem_domain b/kernel/Kconfig.mem_domain new file mode 100644 index 00000000000000..9f94f4cdcbd61a --- /dev/null +++ b/kernel/Kconfig.mem_domain @@ -0,0 +1,56 @@ +# Kernel configuration options + +# Copyright (c) 2014-2015 Wind River Systems, Inc. +# SPDX-License-Identifier: Apache-2.0 + +menu "Memory Domains" + +config MAX_DOMAIN_PARTITIONS + int "Maximum number of partitions per memory domain" + default 16 + range 0 255 + depends on USERSPACE + help + Configure the maximum number of partitions per memory domain. + +config ARCH_MEM_DOMAIN_DATA + bool + depends on USERSPACE + help + This hidden option is selected by the target architecture if + architecture-specific data is needed on a per memory domain basis. + If so, the architecture defines a 'struct arch_mem_domain' which is + embedded within every struct k_mem_domain. The architecture + must also define the arch_mem_domain_init() function to set this up + when a memory domain is created. + + Typical uses might be a set of page tables for that memory domain. + +config ARCH_MEM_DOMAIN_SYNCHRONOUS_API + bool + depends on USERSPACE + help + This hidden option is selected by the target architecture if + modifying a memory domain's partitions at runtime, or changing + a memory domain's thread membership requires synchronous calls + into the architecture layer. + + If enabled, the architecture layer must implement the following + APIs: + + arch_mem_domain_thread_add + arch_mem_domain_thread_remove + arch_mem_domain_partition_remove + arch_mem_domain_partition_add + + It's important to note that although supervisor threads can be + members of memory domains, they have no implications on supervisor + thread access to memory. Memory domain APIs may only be invoked from + supervisor mode. + + For these reasons, on uniprocessor systems unless memory access + policy is managed in separate software constructions like page + tables, these APIs don't need to be implemented as the underlying + memory management hardware will be reprogrammed on context switch + anyway. +endmenu From 242d4571e6296a74529ca6202aeb1b211dc22abe Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1186/1389] kernel: mem_domain: new config for isolated stacks This adds a new kconfig to indicate if architecture code supports isolating thread stacks within the same domain, and another new kconfig to selectively enable this behavior. Signed-off-by: Daniel Leung --- doc/kernel/usermode/memory_domain.rst | 22 ++++++++++++++++++---- kernel/Kconfig.mem_domain | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/doc/kernel/usermode/memory_domain.rst b/doc/kernel/usermode/memory_domain.rst index a1ddcd395e98a0..f830cc981b91b5 100644 --- a/doc/kernel/usermode/memory_domain.rst +++ b/doc/kernel/usermode/memory_domain.rst @@ -74,10 +74,24 @@ Thread Stack ************ Any thread running in user mode will need access to its own stack buffer. -On context switch into a user mode thread, a dedicated MPU region will be -programmed with the bounds of the stack buffer. A thread exceeding its stack -buffer will start pushing data onto memory it doesn't have access to and a -memory access violation exception will be generated. +On context switch into a user mode thread, a dedicated MPU region or MMU +page table entries will be programmed with the bounds of the stack buffer. +A thread exceeding its stack buffer will start pushing data onto memory +it doesn't have access to and a memory access violation exception will be +generated. + +Note that user threads have access to the stacks of other user threads in +the same memory domain. This is the minimum required for architectures to +support memory domains. Architecture can further restrict access to stacks +so each user thread only has access to its own stack if such architecture +advertises this capability via +:kconfig:option:`CONFIG_ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS`. +This behavior is enabled by default if supported and can be selectively +disabled via :kconfig:option:`CONFIG_MEM_DOMAIN_ISOLATED_STACKS` if +architecture supports both operating modes. However, some architectures +may decide to enable this all the time, and thus this option cannot be +disabled. Regardless of these kconfigs, user threads cannot access +the stacks of other user threads outside of their memory domains. Thread Resource Pools ********************* diff --git a/kernel/Kconfig.mem_domain b/kernel/Kconfig.mem_domain index 9f94f4cdcbd61a..28f3d003639d25 100644 --- a/kernel/Kconfig.mem_domain +++ b/kernel/Kconfig.mem_domain @@ -53,4 +53,27 @@ config ARCH_MEM_DOMAIN_SYNCHRONOUS_API tables, these APIs don't need to be implemented as the underlying memory management hardware will be reprogrammed on context switch anyway. + +config ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + bool + help + This hidden option is selected by the target architecture if + the architecture supports isolating thread stacks for threads + within the same memory domain. + +config MEM_DOMAIN_ISOLATED_STACKS + bool + default y + depends on (MMU || MPU) && ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + help + If enabled, thread stacks within the same memory domains are + isolated which means threads within the same memory domains + have no access to others threads' stacks. + + If disabled, threads within the same memory domains can access + other threads' stacks. + + Regardless of this settings, threads cannot access the stacks of + threads outside of their domains. + endmenu From f2872028674200d93d0df818b9de2eae71e4bf3a Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Sun, 26 May 2024 22:39:30 +0200 Subject: [PATCH 1187/1389] tests: mem_protect/userspace: use kconfig for other stack tests This uses the newly introduced CONFIG_MEM_DOMAIN_ISOLATED_STACKS to determine whether to proceed with the tests to access other threads' stacks. This provides more precise control on when to run or skip these tests. Signed-off-by: Daniel Leung --- tests/kernel/mem_protect/userspace/src/main.c | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/tests/kernel/mem_protect/userspace/src/main.c b/tests/kernel/mem_protect/userspace/src/main.c index cd66c06ab7a1ae..d2b5842ee97eac 100644 --- a/tests/kernel/mem_protect/userspace/src/main.c +++ b/tests/kernel/mem_protect/userspace/src/main.c @@ -553,17 +553,16 @@ ZTEST_USER(userspace, test_read_other_stack) /* Try to read from another thread's stack. */ unsigned int val; -#if defined(CONFIG_MMU) || defined(CONFIG_MPU) -#if defined(CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API) - /* With memory domain enabled, all threads within the same domain - * have access to each other threads' stacks, especially with - * CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API=y (as it is expected - * behavior). The access would not fault which the test expects. - * So skip this test. +#if !defined(CONFIG_MEM_DOMAIN_ISOLATED_STACKS) + /* The minimal requirement to support memory domain permits + * threads of the same memory domain to access each others' stacks. + * Some architectures supports further restricting access which + * can be enabled via a kconfig. So if the kconfig is not enabled, + * skip the test. */ ztest_test_skip(); #endif -#endif + k_thread_create(&test_thread, test_stack, STACKSIZE, uthread_read_body, &val, NULL, NULL, -1, K_USER | K_INHERIT_PERMS, @@ -583,17 +582,16 @@ ZTEST_USER(userspace, test_write_other_stack) /* Try to write to another thread's stack. */ unsigned int val; -#if defined(CONFIG_MMU) || defined(CONFIG_MPU) -#if defined(CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API) - /* With memory domain enabled, all threads within the same domain - * have access to each other threads' stacks, especially with - * CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API=y (as it is expected - * behavior). The access would not fault which the test expects. - * So skip this test. +#if !defined(CONFIG_MEM_DOMAIN_ISOLATED_STACKS) + /* The minimal requirement to support memory domain permits + * threads of the same memory domain to access each others' stacks. + * Some architectures supports further restricting access which + * can be enabled via a kconfig. So if the kconfig is not enabled, + * skip the test. */ ztest_test_skip(); #endif -#endif + k_thread_create(&test_thread, test_stack, STACKSIZE, uthread_write_body, &val, NULL, NULL, -1, K_USER | K_INHERIT_PERMS, From 4bebddf902e9f927f07f40b76ac81cd7bcb5d570 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1188/1389] arm: mpu: select CONFIG_MEM_DOMAIN_ISOLATED_STACKS ARM MPU implementation supports isolating thread stacks within the same memory domain, and also is the only supported operating mode. So select the corresponding kconfig by default. Signed-off-by: Daniel Leung --- arch/arm/core/mpu/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/core/mpu/Kconfig b/arch/arm/core/mpu/Kconfig index dc540038e2b2c2..c6d1bdc7da05ad 100644 --- a/arch/arm/core/mpu/Kconfig +++ b/arch/arm/core/mpu/Kconfig @@ -14,6 +14,8 @@ config ARM_MPU select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if !(CPU_HAS_NXP_MPU || ARMV8_M_BASELINE || ARMV8_M_MAINLINE || AARCH32_ARMV8_R) select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if CPU_HAS_ARM_MPU && (ARMV8_M_BASELINE || ARMV8_M_MAINLINE || AARCH32_ARMV8_R) select MPU_GAP_FILLING if AARCH32_ARMV8_R + select ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + select MEM_DOMAIN_ISOLATED_STACKS help MCU implements Memory Protection Unit. From 8cf378bc7c04f9bb99d57be9eb485455606e55cc Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1189/1389] riscv: pmp: select CONFIG_MEM_DOMAIN_ISOLATED_STACKS RISC-V PMP implementation supports isolating thread stacks within the same memory domain, and also is the only supported operating mode. So select the corresponding kconfig by default. Signed-off-by: Daniel Leung --- arch/riscv/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 965ff4e3f8d3c8..1c4d547b29c64b 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -266,6 +266,8 @@ config RISCV_PMP select ARCH_MEM_DOMAIN_SYNCHRONOUS_API if USERSPACE select ARCH_MEM_DOMAIN_DATA if USERSPACE select THREAD_LOCAL_STORAGE if USERSPACE + select ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + select MEM_DOMAIN_ISOLATED_STACKS help MCU implements Physical Memory Protection. From 18f0cc3d7c5c834648ca86c5b2acf09984920bf3 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1190/1389] drivers: sensor: stm32_temp/vbat/vref: ensure the ADC is not suspended The STM32 temperature, battery and voltage reference sensors needs to write the ADC common registers to enable the corresponding ADC features. For that we need to ensure that the ADC is not suspended by using the pm_device_runtime_get/put methods. Signed-off-by: Aurelien Jarno --- drivers/sensor/st/stm32_temp/stm32_temp.c | 3 +++ drivers/sensor/st/stm32_vbat/stm32_vbat.c | 3 +++ drivers/sensor/st/stm32_vref/stm32_vref.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/drivers/sensor/st/stm32_temp/stm32_temp.c b/drivers/sensor/st/stm32_temp/stm32_temp.c index fedd111af04033..48abc493718a49 100644 --- a/drivers/sensor/st/stm32_temp/stm32_temp.c +++ b/drivers/sensor/st/stm32_temp/stm32_temp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #if defined(CONFIG_SOC_SERIES_STM32H5X) #include @@ -74,6 +75,7 @@ static int stm32_temp_sample_fetch(const struct device *dev, enum sensor_channel } k_mutex_lock(&data->mutex, K_FOREVER); + pm_device_runtime_get(data->adc); rc = adc_channel_setup(data->adc, &data->adc_cfg); if (rc) { @@ -97,6 +99,7 @@ static int stm32_temp_sample_fetch(const struct device *dev, enum sensor_channel path &= ~LL_ADC_PATH_INTERNAL_TEMPSENSOR); unlock: + pm_device_runtime_put(data->adc); k_mutex_unlock(&data->mutex); return rc; diff --git a/drivers/sensor/st/stm32_vbat/stm32_vbat.c b/drivers/sensor/st/stm32_vbat/stm32_vbat.c index 352c5a22920cd2..87942f4bfd2052 100644 --- a/drivers/sensor/st/stm32_vbat/stm32_vbat.c +++ b/drivers/sensor/st/stm32_vbat/stm32_vbat.c @@ -9,6 +9,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(stm32_vbat, CONFIG_SENSOR_LOG_LEVEL); @@ -45,6 +46,7 @@ static int stm32_vbat_sample_fetch(const struct device *dev, enum sensor_channel } k_mutex_lock(&data->mutex, K_FOREVER); + pm_device_runtime_get(data->adc); rc = adc_channel_setup(data->adc, &data->adc_cfg); @@ -67,6 +69,7 @@ static int stm32_vbat_sample_fetch(const struct device *dev, enum sensor_channel path &= ~LL_ADC_PATH_INTERNAL_VBAT); unlock: + pm_device_runtime_put(data->adc); k_mutex_unlock(&data->mutex); return rc; diff --git a/drivers/sensor/st/stm32_vref/stm32_vref.c b/drivers/sensor/st/stm32_vref/stm32_vref.c index 14412a6579a621..5db5a857167e93 100644 --- a/drivers/sensor/st/stm32_vref/stm32_vref.c +++ b/drivers/sensor/st/stm32_vref/stm32_vref.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #if defined(CONFIG_SOC_SERIES_STM32H5X) #include @@ -45,6 +46,7 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel } k_mutex_lock(&data->mutex, K_FOREVER); + pm_device_runtime_get(data->adc); rc = adc_channel_setup(data->adc, &data->adc_cfg); if (rc) { @@ -71,6 +73,7 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel unlock: + pm_device_runtime_put(data->adc); k_mutex_unlock(&data->mutex); return rc; From baf8c8b26933a16fa9f87bc85cf1defbd3b5b639 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1191/1389] tests: dac: add rd_rw612_bga support add dac rd_rw612_bga support Signed-off-by: Hake Huang --- tests/drivers/dac/dac_api/src/test_dac.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/drivers/dac/dac_api/src/test_dac.c b/tests/drivers/dac/dac_api/src/test_dac.c index 612aa824ec0bee..b7315b180d4f37 100644 --- a/tests/drivers/dac/dac_api/src/test_dac.c +++ b/tests/drivers/dac/dac_api/src/test_dac.c @@ -87,6 +87,12 @@ #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 +#elif defined(CONFIG_BOARD_RD_RW612_BGA) + +#define DAC_DEVICE_NODE DT_NODELABEL(dac0) +#define DAC_RESOLUTION 10 +#define DAC_CHANNEL_ID 0 + #else #error "Unsupported board." #endif From 51048cdf105b7ae3663429cb40bcb4ec374ed9ca Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1192/1389] tests: dac: frdm_mcx947 add dac test support add frdm_mcx947 defines in source Signed-off-by: Hake Huang --- tests/drivers/dac/dac_api/src/test_dac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drivers/dac/dac_api/src/test_dac.c b/tests/drivers/dac/dac_api/src/test_dac.c index b7315b180d4f37..e38f1ef1273dc3 100644 --- a/tests/drivers/dac/dac_api/src/test_dac.c +++ b/tests/drivers/dac/dac_api/src/test_dac.c @@ -45,6 +45,7 @@ #elif defined(CONFIG_BOARD_TWR_KE18F) || \ defined(CONFIG_BOARD_FRDM_K64F) || \ defined(CONFIG_BOARD_FRDM_K22F) || \ + defined(CONFIG_BOARD_FRDM_MCXN947) || \ defined(CONFIG_BOARD_SEEEDUINO_XIAO) || \ defined(CONFIG_BOARD_ARDUINO_MKRZERO) || \ defined(CONFIG_BOARD_ARDUINO_ZERO) || \ From 92265aa866f1a127840ffa7bfb7ffb6a7c20ef0f Mon Sep 17 00:00:00 2001 From: Marcio Ribeiro Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1193/1389] test: dac: esp32s2_devkitc bugfix add dts and dac setting for tests/driver/dac/dac_api Signed-off-by: Marcio Ribeiro --- boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts | 4 ++++ tests/drivers/dac/dac_api/src/test_dac.c | 1 + 2 files changed, 5 insertions(+) diff --git a/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts b/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts index 25b1c599c571fd..f8282767d22d79 100644 --- a/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts +++ b/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts @@ -163,3 +163,7 @@ &wdt0 { status = "okay"; }; + +&dac { + status = "okay"; +}; diff --git a/tests/drivers/dac/dac_api/src/test_dac.c b/tests/drivers/dac/dac_api/src/test_dac.c index e38f1ef1273dc3..b63410ef53c015 100644 --- a/tests/drivers/dac/dac_api/src/test_dac.c +++ b/tests/drivers/dac/dac_api/src/test_dac.c @@ -70,6 +70,7 @@ defined(CONFIG_BOARD_ESP32_DEVKITC_WROVER) || \ defined(CONFIG_BOARD_ESP_WROVER_KIT) || \ defined(CONFIG_BOARD_ESP32S2_SAOLA) || \ + defined(CONFIG_BOARD_ESP32S2_DEVKITC) || \ defined(CONFIG_BOARD_GD32A503V_EVAL) || \ defined(CONFIG_BOARD_GD32E103V_EVAL) || \ defined(CONFIG_BOARD_GD32F450I_EVAL) || \ From 1664c059a7cb9731b043cd4daa7010e7c7fb6265 Mon Sep 17 00:00:00 2001 From: Paul He Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1194/1389] samples: pktqueue: remove main.h Normally main.c file doesn't have a header file, because it doesn't need to declare any interface to other modules. In this sample, it makes more sense to put all the relevant macro definitions in main.c directly. Signed-off-by: Paul He --- samples/arch/smp/pktqueue/src/main.c | 22 ++++++++++++++++++- samples/arch/smp/pktqueue/src/main.h | 32 ---------------------------- 2 files changed, 21 insertions(+), 33 deletions(-) delete mode 100644 samples/arch/smp/pktqueue/src/main.h diff --git a/samples/arch/smp/pktqueue/src/main.c b/samples/arch/smp/pktqueue/src/main.c index 009cd2de966ec0..cfffd813a8bc2b 100644 --- a/samples/arch/smp/pktqueue/src/main.c +++ b/samples/arch/smp/pktqueue/src/main.c @@ -5,7 +5,27 @@ */ #include "pktqueue.h" -#include "main.h" + +/* Amount of parallel processed sender/receiver queues of packet headers */ +#define QUEUE_NUM 2 + +/* Amount of execution threads per pair of queues*/ +#define THREADS_NUM (CONFIG_MP_MAX_NUM_CPUS+1) + +/* Amount of packet headers in a queue */ +#define SIZE_OF_QUEUE 5000 + +/* Size of packet header (in bytes) */ +#define SIZE_OF_HEADER 24 + +/* CRC16 polynomial */ +#define POLYNOMIAL 0x8005 + +/* CRC bytes in the packet */ +#define CRC_BYTE_1 10 +#define CRC_BYTE_2 11 + +#define STACK_SIZE 2048 static struct k_thread tthread[THREADS_NUM*QUEUE_NUM]; static struct k_thread qthread[QUEUE_NUM]; diff --git a/samples/arch/smp/pktqueue/src/main.h b/samples/arch/smp/pktqueue/src/main.h deleted file mode 100644 index 20020563ca1641..00000000000000 --- a/samples/arch/smp/pktqueue/src/main.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2020 Synopsys, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - - -/* Amount of parallel processed sender/receiver queues of packet headers */ -#define QUEUE_NUM 2 - -/* Amount of execution threads per pair of queues*/ -#define THREADS_NUM (CONFIG_MP_MAX_NUM_CPUS+1) - -/* Amount of packet headers in a queue */ -#define SIZE_OF_QUEUE 5000 - -/* Size of packet header (in bytes) */ -#define SIZE_OF_HEADER 24 - -/* CRC16 polynomial */ -#define POLYNOMIAL 0x8005 - -/* CRC bytes in the packet */ -#define CRC_BYTE_1 10 -#define CRC_BYTE_2 11 - -#define STACK_SIZE 2048 From ba32e9a225e9750a76a51b9eed9a9a1bdb6b310e Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1195/1389] logging: log_output: Prevent redundant flush with zero-length data There's such a case captured. When log immediate mode is enabled, each log message is output per character. However, "log_output_flush()" function is still called with zero data length at the end of "log_output_process()". Better to make "buffer_write()" returns immediatley if buffer data length is zero. Signed-off-by: Dong Wang --- subsys/logging/log_output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/logging/log_output.c b/subsys/logging/log_output.c index 85fbfdb35b6e56..cd8e898a354ba3 100644 --- a/subsys/logging/log_output.c +++ b/subsys/logging/log_output.c @@ -152,11 +152,11 @@ static void buffer_write(log_output_func_t outf, uint8_t *buf, size_t len, { int processed; - do { + while (len != 0) { processed = outf(buf, len, ctx); len -= processed; buf += processed; - } while (len != 0); + } } From ac774805d2f784164cd6fa8caaa9768b10d7282a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1196/1389] userspace: dynamic: Fix k_thread_stack_free verification k_thread_stack_free syscall was not checking if the caller had permission to given stack object. Signed-off-by: Flavio Ceolin --- kernel/dynamic.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/dynamic.c b/kernel/dynamic.c index d03e36693468b5..89f80933dd0f1d 100644 --- a/kernel/dynamic.c +++ b/kernel/dynamic.c @@ -166,6 +166,15 @@ int z_impl_k_thread_stack_free(k_thread_stack_t *stack) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_thread_stack_free(k_thread_stack_t *stack) { + /* The thread stack object must not be in initialized state. + * + * Thread stack objects are initialized when the thread is created + * and de-initialized whent the thread is destroyed. Since we can't + * free a stack that is in use, we have to check that the caller + * has access to the object but that it is not in use anymore. + */ + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_THREAD_STACK_ELEMENT)); + return z_impl_k_thread_stack_free(stack); } #include From fab3649d0f28613f33047331b58a92f5877d19a2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1197/1389] tests: dynamic_thread_stack: Check thread stack permission Check if a user thread is capable of free another thread stack. Signed-off-by: Flavio Ceolin --- .../threads/dynamic_thread_stack/src/main.c | 99 ++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/tests/kernel/threads/dynamic_thread_stack/src/main.c b/tests/kernel/threads/dynamic_thread_stack/src/main.c index bb15d824d81bc5..a833197d36126b 100644 --- a/tests/kernel/threads/dynamic_thread_stack/src/main.c +++ b/tests/kernel/threads/dynamic_thread_stack/src/main.c @@ -9,7 +9,7 @@ #define TIMEOUT_MS 500 -#define POOL_SIZE 20480 +#define POOL_SIZE 28672 #ifdef CONFIG_USERSPACE #define STACK_OBJ_SIZE K_THREAD_STACK_LEN(CONFIG_DYNAMIC_THREAD_STACK_SIZE) @@ -168,6 +168,103 @@ ZTEST(dynamic_thread_stack, test_dynamic_thread_stack_alloc) } } +K_SEM_DEFINE(perm_sem, 0, 1); +ZTEST_BMEM static volatile bool expect_fault; +ZTEST_BMEM static volatile unsigned int expected_reason; + +static void set_fault(unsigned int reason) +{ + expect_fault = true; + expected_reason = reason; + compiler_barrier(); +} + +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +{ + if (expect_fault) { + if (expected_reason == reason) { + printk("System error was expected\n"); + expect_fault = false; + } else { + printk("Wrong fault reason, expecting %d\n", + expected_reason); + TC_END_REPORT(TC_FAIL); + k_fatal_halt(reason); + } + } else { + printk("Unexpected fault during test\n"); + TC_END_REPORT(TC_FAIL); + k_fatal_halt(reason); + } +} + +static void perm_func(void *arg1, void *arg2, void *arg3) +{ + k_sem_take((struct k_sem *)arg1, K_FOREVER); +} + +static void perm_func_violator(void *arg1, void *arg2, void *arg3) +{ + (void)k_thread_stack_free((k_thread_stack_t *)arg2); + + zassert_unreachable("should not reach here"); +} + +/** @brief Exercise stack permissions */ +ZTEST(dynamic_thread_stack, test_dynamic_thread_stack_permission) +{ + static k_tid_t tid[2]; + static struct k_thread th[2]; + static k_thread_stack_t *stack[2]; + + if (!IS_ENABLED(CONFIG_DYNAMIC_THREAD_PREFER_ALLOC)) { + ztest_test_skip(); + } + + if (!IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) { + ztest_test_skip(); + } + + if (!IS_ENABLED(CONFIG_USERSPACE)) { + ztest_test_skip(); + } + + stack[0] = k_thread_stack_alloc(CONFIG_DYNAMIC_THREAD_STACK_SIZE, K_USER); + zassert_not_null(stack[0]); + + stack[1] = k_thread_stack_alloc(CONFIG_DYNAMIC_THREAD_STACK_SIZE, K_USER); + zassert_not_null(stack[1]); + + k_thread_access_grant(k_current_get(), &perm_sem); + + /* First thread inherit permissions */ + tid[0] = k_thread_create(&th[0], stack[0], CONFIG_DYNAMIC_THREAD_STACK_SIZE, perm_func, + &perm_sem, NULL, NULL, 0, K_USER | K_INHERIT_PERMS, K_NO_WAIT); + zassert_not_null(tid[0]); + + /* Second thread will have access to specific kobjects only */ + tid[1] = k_thread_create(&th[1], stack[1], CONFIG_DYNAMIC_THREAD_STACK_SIZE, + perm_func_violator, &perm_sem, stack[0], NULL, 0, K_USER, + K_FOREVER); + zassert_not_null(tid[1]); + k_thread_access_grant(tid[1], &perm_sem); + k_thread_access_grant(tid[1], &stack[1]); + + set_fault(K_ERR_KERNEL_OOPS); + + k_thread_start(tid[1]); + + /* join all threads and check that flags have been set */ + zassert_ok(k_thread_join(tid[1], K_MSEC(TIMEOUT_MS))); + + k_sem_give(&perm_sem); + zassert_ok(k_thread_join(tid[0], K_MSEC(TIMEOUT_MS))); + + /* clean up stacks allocated from the heap */ + zassert_ok(k_thread_stack_free(stack[0])); + zassert_ok(k_thread_stack_free(stack[1])); +} + static void *dynamic_thread_stack_setup(void) { k_thread_heap_assign(k_current_get(), &stack_heap); From 80637858bddac23df810c9daf20dbde83d3766e0 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1198/1389] drivers: i2c: Add support for Apollo3 SoCs I2C This commit adds support for the I2C which can be found in Apollo3 SoCs, it can work in both DMA and non-DMA modes Signed-off-by: Hao Luo --- boards/ambiq/apollo3_evb/apollo3_evb.dts | 8 ++ boards/ambiq/apollo3_evb/apollo3_evb.yaml | 1 + boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 8 ++ boards/ambiq/apollo3p_evb/apollo3p_evb.yaml | 1 + drivers/i2c/Kconfig.ambiq | 11 ++ drivers/i2c/i2c_ambiq.c | 142 +++++++++++++++++--- dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 12 +- dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 12 +- 8 files changed, 168 insertions(+), 27 deletions(-) diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index fd961a550bef8a..9f1cac0b309805 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -95,6 +95,14 @@ status = "okay"; }; +&i2c3 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c3_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.yaml b/boards/ambiq/apollo3_evb/apollo3_evb.yaml index a85086461c3ee5..f55c135f1d4afc 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.yaml +++ b/boards/ambiq/apollo3_evb/apollo3_evb.yaml @@ -11,6 +11,7 @@ supported: - uart - watchdog - gpio + - i2c testing: ignore_tags: - net diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index 2bccb1746d84f9..02acc1bed5705f 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -95,6 +95,14 @@ status = "okay"; }; +&i2c3 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c3_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml index d789a2519bcc0a..0ed3fe2929df01 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml @@ -11,6 +11,7 @@ supported: - uart - watchdog - gpio + - i2c testing: ignore_tags: - net diff --git a/drivers/i2c/Kconfig.ambiq b/drivers/i2c/Kconfig.ambiq index 040a93866e978c..04a80848d9f4bf 100644 --- a/drivers/i2c/Kconfig.ambiq +++ b/drivers/i2c/Kconfig.ambiq @@ -13,3 +13,14 @@ config I2C_AMBIQ select AMBIQ_HAL_USE_I2C help Enable driver for Ambiq I2C. + +config I2C_AMBIQ_DMA + bool "AMBIQ APOLLO I2C DMA Support" + help + Enable DMA for Ambiq I2C. + +config I2C_DMA_TCB_BUFFER_SIZE + int "DMA Transfer Control Buffer size in words." + default 1024 + help + DMA Transfer Control Buffer size in words diff --git a/drivers/i2c/i2c_ambiq.c b/drivers/i2c/i2c_ambiq.c index e8b62fb2c45a7d..f3c5b90e90031f 100644 --- a/drivers/i2c/i2c_ambiq.c +++ b/drivers/i2c/i2c_ambiq.c @@ -19,7 +19,8 @@ LOG_MODULE_REGISTER(ambiq_i2c, CONFIG_I2C_LOG_LEVEL); typedef int (*ambiq_i2c_pwr_func_t)(void); -#define PWRCTRL_MAX_WAIT_US 5 +#define PWRCTRL_MAX_WAIT_US 5 +#define I2C_TRANSFER_TIMEOUT_MSEC 500 /* Transfer timeout period */ #include "i2c-priv.h" @@ -29,13 +30,50 @@ struct i2c_ambiq_config { uint32_t bitrate; const struct pinctrl_dev_config *pcfg; ambiq_i2c_pwr_func_t pwr_func; + void (*irq_config_func)(void); }; +typedef void (*i2c_ambiq_callback_t)(const struct device *dev, int result, void *data); + struct i2c_ambiq_data { am_hal_iom_config_t iom_cfg; - void *IOMHandle; + void *iom_handler; + struct k_sem bus_sem; + struct k_sem transfer_sem; + i2c_ambiq_callback_t callback; + void *callback_data; + int inst_idx; + uint32_t transfer_status; }; +#ifdef CONFIG_I2C_AMBIQ_DMA +static __aligned(32) struct { + __aligned(32) uint32_t buf[CONFIG_I2C_DMA_TCB_BUFFER_SIZE]; +} i2c_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __attribute__((__section__(".nocache"))); + +static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status) +{ + const struct device *dev = callback_ctxt; + struct i2c_ambiq_data *data = dev->data; + + if (data->callback) { + data->callback(dev, status, data->callback_data); + } + data->transfer_status = status; + k_sem_give(&data->transfer_sem); +} +#endif + +static void i2c_ambiq_isr(const struct device *dev) +{ + uint32_t ui32Status; + struct i2c_ambiq_data *data = dev->data; + + am_hal_iom_interrupt_status_get(data->iom_handler, false, &ui32Status); + am_hal_iom_interrupt_clear(data->iom_handler, ui32Status); + am_hal_iom_interrupt_service(data->iom_handler, ui32Status); +} + static int i2c_ambiq_read(const struct device *dev, struct i2c_msg *msg, uint16_t addr) { struct i2c_ambiq_data *data = dev->data; @@ -50,9 +88,24 @@ static int i2c_ambiq_read(const struct device *dev, struct i2c_msg *msg, uint16_ trans.ui32NumBytes = msg->len; trans.pui32RxBuffer = (uint32_t *)msg->buf; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); - - return ret; +#ifdef CONFIG_I2C_AMBIQ_DMA + data->transfer_status = -EFAULT; + ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback, + (void *)dev); + if (k_sem_take(&data->transfer_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC))) { + LOG_ERR("Timeout waiting for transfer complete"); + /* cancel timed out transaction */ + am_hal_iom_disable(data->iom_handler); + /* clean up for next xfer */ + k_sem_reset(&data->transfer_sem); + am_hal_iom_enable(data->iom_handler); + return -ETIMEDOUT; + } + ret = data->transfer_status; +#else + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); +#endif + return (ret != AM_HAL_STATUS_SUCCESS) ? -EIO : 0; } static int i2c_ambiq_write(const struct device *dev, struct i2c_msg *msg, uint16_t addr) @@ -69,9 +122,26 @@ static int i2c_ambiq_write(const struct device *dev, struct i2c_msg *msg, uint16 trans.ui32NumBytes = msg->len; trans.pui32TxBuffer = (uint32_t *)msg->buf; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); +#ifdef CONFIG_I2C_AMBIQ_DMA + data->transfer_status = -EFAULT; + ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback, + (void *)dev); + + if (k_sem_take(&data->transfer_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC))) { + LOG_ERR("Timeout waiting for transfer complete"); + /* cancel timed out transaction */ + am_hal_iom_disable(data->iom_handler); + /* clean up for next xfer */ + k_sem_reset(&data->transfer_sem); + am_hal_iom_enable(data->iom_handler); + return -ETIMEDOUT; + } + ret = data->transfer_status; +#else + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); +#endif - return ret; + return (ret != AM_HAL_STATUS_SUCCESS) ? -EIO : 0; } static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config) @@ -96,7 +166,12 @@ static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config) return -EINVAL; } - am_hal_iom_configure(data->IOMHandle, &data->iom_cfg); +#ifdef CONFIG_I2C_AMBIQ_DMA + data->iom_cfg.pNBTxnBuf = i2c_dma_tcb_buf[data->inst_idx].buf; + data->iom_cfg.ui32NBTxnBufLength = CONFIG_I2C_DMA_TCB_BUFFER_SIZE; +#endif + + am_hal_iom_configure(data->iom_handler, &data->iom_cfg); return 0; } @@ -104,12 +179,16 @@ static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config) static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { + struct i2c_ambiq_data *data = dev->data; int ret = 0; if (!num_msgs) { return 0; } + /* Send out messages */ + k_sem_take(&data->bus_sem, K_FOREVER); + for (int i = 0; i < num_msgs; i++) { if (msgs[i].flags & I2C_MSG_READ) { ret = i2c_ambiq_read(dev, &(msgs[i]), addr); @@ -122,6 +201,8 @@ static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, ui } } + k_sem_give(&data->bus_sem); + return 0; } @@ -134,21 +215,41 @@ static int i2c_ambiq_init(const struct device *dev) data->iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE; - ret = am_hal_iom_initialize((config->base - REG_IOM_BASEADDR) / config->size, - &data->IOMHandle); + if (AM_HAL_STATUS_SUCCESS != + am_hal_iom_initialize((config->base - REG_IOM_BASEADDR) / config->size, + &data->iom_handler)) { + LOG_ERR("Fail to initialize I2C\n"); + return -ENXIO; + } ret = config->pwr_func(); - ret = i2c_ambiq_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); + ret |= i2c_ambiq_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); + if (ret < 0) { + LOG_ERR("Fail to config I2C\n"); + goto end; + } ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; + LOG_ERR("Fail to config I2C pins\n"); + goto end; } - ret = am_hal_iom_enable(data->IOMHandle); +#ifdef CONFIG_I2C_AMBIQ_DMA + am_hal_iom_interrupt_clear(data->iom_handler, AM_HAL_IOM_INT_CQUPD | AM_HAL_IOM_INT_ERR); + am_hal_iom_interrupt_enable(data->iom_handler, AM_HAL_IOM_INT_CQUPD | AM_HAL_IOM_INT_ERR); + config->irq_config_func(); +#endif + if (AM_HAL_STATUS_SUCCESS != am_hal_iom_enable(data->iom_handler)) { + LOG_ERR("Fail to enable I2C\n"); + ret = -EIO; + } +end: + if (ret < 0) { + am_hal_iom_uninitialize(data->iom_handler); + } return ret; } @@ -167,12 +268,23 @@ static const struct i2c_driver_api i2c_ambiq_driver_api = { k_busy_wait(PWRCTRL_MAX_WAIT_US); \ return 0; \ } \ - static struct i2c_ambiq_data i2c_ambiq_data##n; \ + static void i2c_irq_config_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), i2c_ambiq_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + }; \ + static struct i2c_ambiq_data i2c_ambiq_data##n = { \ + .bus_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.bus_sem, 1, 1), \ + .transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1), \ + .inst_idx = n, \ + }; \ static const struct i2c_ambiq_config i2c_ambiq_config##n = { \ .base = DT_INST_REG_ADDR(n), \ .size = DT_INST_REG_SIZE(n), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .irq_config_func = i2c_irq_config_func_##n, \ .pwr_func = pwr_on_ambiq_i2c_##n}; \ I2C_DEVICE_DT_INST_DEFINE(n, i2c_ambiq_init, NULL, &i2c_ambiq_data##n, \ &i2c_ambiq_config##n, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index 5ae40c06790a24..0005102b69727a 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -95,7 +95,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x100>; }; - iom0: iom@50004000 { + i2c0: i2c@50004000 { reg = <0x50004000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -104,7 +104,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; }; - iom1: iom@50005000 { + i2c1: i2c@50005000 { reg = <0x50005000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -113,7 +113,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; }; - iom2: iom@50006000 { + i2c2: i2c@50006000 { reg = <0x50006000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -122,7 +122,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; }; - iom3: iom@50007000 { + i2c3: i2c@50007000 { reg = <0x50007000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -131,7 +131,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; }; - iom4: iom@50008000 { + i2c4: i2c@50008000 { reg = <0x50008000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -140,7 +140,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; }; - iom5: iom@50009000 { + i2c5: i2c@50009000 { reg = <0x50009000 0x1000>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index ac53b55883e2d6..dc578356bf1437 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -95,7 +95,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x100>; }; - iom0: iom@50004000 { + i2c0: i2c@50004000 { reg = <0x50004000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -104,7 +104,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; }; - iom1: iom@50005000 { + i2c1: i2c@50005000 { reg = <0x50005000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -113,7 +113,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; }; - iom2: iom@50006000 { + i2c2: i2c@50006000 { reg = <0x50006000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -122,7 +122,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; }; - iom3: iom@50007000 { + i2c3: i2c@50007000 { reg = <0x50007000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -131,7 +131,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; }; - iom4: iom@50008000 { + i2c4: i2c@50008000 { reg = <0x50008000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -140,7 +140,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; }; - iom5: iom@50009000 { + i2c5: i2c@50009000 { reg = <0x50009000 0x1000>; #address-cells = <1>; #size-cells = <0>; From 7fb6b2b7a6da2e5ad4ef17a501d4bd7d79ca01d5 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1199/1389] drivers: sensor: rtio: use catch-remaining for decoding As new channels are added to the `enum sensor_channel`, some of the newer channel aren't updated in the whitelist of rtio decoder. Instead of specifying every channel in the list, do: 1. Verify that the `channel` is valid 2. cherry-pick the channels that require special handling, i.e. 1. `three_axis_data` 2. `byte_data` 3. `uint64_data` 3. handle the remaining `channel` in the default case as `q31_data` to make sure that all channels are handled. Updated the pytest to get channel 32, previously nothing would happen for this channel as there isn't a decoder for it, now it would return: ``` channel type=32((null)) ``` the channel name is NULL because it wasn't added to the channel name look up table in the sensor_shell.c, that is being fixed in #72815. Signed-off-by: Yong Cong Sin --- drivers/sensor/default_rtio_sensor.c | 98 ++++------------------------ 1 file changed, 12 insertions(+), 86 deletions(-) diff --git a/drivers/sensor/default_rtio_sensor.c b/drivers/sensor/default_rtio_sensor.c index dec4faacc3b734..c95dcedfe87954 100644 --- a/drivers/sensor/default_rtio_sensor.c +++ b/drivers/sensor/default_rtio_sensor.c @@ -323,6 +323,10 @@ int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, __ASSERT_NO_MSG(base_size != NULL); __ASSERT_NO_MSG(frame_size != NULL); + if (((int)channel.chan_type < 0) || channel.chan_type >= (SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + switch (channel.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: @@ -342,49 +346,6 @@ int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, *base_size = sizeof(struct sensor_three_axis_data); *frame_size = sizeof(struct sensor_three_axis_sample_data); return 0; - case SENSOR_CHAN_DIE_TEMP: - case SENSOR_CHAN_AMBIENT_TEMP: - case SENSOR_CHAN_PRESS: - case SENSOR_CHAN_HUMIDITY: - case SENSOR_CHAN_LIGHT: - case SENSOR_CHAN_IR: - case SENSOR_CHAN_RED: - case SENSOR_CHAN_GREEN: - case SENSOR_CHAN_BLUE: - case SENSOR_CHAN_ALTITUDE: - case SENSOR_CHAN_PM_1_0: - case SENSOR_CHAN_PM_2_5: - case SENSOR_CHAN_PM_10: - case SENSOR_CHAN_DISTANCE: - case SENSOR_CHAN_CO2: - case SENSOR_CHAN_VOC: - case SENSOR_CHAN_GAS_RES: - case SENSOR_CHAN_VOLTAGE: - case SENSOR_CHAN_CURRENT: - case SENSOR_CHAN_POWER: - case SENSOR_CHAN_RESISTANCE: - case SENSOR_CHAN_ROTATION: - case SENSOR_CHAN_RPM: - case SENSOR_CHAN_GAUGE_VOLTAGE: - case SENSOR_CHAN_GAUGE_AVG_CURRENT: - case SENSOR_CHAN_GAUGE_STDBY_CURRENT: - case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: - case SENSOR_CHAN_GAUGE_TEMP: - case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: - case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_AVG_POWER: - case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: - case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY: - case SENSOR_CHAN_GAUGE_TIME_TO_FULL: - case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: - *base_size = sizeof(struct sensor_q31_data); - *frame_size = sizeof(struct sensor_q31_sample_data); - return 0; case SENSOR_CHAN_PROX: *base_size = sizeof(struct sensor_byte_data); *frame_size = sizeof(struct sensor_byte_sample_data); @@ -394,7 +355,9 @@ int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, *frame_size = sizeof(struct sensor_uint64_sample_data); return 0; default: - return -ENOTSUP; + *base_size = sizeof(struct sensor_q31_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; } } @@ -485,6 +448,10 @@ static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, return -EINVAL; } + if (((int)chan_spec.chan_type < 0) || chan_spec.chan_type >= (SENSOR_CHAN_ALL)) { + return 0; + } + /* Check for 3d channel mappings */ switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: @@ -518,49 +485,8 @@ static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, chan_spec.chan_idx); break; - case SENSOR_CHAN_DIE_TEMP: - case SENSOR_CHAN_AMBIENT_TEMP: - case SENSOR_CHAN_PRESS: - case SENSOR_CHAN_HUMIDITY: - case SENSOR_CHAN_LIGHT: - case SENSOR_CHAN_IR: - case SENSOR_CHAN_RED: - case SENSOR_CHAN_GREEN: - case SENSOR_CHAN_BLUE: - case SENSOR_CHAN_ALTITUDE: - case SENSOR_CHAN_PM_1_0: - case SENSOR_CHAN_PM_2_5: - case SENSOR_CHAN_PM_10: - case SENSOR_CHAN_DISTANCE: - case SENSOR_CHAN_CO2: - case SENSOR_CHAN_VOC: - case SENSOR_CHAN_GAS_RES: - case SENSOR_CHAN_VOLTAGE: - case SENSOR_CHAN_CURRENT: - case SENSOR_CHAN_POWER: - case SENSOR_CHAN_RESISTANCE: - case SENSOR_CHAN_ROTATION: - case SENSOR_CHAN_RPM: - case SENSOR_CHAN_GAUGE_VOLTAGE: - case SENSOR_CHAN_GAUGE_AVG_CURRENT: - case SENSOR_CHAN_GAUGE_STDBY_CURRENT: - case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: - case SENSOR_CHAN_GAUGE_TEMP: - case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: - case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_AVG_POWER: - case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: - case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY: - case SENSOR_CHAN_GAUGE_TIME_TO_FULL: - case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: - count = decode_q31(header, q, data_out, chan_spec); - break; default: + count = decode_q31(header, q, data_out, chan_spec); break; } if (count > 0) { From 41dc4eb2b992603f26fac77f819aad762302b2ce Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1200/1389] MAINTAINERS: Add snematbakhsh as OpenTitan platform maintainer Add myself as maintainer for OpenTitan. Signed-off-by: Shawn Nematbakhsh --- MAINTAINERS.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 62b4cf8d461829..09ed1022e28825 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3491,6 +3491,21 @@ nRF Platforms: labels: - "platform: nRF" +OpenTitan Platforms: + status: maintained + maintainers: + - snematbakhsh + files: + - boards/lowrisc/opentitan_earlgrey/ + - drivers/*/*opentitan* + - dts/bindings/*/*opentitan* + - dts/riscv/lowrisc/*opentitan* + - soc/lowrisc/opentitan/ + labels: + - "platform: OpenTitan" + description: >- + OpenTitan boards, SOCs, dts files and related drivers. + Renesas SmartBond Platforms: status: maintained maintainers: From 3d5ea45f4343c87e0bfb32e2993713c794cc0782 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1201/1389] Bluetooth: Controller: Remove legacy LL optimize for speed dependency Remove legacy LL optimize for speed dependency required to support encryption feature in Controller where crypto was performed in highest priority ISRs to setup encryption in 3 radio events (this now requires 5 radio events in split LL). Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/Kconfig.ll_sw_split | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 7828dfdf65abd7..8e1bc6d615cf63 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -599,9 +599,9 @@ config BT_CTLR_DYNAMIC_INTERRUPTS enabled. config BT_CTLR_OPTIMIZE_FOR_SPEED - prompt "Optimize for Speed" if !(SOC_SERIES_NRF51X && BT_CTLR_LE_ENC) + prompt "Optimize for Speed" bool - default y if BT_CTLR_LE_ENC + default y help Optimize compilation of controller for execution speed. From 96361b8d06241023cc9c12cc575359f31eaa089b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1202/1389] Bluetooth: Controller: Support Link Time Optimizations (LTO) Support for using Link Time Optimization (LTO) when building application with open source Bluetooth Low Energy Controller. This reduces code space usage. Current Memory Usage at the time of this PR (hci_ipc): BT_CTLR_OPTIMIZE_FOR_SPEED: Memory region Used Size Region Size %age Used FLASH: 260112 B 256 KB 99.22% RAM: 60136 B 64 KB 91.76% SRAM1: 0 B 64 KB 0.00% IDT_LIST: 0 B 32 KB 0.00% BT_CTLR_OPTIMIZE_FOR_SIZE: Memory region Used Size Region Size %age Used FLASH: 232292 B 256 KB 88.61% RAM: 60128 B 64 KB 91.75% SRAM1: 0 B 64 KB 0.00% IDT_LIST: 0 B 32 KB 0.00% BT_CTLR_OPTIMIZE_FOR_APP_DEFAULT: Memory region Used Size Region Size %age Used FLASH: 232292 B 256 KB 88.61% RAM: 60128 B 64 KB 91.75% SRAM1: 0 B 64 KB 0.00% IDT_LIST: 0 B 32 KB 0.00% BT_CTLR_LTO: Memory region Used Size Region Size %age Used FLASH: 221484 B 256 KB 84.49% RAM: 60120 B 64 KB 91.74% SRAM1: 0 B 64 KB 0.00% IDT_LIST: 0 B 32 KB 0.00% Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/CMakeLists.txt | 5 ++++ .../bluetooth/controller/Kconfig.ll_sw_split | 30 ++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/CMakeLists.txt b/subsys/bluetooth/controller/CMakeLists.txt index a2fb0d22508b27..a9761dc217d0e8 100644 --- a/subsys/bluetooth/controller/CMakeLists.txt +++ b/subsys/bluetooth/controller/CMakeLists.txt @@ -212,6 +212,11 @@ add_subdirectory_ifdef( ll_sw/openisa ) +zephyr_library_compile_options_ifdef( + CONFIG_BT_CTLR_OPTIMIZE_FOR_SIZE + ${OPTIMIZE_FOR_SIZE_FLAG} + ) + zephyr_library_compile_options_ifdef( CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED ${OPTIMIZE_FOR_SPEED_FLAG} diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 8e1bc6d615cf63..e4428929e35855 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -598,12 +598,34 @@ config BT_CTLR_DYNAMIC_INTERRUPTS permit use of SoC's peripheral for custom use when Bluetooth is not enabled. +choice + prompt "Optimization options" + depends on !LTO + default BT_CTLR_OPTIMIZE_FOR_SPEED + +config BT_CTLR_OPTIMIZE_FOR_APP_DEFAULT + bool "Optimize for application defaults" + help + Optimize compilation of Controller for application's default. + +config BT_CTLR_OPTIMIZE_FOR_SIZE + bool "Optimize for space" + help + Optimize compilation of Controller for code size. + + This is the Zephyr project default, but is overridden to use optimize + for speed when compiling the Controller to reduce application's ISR + and thread latencies. + config BT_CTLR_OPTIMIZE_FOR_SPEED - prompt "Optimize for Speed" - bool - default y + bool "Optimize for Speed" help - Optimize compilation of controller for execution speed. + Optimize compilation of Controller for execution speed. As the + Controller's Upper Link Layer and Lower Link Layer execute in ISRs, + use of speed optimizations reduces application's ISR and thread + latencies. + +endchoice config BT_CTLR_XTAL_ADVANCED bool "Advanced event preparation" From 353949aa914fbce3f75ce729b9edc570e425d6f6 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1203/1389] tests: Bluetooth: init: Build time coverage for Controller optimization Added build time coverage for added new Controller optimization related Kconfigs. New Kconfigs are either covered in samples.yaml or in the tests/bluetooth/init conf files. Signed-off-by: Vinayak Kariappa Chettimada --- tests/bluetooth/init/prj_ctlr_4_0_dbg.conf | 1 + tests/bluetooth/init/prj_ctlr_5_x_dbg.conf | 1 + tests/bluetooth/init/prj_ctlr_dbg.conf | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf index 59314c494d7ea0..372d4a2901029b 100644 --- a/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_4_0_dbg.conf @@ -25,6 +25,7 @@ CONFIG_BT_CTLR_CONN_RSSI=n CONFIG_BT_CTLR_ADV_INDICATION=n CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n CONFIG_BT_CTLR_SCAN_REQ_RSSI=n +CONFIG_BT_CTLR_OPTIMIZE_FOR_APP_DEFAULT=y CONFIG_BT_CTLR_PROFILE_ISR=n CONFIG_BT_CTLR_DEBUG_PINS=n CONFIG_BT_HCI_VS=y diff --git a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf index b65082eb70f6f4..920a9f088609ec 100644 --- a/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_5_x_dbg.conf @@ -41,6 +41,7 @@ CONFIG_BT_CTLR_SYNC_ISO_RESERVE_MAX=n CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX=n CONFIG_BT_CTLR_CIS_ACCEPT_MIN_OFFSET_STRICT=y CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX=n +CONFIG_BT_CTLR_OPTIMIZE_FOR_SIZE=y CONFIG_BT_CTLR_PROFILE_ISR=y CONFIG_BT_CTLR_DEBUG_PINS=y CONFIG_BT_CTLR_TEST=y diff --git a/tests/bluetooth/init/prj_ctlr_dbg.conf b/tests/bluetooth/init/prj_ctlr_dbg.conf index 1b32cbf6dc99e0..386e81a33f9192 100644 --- a/tests/bluetooth/init/prj_ctlr_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_dbg.conf @@ -31,6 +31,7 @@ CONFIG_BT_CTLR_ADV_INDICATION=y CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=y CONFIG_BT_CTLR_SCAN_REQ_RSSI=y CONFIG_BT_CTLR_SCAN_INDICATION=y +CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED=y CONFIG_BT_CTLR_PROFILE_ISR=y CONFIG_BT_CTLR_DEBUG_PINS=y CONFIG_BT_CTLR_TEST=y From e92133c1f3ba68a6a73aa8a670cebc76bb80bdd4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1204/1389] samples: Bluetooth: hci_ipc: Use LTO when building ISO features Use Link Time Optimisation (LTO) when building Controller with Isochronous channels support. nRF53x SoCs has 256KB flash and using speed optimisation, which is the default today, overflows flash when adding new features related to ISO support. Signed-off-by: Vinayak Kariappa Chettimada --- .../bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 3377273dd9ab63..8fbd3d3af2dcc5 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -9,6 +9,9 @@ CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 CONFIG_HEAP_MEM_POOL_SIZE=8192 CONFIG_CBPRINTF_REDUCED_INTEGRAL=y +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y +CONFIG_LTO=y + CONFIG_BT=y CONFIG_BT_HCI_RAW=y CONFIG_BT_MAX_CONN=2 From 29622d93d4f0c441864939cb87ff667fc3506965 Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1205/1389] boards: fvp_baser_armv8r: add missing SMP variant ARMFVP configuration was not defined for SMP variants leading to test failure. Signed-off-by: Wilfried Chauveau --- boards/arm/fvp_baser_aemv8r/board.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/boards/arm/fvp_baser_aemv8r/board.cmake b/boards/arm/fvp_baser_aemv8r/board.cmake index f7753bc5099b17..8f5b70f5f330db 100644 --- a/boards/arm/fvp_baser_aemv8r/board.cmake +++ b/boards/arm/fvp_baser_aemv8r/board.cmake @@ -5,7 +5,8 @@ set(SUPPORTED_EMU_PLATFORMS armfvp) set(ARMFVP_BIN_NAME FVP_BaseR_AEMv8R) set(ARMFVP_MIN_VERSION 11.16.16) -if(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64) +if(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64 OR + CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64_SMP) set(ARMFVP_FLAGS -C cluster0.has_aarch64=1 -C cluster0.VMSA_supported=0 @@ -38,7 +39,8 @@ if(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64) -C bp.vis.rate_limit-enable=0 -C cache_state_modelled=1 ) -elseif(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH32) +elseif(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH32 OR + CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH32_SMP) set(ARMFVP_FLAGS -C cluster0.has_aarch64=0 -C cluster0.VMSA_supported=0 From 4d2805da9c81cd9b1a34178e3a53a71c8cac03b5 Mon Sep 17 00:00:00 2001 From: Conor Paxton Date: Sun, 26 May 2024 22:39:31 +0200 Subject: [PATCH 1206/1389] boards: microchip: add icicle kit smp variant With the introduction of the new Hardware model, we now have an easy method to describe variants of boards. This is especially helpful for Microchip's PolarFire SoC Icicle Kit which has a heterogeneous core-complex. Introduce an SMP capable variant with four SMP capable harts for the SMP cluster and disables the e51 monitor hart Signed-off-by: Conor Paxton --- boards/microchip/mpfs_icicle/board.yml | 2 + boards/microchip/mpfs_icicle/doc/index.rst | 5 + .../microchip/mpfs_icicle/mpfs_icicle_smp.dts | 94 +++++++++++++++++++ .../mpfs_icicle/mpfs_icicle_smp.yaml | 12 +++ .../mpfs_icicle/mpfs_icicle_smp_defconfig | 14 +++ 5 files changed, 127 insertions(+) create mode 100644 boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts create mode 100644 boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml create mode 100644 boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig diff --git a/boards/microchip/mpfs_icicle/board.yml b/boards/microchip/mpfs_icicle/board.yml index a4976aa909b429..f97e2409c14cd4 100644 --- a/boards/microchip/mpfs_icicle/board.yml +++ b/boards/microchip/mpfs_icicle/board.yml @@ -3,3 +3,5 @@ board: vendor: microchip socs: - name: polarfire + variants: + - name: 'smp' diff --git a/boards/microchip/mpfs_icicle/doc/index.rst b/boards/microchip/mpfs_icicle/doc/index.rst index 7a599081793c47..203745dc4eeb36 100644 --- a/boards/microchip/mpfs_icicle/doc/index.rst +++ b/boards/microchip/mpfs_icicle/doc/index.rst @@ -23,6 +23,11 @@ Applications for the ``mpfs_icicle`` board configuration can be built as usual :board: mpfs_icicle :goals: build +To build the default SMP capable variant + +.. zephyr-app-commands:: + :board: mpfs_icicle/polarfire/smp + :goals: build Flashing ======== diff --git a/boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts new file mode 100644 index 00000000000000..6d122ed5d97b75 --- /dev/null +++ b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020-2021 Microchip Technology Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "Microchip PolarFire-SoC Icicle Kit"; + compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs"; + + cpus { + cpu@0 { + status = "disabled"; + }; + }; + + aliases { + led0 = &led0; + sw0 = &sw0; + i2c0 = &i2c0; + i2c1 = &i2c1; + }; + + chosen { + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + zephyr,sram = &sram1; + }; + + leds { + compatible = "gpio-leds"; + + led0: led0 { + gpios = <&gpio2 16 GPIO_ACTIVE_LOW>; + label = "LED_0"; + }; + }; + + keys { + compatible = "gpio-keys"; + sw0: sw0 { + gpios = <&gpio2 30 GPIO_ACTIVE_LOW>; + label = "SW_0"; + zephyr,code = ; + }; + }; +}; + +&uart1 { + status = "okay"; + current-speed = <115200>; + clock-frequency = <150000000>; +}; + +&qspi0 { + status = "okay"; + qspi_flash: spi-nor-flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <5000000>; + size = ; + jedec-id = [20 ba 19]; + }; +}; + +&spi1 { + status = "okay"; +}; + +&syscontroller_qspi { + status = "okay"; + sys_ctrl_flash: spi-nor-flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <5000000>; + }; +}; + +&gpio2 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; diff --git a/boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml new file mode 100644 index 00000000000000..2f7983ca092929 --- /dev/null +++ b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml @@ -0,0 +1,12 @@ +identifier: mpfs_icicle/polarfire/smp +name: Microchip PolarFire ICICLE kit (SMP) +type: mcu +arch: riscv +toolchain: + - zephyr +ram: 3840 +testing: + ignore_tags: + - net + - bluetooth +vendor: microchip diff --git a/boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig b/boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig new file mode 100644 index 00000000000000..529171d1c46daf --- /dev/null +++ b/boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig @@ -0,0 +1,14 @@ +CONFIG_MPFS_HAL=n +CONFIG_BASE64=y +CONFIG_INCLUDE_RESET_VECTOR=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_XIP=n +CONFIG_INIT_STACKS=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_GPIO=y +CONFIG_I2C=y +CONFIG_SMP=y +CONFIG_RV_BOOT_HART=1 +CONFIG_MP_MAX_NUM_CPUS=4 From 601767c2acbad0a48df5615a943476674943e9e8 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1207/1389] arch/xtensa: Add automatic vector linkage generation Existing solutions for linking the Xtensa vector table are a cut-and-paste mess of inherited code, with more than a dozen special sections that need to be linked into many special MEMORY{} regions. Accept the existing convention used by C/asm code, but automatically detect the needed offsets for the platform from core-isa.h (it can share the preprocessing with gen_zsr.py) and emit a file that can be included in lieu of all the existing boilerplate. Signed-off-by: Andy Ross --- arch/xtensa/core/CMakeLists.txt | 8 +++ arch/xtensa/core/gen_vectors.py | 122 ++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100755 arch/xtensa/core/gen_vectors.py diff --git a/arch/xtensa/core/CMakeLists.txt b/arch/xtensa/core/CMakeLists.txt index 40906a0a3262b4..4c2ce8173ca597 100644 --- a/arch/xtensa/core/CMakeLists.txt +++ b/arch/xtensa/core/CMakeLists.txt @@ -103,3 +103,11 @@ add_custom_command( add_custom_target(xtensa_handlers_h DEPENDS ${HANDLERS}.h) add_dependencies(zephyr_interface xtensa_handlers_h) + +# Auto-generate interrupt vector entry +set(VECS_LD ${CMAKE_BINARY_DIR}/zephyr/include/generated/xtensa_vectors.ld) +add_custom_command(OUTPUT ${VECS_LD} DEPENDS ${CORE_ISA_DM} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_vectors.py + ${CORE_ISA_DM} > ${VECS_LD}) +add_custom_target(xtensa_vectors_ld DEPENDS ${VECS_LD}) +add_dependencies(zephyr_interface xtensa_vectors_ld) diff --git a/arch/xtensa/core/gen_vectors.py b/arch/xtensa/core/gen_vectors.py new file mode 100755 index 00000000000000..e9e60e30fe5296 --- /dev/null +++ b/arch/xtensa/core/gen_vectors.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 +import sys +import re + +# Xtensa Vector Table linker generator +# +# Takes a pre-processed (gcc -dM) core-isa.h file as its first +# argument, and emits a GNU linker section declartion which will +# correctly load the exception vectors and literals as long as their +# code is declared using standard conventions (see below). +# +# The section name will be ".z_xtensa_vectors", and a symbol +# "z_xtensa_vecbase" is emitted containing a valid value for the +# VECBASE SR at runtime. +# +# Obviously, this requires that XCHAL_HAVE_VECBASE=1. A similar trick +# could be played to load vectors at fixed addresses on hardware that +# lacks VECBASE, but the core-isa.h interface is inexplicably +# different. +# +# Because the "standard conventions" (which descend from somewhere in +# Cadence) are not documented anywhere and just end up cut and pasted +# between devices, here's an attempt at a specification: +# +# + The six register window exception vectors are defined with offsets +# internal to their assembly code. They are linked in a single +# section named ".WindowVectors.text". +# +# + The "kernel", "user" and "double exception" vectors are emitted in +# sections named ".KernelExceptionVector.text", +# "UserExceptionVector.text" and "DoubleExceptionVector.text" +# respectively. +# +# + XEA2 interrupt vectors are in sections named +# ".LevelInterruptVector.text", except (!) for ones which are +# given special names. The "debug" and "NMI" interrupts (if they +# exist) are technically implemented as standard interrupt vectors +# (of a platform-dependent level), but the code for them is emitted +# in ".DebugExceptionVector.text" and ".NMIExceptionVector.text", +# and not a section corresponding to their interrupt level. +# +# + Any unused bytes at the end of a vector are made available as +# storage for immediate values used by the following vector (Xtensa +# can only back-reference immediates for MOVI/L32R instructions) as +# a "Vector.literal" section. Note that there is no guarantee +# of how much space is available, it depends on the previous +# vector's code size. Zephyr code has historically not used this +# space, as support in existing linker scripts is inconsistent. But +# it's exposed here. + +coreisa = sys.argv[1] + +debug_level = 0 + +# Translation for the core-isa.h vs. linker section naming conventions +sect_names = { "DOUBLEEXC" : "DoubleException", + "KERNEL" : "KernelException", + "NMI" : "NMIException", + "USER" : "UserException" } + +offsets = {} + +with open(coreisa) as infile: + for line in infile.readlines(): + m = re.match(r"^#define\s+XCHAL_([^ ]+)_VECOFS\s*(.*)", line.rstrip()) + if m: + (sym, val) = (m.group(1), m.group(2)) + if sym == "WINDOW_OF4": + # This must be the start of the section + assert eval(val) == 0 + elif sym.startswith("WINDOW"): + # Ignore the other window exceptions, they're internally sorted + pass + elif sym == "RESET": + # Ignore, not actually part of the vector table + pass + elif sym == "DEBUG": + # This one is a recursive macro that doesn't expand, + # so handle manually + m = re.match(r"XCHAL_INTLEVEL(\d+)_VECOFS", val) + if not m: + print(f"no intlevel match for debug val {val}") + assert m + debug_level = eval(m.group(1)) + else: + if val == "XCHAL_NMI_VECOFS": + # This gets recursively defined in the other + # direction, so ignore the INTLEVEL + pass + else: + addr = eval(val) + m = re.match(r"^INTLEVEL(\d+)", sym) + if m: + offsets[f"Level{m.group(1)}Interrupt"] = addr + else: + offsets[sect_names[sym]] = addr + +if debug_level > 0: + old = f"Level{debug_level}Interrupt" + offsets[f"DebugException"] = offsets[old] + del offsets[old] + +sects = list(offsets) +sects.sort(key=lambda s: offsets[s]) + +print("/* Automatically Generated Code - Do Not Edit */") +print("/* See arch/xtensa/core/gen_vector.py */") +print("") + +# The 1k alignment is experimental, the docs on the Relocatable Vector +# Option doesn't specify an alignment at all, but writes to the +# bottom bits don't take... +print( " .z_xtensa_vectors : ALIGN(1024) {") +print( " z_xtensa_vecbase = .;") +print(f" KEEP(*(.WindowVectors.text));") +for s in sects: + print(f" KEEP(*(.{s}Vector.literal));") + print( " . = 0x%3.3x;" % (offsets[s])) + print(f" KEEP(*(.{s}Vector.text));") +print(" }") From 30eeaf59c5091705e0c13f40e95a7587a51e1e4b Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1208/1389] soc/qemu_xtensa_dc233c: Use the automatically-generated vector region Remove all the hard-configured absolute addresses and zillions of tiny ELF segments in favor of the auto-generated vector region, which is guaranteed correct as long as core-isa.h is matched to the target. Signed-off-by: Andy Ross --- soc/cdns/dc233c/include/xtensa-dc233c.ld | 176 +---------------------- 1 file changed, 5 insertions(+), 171 deletions(-) diff --git a/soc/cdns/dc233c/include/xtensa-dc233c.ld b/soc/cdns/dc233c/include/xtensa-dc233c.ld index b77effc032bd3f..87ad18b54246c5 100644 --- a/soc/cdns/dc233c/include/xtensa-dc233c.ld +++ b/soc/cdns/dc233c/include/xtensa-dc233c.ld @@ -45,25 +45,7 @@ MEMORY { - sram0_0_seg : org = 0x00002000, len = 0x178 - sram0_1_seg : org = 0x00002178, len = 0x8 - sram0_2_seg : org = 0x00002180, len = 0x38 - sram0_3_seg : org = 0x000021B8, len = 0x8 - sram0_4_seg : org = 0x000021C0, len = 0x38 - sram0_5_seg : org = 0x000021F8, len = 0x8 - sram0_6_seg : org = 0x00002200, len = 0x38 - sram0_7_seg : org = 0x00002238, len = 0x8 - sram0_8_seg : org = 0x00002240, len = 0x38 - sram0_9_seg : org = 0x00002278, len = 0x8 - sram0_10_seg : org = 0x00002280, len = 0x38 - sram0_11_seg : org = 0x000022B8, len = 0x8 - sram0_12_seg : org = 0x000022C0, len = 0x38 - sram0_13_seg : org = 0x000022F8, len = 0x8 - sram0_14_seg : org = 0x00002300, len = 0x38 - sram0_15_seg : org = 0x00002338, len = 0x8 - sram0_16_seg : org = 0x00002340, len = 0x38 - sram0_17_seg : org = 0x00002378, len = 0x48 - sram0_18_seg : org = 0x000023C0, len = 0x40 + vectors : org = 0x00002000, len = 0x2400 #ifdef CONFIG_XTENSA_MMU vec_helpers : org = 0x00002400, len = (PHYS_RAM_ADDR - 0x00002400) #endif @@ -87,26 +69,7 @@ MEMORY PHDRS { - sram0_0_phdr PT_LOAD; - sram0_1_phdr PT_LOAD; - sram0_2_phdr PT_LOAD; - sram0_3_phdr PT_LOAD; - sram0_4_phdr PT_LOAD; - sram0_5_phdr PT_LOAD; - sram0_6_phdr PT_LOAD; - sram0_7_phdr PT_LOAD; - sram0_8_phdr PT_LOAD; - sram0_9_phdr PT_LOAD; - sram0_10_phdr PT_LOAD; - sram0_11_phdr PT_LOAD; - sram0_12_phdr PT_LOAD; - sram0_13_phdr PT_LOAD; - sram0_14_phdr PT_LOAD; - sram0_15_phdr PT_LOAD; - sram0_16_phdr PT_LOAD; - sram0_17_phdr PT_LOAD; - sram0_18_phdr PT_LOAD; - + vectors_phdr PT_LOAD; #ifdef CONFIG_XTENSA_MMU vec_helpers_phdr PT_LOAD; #endif @@ -154,138 +117,9 @@ SECTIONS #include #endif - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >sram0_0_seg :sram0_0_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >sram0_1_seg :sram0_1_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >sram0_2_seg :sram0_2_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >sram0_3_seg :sram0_3_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >sram0_4_seg :sram0_4_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >sram0_5_seg :sram0_5_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >sram0_6_seg :sram0_6_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >sram0_7_seg :sram0_7_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >sram0_8_seg :sram0_8_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >sram0_9_seg :sram0_9_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >sram0_10_seg :sram0_10_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >sram0_11_seg :sram0_11_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >sram0_12_seg :sram0_12_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >sram0_13_seg :sram0_13_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >sram0_14_seg :sram0_14_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >sram0_15_seg :sram0_15_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >sram0_16_seg :sram0_16_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >sram0_17_seg :sram0_17_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >sram0_18_seg :sram0_18_phdr +/* Auto-generated vector linkage, to "vectors" memory region */ +#include + >vectors :vectors_phdr #define LIB_OBJ_FUNC_IN_SECT(library, obj_file, func) \ *##library##:##obj_file##(.literal.##func .text.##func) \ From db4ff6f6e10fb8567566ac7ed941e5585e85d2ac Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1209/1389] manifest: Update nRF hw models to latest Update the HW models module to: 36b12714a5ed32450d907c89bb118f6280da3483 Including the following: * 36b1271 54L15: Added RRAMC, RRAM & UICR * b60af23 FICR 54L: Added first version Signed-off-by: Alberto Escolar Piedras --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 4349b0d9d41ce5..601719200b031d 100644 --- a/west.yml +++ b/west.yml @@ -295,7 +295,7 @@ manifest: groups: - tools - name: nrf_hw_models - revision: 5d638052c9fe1ef3bd7638067354eba4d3f2fa78 + revision: 36b12714a5ed32450d907c89bb118f6280da3483 path: modules/bsim_hw_models/nrf_hw_models - name: open-amp revision: da78aea63159771956fe0c9263f2e6985b66e9d5 From e2fddf8081bbac6d0d45faa66fb7e704006cf2e0 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1210/1389] drivers/flash/ nrf RRAM: Support simulated targets In simulated targets the RRAM is not allocated starting at address 0x0, but on an area allocated at runtime. Let's support this, to enable running the real RRAM driver for simulated targets. Signed-off-by: Alberto Escolar Piedras --- drivers/flash/soc_flash_nrf_rram.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/flash/soc_flash_nrf_rram.c b/drivers/flash/soc_flash_nrf_rram.c index b8ab3afa8feb2b..9e5e652ca5ed55 100644 --- a/drivers/flash/soc_flash_nrf_rram.c +++ b/drivers/flash/soc_flash_nrf_rram.c @@ -41,7 +41,11 @@ LOG_MODULE_REGISTER(flash_nrf_rram, CONFIG_FLASH_LOG_LEVEL); #define RRAM DT_INST(0, soc_nv_flash) +#if defined(CONFIG_SOC_SERIES_BSIM_NRFXX) +#define RRAM_START NRF_RRAM_BASE_ADDR +#else #define RRAM_START DT_REG_ADDR(RRAM) +#endif #define RRAM_SIZE DT_REG_SIZE(RRAM) #define PAGE_SIZE DT_PROP(RRAM, erase_block_size) From 4ad81c2e904a0439bff97796499a74ed0a8c9b1a Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1211/1389] boards nrf54l15bsim: Enable RRAMC and add storage partition The RRAMC is now supported by the HW models. Let's enable the RRAM controller, and add a storage partition definition which tests and samples can use by default. Signed-off-by: Alberto Escolar Piedras --- .../nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts index 994af625bcbbaf..ff4aef337f25dc 100644 --- a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -15,6 +15,8 @@ chosen { zephyr,entropy = &rng; + zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; }; /delete-node/ cpus; @@ -22,8 +24,6 @@ /delete-node/ sw-pwm; soc { - /delete-node/ uicr@ffd000; - /delete-node/ ficr@ffc000; /delete-node/ memory@20000000; /delete-node/ memory@2002f000; peripheral@50000000 { @@ -62,7 +62,6 @@ /delete-node/ gpiote@10c000; /delete-node/ clock@10e000; }; - /delete-node/ rram-controller@5004b000; /delete-node/ spu@50003000; /delete-node/ gpiote@5000d000; /delete-node/ crypto@50844000; @@ -81,6 +80,18 @@ status = "okay"; }; +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + storage_partition: partition@0 { + label = "storage"; + reg = <0x0 DT_SIZE_K(500)>; + }; + }; +}; + &temp { status = "okay"; }; From 410c7be223bf0f286267e39cf6b96765d794ee08 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1212/1389] boards nrf54l15bsim: Update docs with RRAMC, FICR and UICR mention This board HW models now include the RRAMC, FICR and UICR. Let's update the docs accordingly. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/doc/nrf54l15bsim.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/boards/native/nrf_bsim/doc/nrf54l15bsim.rst b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst index 8440d76384d0bd..702ff50f85170b 100644 --- a/boards/native/nrf_bsim/doc/nrf54l15bsim.rst +++ b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst @@ -38,18 +38,21 @@ This boards include models of some of the nRF54L15 SOC peripherals: * DPPI (Distributed Programmable Peripheral Interconnect) * EGU (Event Generator Unit) +* FICR (Factory Information Configuration Registers) * GRTC (Global Real-time Counter) * PPIB (PPI Bridge) +* RRAMC (Resistive RAM Controller) * RTC (Real Time Counter) * TEMP (Temperature sensor) * TIMER +* UICR (User Information Configuration Registers) and will use the same drivers as the nrf54l15pdk targets for these. For more information on what is modeled to which level of detail, check the `HW models implementation status`_. -Note that unlike a real nrf54l15 device, the nrf54l15bsim boards have unlimited RAM and flash for -code. +Note that unlike a real nrf54l15 device, the nrf54l15bsim boards have unlimited RAM, and code does +not occupy their RRAM. .. _BabbleSim: https://BabbleSim.github.io From 2d34a749a1c03285967a81a2a355dce43bcd306c Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1213/1389] Bluetooth samples: Fix broadcast source device name The device name explicitly added in the advertising data. Signed-off-by: Jens Rehhoff Thomsen --- .../broadcast_audio_source/src/main.c | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/samples/bluetooth/broadcast_audio_source/src/main.c b/samples/bluetooth/broadcast_audio_source/src/main.c index dee7de02a8a32a..e6f2c85b8b4968 100644 --- a/samples/bluetooth/broadcast_audio_source/src/main.c +++ b/samples/bluetooth/broadcast_audio_source/src/main.c @@ -432,10 +432,6 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source) return 0; } -static const struct bt_data ad[] = { - BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), -}; - int main(void) { struct bt_le_ext_adv *adv; @@ -493,7 +489,7 @@ int main(void) NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); NET_BUF_SIMPLE_DEFINE(base_buf, 128); - struct bt_data ext_ad; + struct bt_data ext_ad[2]; struct bt_data per_ad; uint32_t broadcast_id; @@ -505,12 +501,6 @@ int main(void) return 0; } - err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0); - if (err) { - printk("Failed to set advertising data (err %d)\n", err); - return 0; - } - /* Set periodic advertising parameters */ err = bt_le_per_adv_set_param(adv, BT_LE_PER_ADV_DEFAULT); if (err) { @@ -535,10 +525,12 @@ int main(void) /* Setup extended advertising data */ net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); net_buf_simple_add_le24(&ad_buf, broadcast_id); - ext_ad.type = BT_DATA_SVC_DATA16; - ext_ad.data_len = ad_buf.len; - ext_ad.data = ad_buf.data; - err = bt_le_ext_adv_set_data(adv, &ext_ad, 1, NULL, 0); + ext_ad[0].type = BT_DATA_SVC_DATA16; + ext_ad[0].data_len = ad_buf.len; + ext_ad[0].data = ad_buf.data; + ext_ad[1] = (struct bt_data)BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, + sizeof(CONFIG_BT_DEVICE_NAME) - 1); + err = bt_le_ext_adv_set_data(adv, ext_ad, 2, NULL, 0); if (err != 0) { printk("Failed to set extended advertising data: %d\n", err); From 1da1b16c705a5a3f8c2df58bcfc075a35e351dea Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1214/1389] tests/posix/env: Remove arch posix filter This test runs fine in "native" targets based on the toolchain and C library filtering. As there is no need to exclude this architecture, let's remove the exclusion to improve coverage. Signed-off-by: Alberto Escolar Piedras --- tests/posix/env/testcase.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/posix/env/testcase.yaml b/tests/posix/env/testcase.yaml index 305fdfff5f8dcc..4648743bbafa7d 100644 --- a/tests/posix/env/testcase.yaml +++ b/tests/posix/env/testcase.yaml @@ -1,7 +1,5 @@ common: filter: not CONFIG_NATIVE_LIBC - arch_exclude: - - posix integration_platforms: - qemu_riscv64 tags: posix From 3e331c1a526202a92d5a3885f2631c135a6d6b2d Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1215/1389] doc: Add missing ABNF macros for child num MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 5871ff010b4d2b27e4a27d7580a2b912f1044cb8 added support for generated DT macros to get the number of child nodes of a node, but we forgot to update the documentation of the augmented Backus–Naur form of the DT macros to reflect this addition. Signed-off-by: Declan Snyder --- doc/build/dts/macros.bnf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/build/dts/macros.bnf b/doc/build/dts/macros.bnf index f42f483887749c..88ed70f2ba9506 100644 --- a/doc/build/dts/macros.bnf +++ b/doc/build/dts/macros.bnf @@ -73,6 +73,9 @@ node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM" node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_SEP" node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_VARGS" node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_SEP_VARGS" +; These are used by DT_CHILD_NUM and DT_CHILD_NUM_STATUS_OKAY macros +node-macro =/ %s"DT_N" path-id %s"_CHILD_NUM" +node-macro =/ %s"DT_N" path-id %s"_CHILD_NUM_STATUS_OKAY" ; These are used internally by DT_FOREACH_CHILD, which iterates over ; each child node. node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD" From 65b364fc6afa05199ef52956ef1f8072201e6976 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1216/1389] wifi: shell: Support configuration of timeout in connect command Add support for configuring timeout in `wifi connect` command. Signed-off-by: Ravi Dondaputi --- subsys/net/l2/wifi/wifi_shell.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index a25a4b37e505bb..ab2637a1271a37 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -457,6 +457,7 @@ static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv {"bssid", required_argument, 0, 'm'}, {"band", required_argument, 0, 'b'}, {"channel", required_argument, 0, 'c'}, + {"timeout", required_argument, 0, 't'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; int opt_index = 0; @@ -477,7 +478,8 @@ static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv params->security = WIFI_SECURITY_TYPE_NONE; params->mfp = WIFI_MFP_OPTIONAL; - while ((opt = getopt_long(argc, argv, "s:p:k:w:b:c:m:h", long_options, &opt_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:p:k:w:b:c:m:t:h", + long_options, &opt_index)) != -1) { state = getopt_state_get(); switch (opt) { case 's': @@ -563,6 +565,15 @@ static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv ¶ms->bssid[2], ¶ms->bssid[3], ¶ms->bssid[4], ¶ms->bssid[5]); break; + case 't': + if (iface_mode == WIFI_MODE_INFRA) { + params->timeout = strtol(optarg, &endptr, 10); + if (*endptr != '\0') { + PR_ERROR("Invalid timeout: %s\n", optarg); + return -EINVAL; + } + } + break; case 'h': return -ENOEXEC; default: @@ -1920,6 +1931,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands, "[-w, --ieee-80211w]: MFP (optional: needs security type to be specified)\n" ": 0:Disable, 1:Optional, 2:Required.\n" "[-m, --bssid]: MAC address of the AP (BSSID).\n" + "[-t, --timeout]: Timeout for the connection attempt (in seconds).\n" "[-h, --help]: Print out the help for the connect command.\n", cmd_wifi_connect, 2, 7), From 0e60e73441efe6079337168069f2cc4f323f053d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1217/1389] boards: renesas: da1469x_dk_pro: Update SPI pins Two pins assigned to SPI controller (P0_22,P0_23) are dedicated to XTAL32K which is present on devkit. For this reason SPI function are re-assigned to pins available on optional header MikorBUS 1 to match configuration of SPI2 which is routed to MikorBUS 2 header. Signed-off-by: Jerzy Kasenberg --- boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi index 60d7fb98c56b88..0a90af9a63cf4a 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi @@ -64,12 +64,12 @@ spi_controller: spi_controller { group1 { - pinmux = , - ; + pinmux = , + ; output-enable; }; group2 { - pinmux = ; + pinmux = ; input-enable; }; }; From beaeb56a7cd1482797666b619f4422dc75789600 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1218/1389] drivers: nsos: propagate POLLHUP from host's epoll() This flag is set in case socket was closed, so propagate it as well. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_adapt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index a9b5fb1b33fb04..af9acd1e40e7ee 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -752,6 +752,7 @@ static int nsos_poll_to_epoll_events(int events_from) MAP_POLL_EPOLL(POLLIN, EPOLLIN); MAP_POLL_EPOLL(POLLOUT, EPOLLOUT); MAP_POLL_EPOLL(POLLERR, EPOLLERR); + MAP_POLL_EPOLL(POLLHUP, EPOLLHUP); return events_to; } @@ -763,6 +764,7 @@ static int nsos_epoll_to_poll_events(int events_from) MAP_POLL_EPOLL(EPOLLIN, POLLIN); MAP_POLL_EPOLL(EPOLLOUT, POLLOUT); MAP_POLL_EPOLL(EPOLLERR, POLLERR); + MAP_POLL_EPOLL(EPOLLHUP, POLLHUP); return events_to; } From 3095b0ed72a201c1e6d7087d1849b668ba714225 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1219/1389] drivers: nsos: fix nsos_sendmsg() error code There is a goto statement with conversion using errno_from_nsos_mid(). Use NSOS_MID_ERRNO instead of ERRNO to return proper error code. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 54b1af8b246135..d8382df4bc779c 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -708,7 +708,7 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) msg_iov = k_calloc(msg->msg_iovlen, sizeof(*msg_iov)); if (!msg_iov) { - ret = -ENOMEM; + ret = -NSOS_MID_ENOMEM; goto return_ret; } From 9a9959f008ebe195fd3bbe455caffd3038628b40 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1220/1389] drivers: nsos: set errno on failed z_reserve_fd() Just propagate proper error code, which is the negated return value from z_reserve_fd(). Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index d8382df4bc779c..7050c962a14c20 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -624,6 +624,7 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) zephyr_fd = z_reserve_fd(); if (zephyr_fd < 0) { + errno = -zephyr_fd; goto close_adapt_fd; } From 70b7d7e42de76b07def9068399174bf91a4a28ae Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1221/1389] drivers: nsos: fix ENOMEM return from ZFD_IOCTL_POLL_PREPARE ioctl() API expects error codes to be returned as negative value directly, instead of using 'errno'. Fix ZFD_IOCTL_POLL_PREPARE handling to respect that. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 7050c962a14c20..1c7df2af830d9d 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -265,8 +265,7 @@ static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, sock->pollfd.cb = pollcb; if (*pev == pev_end) { - errno = ENOMEM; - return -1; + return -ENOMEM; } k_poll_signal_init(&sock->poll); From f9d53e7b1ab550aceea8074318c4c2132f455445 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1222/1389] west: updated west.yml to grab ke15z Pinctrl definitions Updated the west.yml file to add pinctrl support required for the frdm_ke15z board. Signed-off-by: Emilio Benavente Signed-off-by: Pavel Krenek --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 601719200b031d..c6ff13bd6bf9f2 100644 --- a/west.yml +++ b/west.yml @@ -193,7 +193,7 @@ manifest: groups: - hal - name: hal_nxp - revision: abc66979c77421fb3a140ce2e4e6ea7165cdbe8f + revision: 57d844b03ea545aa702ae99d9777481709ba8aa4 path: modules/hal/nxp groups: - hal From f9b148717f0bdf015330ffacb092a22e8e20cf40 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Sun, 26 May 2024 22:39:32 +0200 Subject: [PATCH 1223/1389] dts: arm: nxp: nxp_ke1xz: added dts file. Added required dts file to support frdm_ke1xz platforms. Signed-off-by: Emilio Benavente Signed-off-by: Pavel Krenek --- dts/arm/nxp/nxp_ke1xz.dtsi | 235 ++++++++++++++++++++++++ dts/bindings/gpio/nxp,gpio-cluster.yaml | 9 + 2 files changed, 244 insertions(+) create mode 100644 dts/arm/nxp/nxp_ke1xz.dtsi create mode 100644 dts/bindings/gpio/nxp,gpio-cluster.yaml diff --git a/dts/arm/nxp/nxp_ke1xz.dtsi b/dts/arm/nxp/nxp_ke1xz.dtsi new file mode 100644 index 00000000000000..5f6b08f5dc0784 --- /dev/null +++ b/dts/arm/nxp/nxp_ke1xz.dtsi @@ -0,0 +1,235 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "armv6-m.dtsi" +#include +#include +#include + +/ { + chosen { + zephyr,flash-controller = &ftfe; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m0+"; + clock-frequency = <48000000>; + reg = <0>; + }; + }; + + sram_l: memory@1fffe000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x1FFFE000 DT_SIZE_K(8)>; + zephyr,memory-region = "SRAML"; + }; + + sram_u: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(24)>; + zephyr,memory-region = "SRAMU"; + }; + + pinctrl: pinctrl { + compatible = "nxp,kinetis-pinctrl"; + }; + + soc { + scg: scg@40064000 { + sosc-mode = ; + compatible = "nxp,kinetis-scg"; + reg = <0x40064000 0x1000>; + #clock-cells = <1>; + + sirc_clk: sirc_clk { + compatible = "fixed-clock"; + clock-frequency = <8000000>; + #clock-cells = <0>; + }; + + firc_clk: firc_clk { + compatible = "fixed-clock"; + clock-frequency = <48000000>; + #clock-cells = <0>; + }; + + core_clk: core_clk { + compatible = "fixed-factor-clock"; + clocks = <&firc_clk>; + clock-div = <1>; + #clock-cells = <0>; + }; + + bus_clk: bus_clk { + compatible = "fixed-factor-clock"; + clocks = <&core_clk>; + clock-div = <4>; + #clock-cells = <0>; + }; + + sircdiv2_clk: sircdiv2_clk { + compatible = "fixed-factor-clock"; + clocks = <&sirc_clk>; + clock-div = <2>; + #clock-cells = <0>; + }; + + fircdiv2_clk: fircdiv2_clk { + compatible = "fixed-factor-clock"; + clocks = <&firc_clk>; + clock-div = <1>; + #clock-cells = <0>; + }; + }; + + pcc: pcc@40065000 { + compatible = "nxp,kinetis-pcc"; + reg = <0x40065000 0x1000>; + #clock-cells = <2>; + }; + + ftfe: flash-controller@40020000 { + compatible = "nxp,kinetis-ftfe"; + reg = <0x40020000 0x1000>; + interrupts = <5 0>; + interrupt-names = "command-complete"; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 DT_SIZE_K(256)>; + erase-block-size = ; + write-block-size = <8>; + }; + }; + + lpuart0: uart@4006a000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4006a000 0x1000>; + interrupts = <12 0>; + clocks = <&pcc 0x1a8 KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + lpuart1: uart@4006b000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4006b000 0x1000>; + interrupts = <13 0>; + clocks = <&pcc 0x1ac KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + lpuart2: uart@4006c000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4006c000 0x1000>; + interrupts = <14 0>; + clocks = <&pcc 0x1b0 KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + porta: pinmux@40049000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x40049000 0x1000>; + clocks = <&pcc 0x124 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + portb: pinmux@4004a000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004a000 0x1000>; + clocks = <&pcc 0x128 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + portc: pinmux@4004b000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004b000 0x1000>; + clocks = <&pcc 0x12c KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + portd: pinmux@4004c000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004c000 0x1000>; + clocks = <&pcc 0x130 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + porte: pinmux@4004d000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004d000 0x1000>; + clocks = <&pcc 0x134 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + gpios0: gpios0 { + compatible = "nxp,gpio-cluster"; + interrupts = <7 2>; + + #address-cells = <1>; + #size-cells = <1>; + + gpioa: gpio@400ff000 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x400ff000 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&porta>; + }; + + gpioe: gpio@400ff100 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x400ff100 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&porte>; + }; + }; + + gpios1: gpios1 { + compatible = "nxp,gpio-cluster"; + interrupts = <26 2>; + + #address-cells = <1>; + #size-cells = <1>; + + gpiob: gpio@400ff040 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x400ff040 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&portb>; + }; + + gpioc: gpio@400ff080 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x400ff080 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&portc>; + }; + + gpiod: gpio@400ff0c0 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x400ff0c0 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&portd>; + }; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <2>; +}; diff --git a/dts/bindings/gpio/nxp,gpio-cluster.yaml b/dts/bindings/gpio/nxp,gpio-cluster.yaml new file mode 100644 index 00000000000000..73f5de72ea2cda --- /dev/null +++ b/dts/bindings/gpio/nxp,gpio-cluster.yaml @@ -0,0 +1,9 @@ +description: A group of GPIOs that share an interrupt. + +compatible: "nxp,gpio-cluster" + +include: [base.yaml] + +properties: + interrupts: + required: true From 19f32c8b2d487977f56f714ec4dc72e1c1bf6209 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1224/1389] drivers: gpio_mcux: Support shared interrupts Updating the driver to support multiple ports sharing a single interrupt. Signed-off-by: Emilio Benavente --- drivers/gpio/gpio_mcux.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio_mcux.c b/drivers/gpio/gpio_mcux.c index 8fa48abc8c675b..f7d15e3cf0cba8 100644 --- a/drivers/gpio/gpio_mcux.c +++ b/drivers/gpio/gpio_mcux.c @@ -332,6 +332,40 @@ static void gpio_mcux_port_isr(const struct device *dev) gpio_fire_callbacks(&data->callbacks, dev, int_status); } +#define GPIO_HAS_SHARED_IRQ DT_HAS_COMPAT_STATUS_OKAY(nxp_gpio_cluster) + +#if GPIO_HAS_SHARED_IRQ +static void gpio_mcux_shared_cluster_isr(const struct device *ports[]) +{ + const struct device **current_port = &ports[0]; + + while (*current_port != NULL) { + gpio_mcux_port_isr(*current_port); + current_port++; + } +} + +#define CLUSTER_ARRAY_ELEMENT(node_id) DEVICE_DT_GET(node_id), + +#define GPIO_MCUX_CLUSTER_INIT(node_id) \ + const struct device *shared_array##node_id[DT_CHILD_NUM_STATUS_OKAY(node_id) + 1] = \ + {DT_FOREACH_CHILD_STATUS_OKAY(node_id, CLUSTER_ARRAY_ELEMENT) NULL}; \ + \ + static int gpio_mcux_shared_interrupt_init##node_id(void) \ + { \ + IRQ_CONNECT(DT_IRQN(node_id), \ + DT_IRQ(node_id, priority), \ + gpio_mcux_shared_cluster_isr, \ + shared_array##node_id, 0); \ + irq_enable(DT_IRQN(node_id)); \ + \ + return 0; \ + } \ + SYS_INIT(gpio_mcux_shared_interrupt_init##node_id, POST_KERNEL, 0); + +DT_FOREACH_STATUS_OKAY(nxp_gpio_cluster, GPIO_MCUX_CLUSTER_INIT) +#endif + #ifdef CONFIG_GPIO_GET_DIRECTION static int gpio_mcux_port_get_direction(const struct device *dev, gpio_port_pins_t map, gpio_port_pins_t *inputs, gpio_port_pins_t *outputs) @@ -388,7 +422,8 @@ static const struct gpio_driver_api gpio_mcux_driver_api = { }, \ .gpio_base = (GPIO_Type *) DT_INST_REG_ADDR(n), \ .port_base = (PORT_Type *) GPIO_PORT_BASE_ADDR(n), \ - .flags = UTIL_AND(DT_INST_IRQ_HAS_IDX(n, 0), GPIO_INT_ENABLE),\ + .flags = UTIL_AND(UTIL_OR(DT_INST_IRQ_HAS_IDX(n, 0), \ + GPIO_HAS_SHARED_IRQ), GPIO_INT_ENABLE), \ }; \ \ static struct gpio_mcux_data gpio_mcux_port## n ##_data; \ From 88c7fbe72a1704035fc1143c25be165930c3ac9b Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1225/1389] soc: nxp: kinetis: added soc support for ke1xz platforms. Adding supporting soc files for the ke1xz platforms updating soc.yaml and kinetis soc files to support ke1xz. Signed-off-by: Emilio Benavente Signed-off-by: Pavel Krenek --- soc/nxp/kinetis/common/pinctrl_soc.h | 10 +- soc/nxp/kinetis/ke1xz/CMakeLists.txt | 13 +++ soc/nxp/kinetis/ke1xz/Kconfig | 14 +++ soc/nxp/kinetis/ke1xz/Kconfig.defconfig | 28 +++++ soc/nxp/kinetis/ke1xz/Kconfig.soc | 37 ++++++ soc/nxp/kinetis/ke1xz/soc.c | 142 ++++++++++++++++++++++++ soc/nxp/kinetis/ke1xz/soc.h | 23 ++++ soc/nxp/kinetis/soc.yml | 3 + 8 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 soc/nxp/kinetis/ke1xz/CMakeLists.txt create mode 100644 soc/nxp/kinetis/ke1xz/Kconfig create mode 100644 soc/nxp/kinetis/ke1xz/Kconfig.defconfig create mode 100644 soc/nxp/kinetis/ke1xz/Kconfig.soc create mode 100644 soc/nxp/kinetis/ke1xz/soc.c create mode 100644 soc/nxp/kinetis/ke1xz/soc.h diff --git a/soc/nxp/kinetis/common/pinctrl_soc.h b/soc/nxp/kinetis/common/pinctrl_soc.h index d3a2ee0c02d02b..9caa7610b72116 100644 --- a/soc/nxp/kinetis/common/pinctrl_soc.h +++ b/soc/nxp/kinetis/common/pinctrl_soc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 NXP + * Copyright (c) 2022, 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,14 +29,16 @@ typedef uint32_t pinctrl_soc_pin_t; #if (defined(CONFIG_SOC_SERIES_KINETIS_KWX) && \ !(defined(CONFIG_SOC_MKW24D5) || \ defined(CONFIG_SOC_MKW22D5))) || \ - defined(CONFIG_SOC_SERIES_KINETIS_KL2X) || \ - defined(CONFIG_SOC_SERIES_KINETIS_KE1XF) + defined(CONFIG_SOC_SERIES_KINETIS_KL2X) || \ + defined(CONFIG_SOC_SERIES_KINETIS_KE1XF) || \ + defined(CONFIG_SOC_SERIES_KE1XZ) #define PORT_PCR_ODE(x) 0x0 #define PORT_PCR_ODE_MASK 0x0 #endif /* Kinetis KE series does not support slew rate. Define macros to have no effect */ -#if defined(CONFIG_SOC_SERIES_KINETIS_KE1XF) +#if defined(CONFIG_SOC_SERIES_KINETIS_KE1XF) || \ + defined(CONFIG_SOC_SERIES_KE1XZ) #define PORT_PCR_SRE(x) 0x0 #define PORT_PCR_SRE_MASK 0x0 #endif diff --git a/soc/nxp/kinetis/ke1xz/CMakeLists.txt b/soc/nxp/kinetis/ke1xz/CMakeLists.txt new file mode 100644 index 00000000000000..116e67f67510ad --- /dev/null +++ b/soc/nxp/kinetis/ke1xz/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_sources( + soc.c +) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") + +zephyr_include_directories(.) diff --git a/soc/nxp/kinetis/ke1xz/Kconfig b/soc/nxp/kinetis/ke1xz/Kconfig new file mode 100644 index 00000000000000..9e01b9ec4eba6e --- /dev/null +++ b/soc/nxp/kinetis/ke1xz/Kconfig @@ -0,0 +1,14 @@ +# Kinetis KE1xZ series MCU + +# Copyright (c) 2019 Vestas Wind Systems A/S +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_KE1XZ + select ARM + select CPU_CORTEX_M0PLUS + select CPU_CORTEX_M_HAS_SYSTICK + select CPU_CORTEX_M_HAS_VTOR + select CLOCK_CONTROL + select HAS_MCUX + select PLATFORM_SPECIFIC_INIT diff --git a/soc/nxp/kinetis/ke1xz/Kconfig.defconfig b/soc/nxp/kinetis/ke1xz/Kconfig.defconfig new file mode 100644 index 00000000000000..3077b6e8731768 --- /dev/null +++ b/soc/nxp/kinetis/ke1xz/Kconfig.defconfig @@ -0,0 +1,28 @@ +# Kinetis KE1xZ series configuration options + +# Copyright (c) 2019-2021 Vestas Wind Systems A/S +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_KE1XZ + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if CORTEX_M_SYSTICK + +config NUM_IRQS + default 32 + +config CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS + default y + +# This Kconfig is SOC Specific and configures the MCU at boot time +# This SOC is configured via the following bits +# 0000 0001 - Normal Boot +# 0000 0100 - Enable Interrupts +# 0000 1000 - Allow Reset detection from RESET_Pin +# 0111 0000 - Reserved for Future Expansion +config KINETIS_FLASH_CONFIG_FOPT + default 0x7d + depends on KINETIS_FLASH_CONFIG + +endif # SOC_SERIES_KE1XZ diff --git a/soc/nxp/kinetis/ke1xz/Kconfig.soc b/soc/nxp/kinetis/ke1xz/Kconfig.soc new file mode 100644 index 00000000000000..e0059ac98b1b99 --- /dev/null +++ b/soc/nxp/kinetis/ke1xz/Kconfig.soc @@ -0,0 +1,37 @@ +# Kinetis KE1xZ MCU line + +# Copyright (c) 2019 Vestas Wind Systems A/S +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_KE1XZ + bool + select SOC_FAMILY_KINETIS + +config SOC_SERIES + default "ke1xz" if SOC_SERIES_KE1XZ + +config SOC_MKE15Z7 + bool + select SOC_SERIES_KE1XZ + +config SOC + default "mke15z7" if SOC_MKE15Z7 + +config SOC_PART_NUMBER_MKE15Z128VLL7 + bool + +config SOC_PART_NUMBER_MKE15Z128VLH7 + bool + +config SOC_PART_NUMBER_MKE15Z256VLL7 + bool + +config SOC_PART_NUMBER_MKE15Z256VLH7 + bool + +config SOC_PART_NUMBER + default "MKE15Z128VLL7" if SOC_PART_NUMBER_MKE15Z128VLL7 + default "MKE15Z128VLH7" if SOC_PART_NUMBER_MKE15Z128VLH7 + default "MKE15Z256VLL7" if SOC_PART_NUMBER_MKE15Z256VLL7 + default "MKE15Z256VLH7" if SOC_PART_NUMBER_MKE15Z256VLH7 diff --git a/soc/nxp/kinetis/ke1xz/soc.c b/soc/nxp/kinetis/ke1xz/soc.c new file mode 100644 index 00000000000000..3aeb5db419efbd --- /dev/null +++ b/soc/nxp/kinetis/ke1xz/soc.c @@ -0,0 +1,142 @@ +/* + * Copyright 2024 NXP + * Copyright (c) 2019-2021 Vestas Wind Systems A/S + * + * Based on NXP k6x soc.c, which is: + * Copyright (c) 2014-2015 Wind River Systems, Inc. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define ASSERT_WITHIN_RANGE(val, min, max, str) \ + BUILD_ASSERT(val >= min && val <= max, str) + +#define ASSERT_ASYNC_CLK_DIV_VALID(val, str) \ + BUILD_ASSERT(val == 0 || val == 1 || val == 2 || val == 4 || \ + val == 8 || val == 16 || val == 2 || val == 64, str) + +#define TO_SYS_CLK_DIV(val) _DO_CONCAT(kSCG_SysClkDivBy, val) + +#define kSCG_AsyncClkDivBy0 kSCG_AsyncClkDisable +#define TO_ASYNC_CLK_DIV(val) _DO_CONCAT(kSCG_AsyncClkDivBy, val) + +#define SCG_CLOCK_NODE(name) DT_CHILD(DT_INST(0, nxp_kinetis_scg), name) +#define SCG_CLOCK_DIV(name) DT_PROP(SCG_CLOCK_NODE(name), clock_div) + +/* System Clock configuration */ +ASSERT_WITHIN_RANGE(SCG_CLOCK_DIV(bus_clk), 2, 8, + "Invalid SCG bus clock divider value"); +ASSERT_WITHIN_RANGE(SCG_CLOCK_DIV(core_clk), 1, 16, + "Invalid SCG core clock divider value"); + +static const scg_sys_clk_config_t scg_sys_clk_config = { + .divSlow = TO_SYS_CLK_DIV(SCG_CLOCK_DIV(bus_clk)), + .divCore = TO_SYS_CLK_DIV(SCG_CLOCK_DIV(core_clk)), +#if DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(sirc_clk)) + .src = kSCG_SysClkSrcSirc, +#elif DT_SAME_NODE(DT_CLOCKS_CTLR(SCG_CLOCK_NODE(core_clk)), SCG_CLOCK_NODE(firc_clk)) + .src = kSCG_SysClkSrcFirc, +#endif +}; + +/* Slow Internal Reference Clock (SIRC) configuration */ +ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(sircdiv2_clk), + "Invalid SCG SIRC divider 2 value"); +static const scg_sirc_config_t scg_sirc_config = { + .enableMode = kSCG_SircEnable, + .div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(sircdiv2_clk)), +#if MHZ(2) == DT_PROP(SCG_CLOCK_NODE(sirc_clk), clock_frequency) + .range = kSCG_SircRangeLow +#elif MHZ(8) == DT_PROP(SCG_CLOCK_NODE(sirc_clk), clock_frequency) + .range = kSCG_SircRangeHigh +#else +#error Invalid SCG SIRC clock frequency +#endif +}; + +/* Fast Internal Reference Clock (FIRC) configuration */ +ASSERT_ASYNC_CLK_DIV_VALID(SCG_CLOCK_DIV(fircdiv2_clk), + "Invalid SCG FIRC divider 2 value"); +static const scg_firc_config_t scg_firc_config = { + .enableMode = kSCG_FircEnable, + .div2 = TO_ASYNC_CLK_DIV(SCG_CLOCK_DIV(fircdiv2_clk)), /* b20253 */ +#if MHZ(48) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency) + .range = kSCG_FircRange48M, +#elif MHZ(52) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency) + .range = kSCG_FircRange52M, +#elif MHZ(56) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency) + .range = kSCG_FircRange56M, +#elif MHZ(60) == DT_PROP(SCG_CLOCK_NODE(firc_clk), clock_frequency) + .range = kSCG_FircRange60M, +#else +#error Invalid SCG FIRC clock frequency +#endif + .trimConfig = NULL +}; + +static ALWAYS_INLINE void clk_init(void) +{ + const scg_sys_clk_config_t scg_sys_clk_config_safe = { + .divSlow = kSCG_SysClkDivBy4, + .divCore = kSCG_SysClkDivBy1, + .src = kSCG_SysClkSrcSirc + }; + scg_sys_clk_config_t current; + + /* Configure SIRC */ + CLOCK_InitSirc(&scg_sirc_config); + + /* Temporary switch to safe SIRC in order to configure FIRC */ + CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config_safe); + do { + CLOCK_GetCurSysClkConfig(¤t); + } while (current.src != scg_sys_clk_config_safe.src); + CLOCK_InitFirc(&scg_firc_config); + + /* Only RUN mode supported for now */ + CLOCK_SetRunModeSysClkConfig(&scg_sys_clk_config); + do { + CLOCK_GetCurSysClkConfig(¤t); + } while (current.src != scg_sys_clk_config.src); + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart0), okay) + CLOCK_SetIpSrc(kCLOCK_Lpuart0, + DT_CLOCKS_CELL(DT_NODELABEL(lpuart0), ip_source)); +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart1), okay) + CLOCK_SetIpSrc(kCLOCK_Lpuart1, + DT_CLOCKS_CELL(DT_NODELABEL(lpuart1), ip_source)); +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart2), okay) + CLOCK_SetIpSrc(kCLOCK_Lpuart2, + DT_CLOCKS_CELL(DT_NODELABEL(lpuart2), ip_source)); +#endif +} + +static int ke1xz_init(void) + +{ + /* Initialize system clocks and PLL */ + clk_init(); + + return 0; +} + +#ifdef CONFIG_PLATFORM_SPECIFIC_INIT + +void z_arm_platform_init(void) +{ + /* SystemInit is provided by the NXP SDK */ + SystemInit(); +} + +#endif /* CONFIG_PLATFORM_SPECIFIC_INIT */ + +SYS_INIT(ke1xz_init, PRE_KERNEL_1, 0); diff --git a/soc/nxp/kinetis/ke1xz/soc.h b/soc/nxp/kinetis/ke1xz/soc.h new file mode 100644 index 00000000000000..ac805348a55d28 --- /dev/null +++ b/soc/nxp/kinetis/ke1xz/soc.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Vestas Wind Systems A/S + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +#include +#include + +#define PORT_MUX_GPIO kPORT_MuxAsGpio /* GPIO setting for the Port Mux Register */ + +#ifndef _ASMLANGUAGE + +#include + + +#endif /* !_ASMLANGUAGE */ + +#endif /* _SOC__H_ */ diff --git a/soc/nxp/kinetis/soc.yml b/soc/nxp/kinetis/soc.yml index c2b27eb9841cd6..887c6d6980b22a 100644 --- a/soc/nxp/kinetis/soc.yml +++ b/soc/nxp/kinetis/soc.yml @@ -29,3 +29,6 @@ family: socs: - name: mkv56f24 - name: mkv58f24 + - name: ke1xz + socs: + - name: mke15z7 From 4e1e3d1dd119b15d3e430598a41fcedf7d302bce Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1226/1389] boards: nxp: frdm_ke15z: Add board support for ke15z Added initial board support for the frdm_ke15z board. Signed-off-by: Emilio Benavente Signed-off-by: Pavel Krenek --- boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z | 6 + boards/nxp/frdm_ke15z/board.cmake | 11 ++ boards/nxp/frdm_ke15z/board.yml | 5 + boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp | Bin 0 -> 10224 bytes boards/nxp/frdm_ke15z/doc/index.rst | 187 ++++++++++++++++++ boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi | 17 ++ boards/nxp/frdm_ke15z/frdm_ke15z.dts | 76 +++++++ boards/nxp/frdm_ke15z/frdm_ke15z.yaml | 13 ++ boards/nxp/frdm_ke15z/frdm_ke15z_defconfig | 17 ++ .../clock_control/clock_control_mcux_scg.c | 25 +++ 10 files changed, 357 insertions(+) create mode 100644 boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z create mode 100644 boards/nxp/frdm_ke15z/board.cmake create mode 100644 boards/nxp/frdm_ke15z/board.yml create mode 100644 boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp create mode 100644 boards/nxp/frdm_ke15z/doc/index.rst create mode 100644 boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi create mode 100644 boards/nxp/frdm_ke15z/frdm_ke15z.dts create mode 100644 boards/nxp/frdm_ke15z/frdm_ke15z.yaml create mode 100644 boards/nxp/frdm_ke15z/frdm_ke15z_defconfig diff --git a/boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z b/boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z new file mode 100644 index 00000000000000..32c3589c59119b --- /dev/null +++ b/boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z @@ -0,0 +1,6 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_KE15Z + select SOC_MKE15Z7 + select SOC_PART_NUMBER_MKE15Z256VLL7 diff --git a/boards/nxp/frdm_ke15z/board.cmake b/boards/nxp/frdm_ke15z/board.cmake new file mode 100644 index 00000000000000..d14370f54fa7a5 --- /dev/null +++ b/boards/nxp/frdm_ke15z/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_runner_args(linkserver "--device=MKE15Z256xxx7:FRDM-KE15Z") +board_runner_args(jlink "--device=MKE15Z256xxx7" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/nxp/frdm_ke15z/board.yml b/boards/nxp/frdm_ke15z/board.yml new file mode 100644 index 00000000000000..c637334b8b83e6 --- /dev/null +++ b/boards/nxp/frdm_ke15z/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_ke15z + vendor: nxp + socs: + - name: mke15z7 diff --git a/boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp b/boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp new file mode 100644 index 0000000000000000000000000000000000000000..f45a78b66e24ee3bff3c6e732880fa2738e25be7 GIT binary patch literal 10224 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 z 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 literal 0 HcmV?d00001 diff --git a/boards/nxp/frdm_ke15z/doc/index.rst b/boards/nxp/frdm_ke15z/doc/index.rst new file mode 100644 index 00000000000000..fd1dec9bc67f6d --- /dev/null +++ b/boards/nxp/frdm_ke15z/doc/index.rst @@ -0,0 +1,187 @@ +.. _frdm_ke15z: + +NXP FRDM-KE15Z +############## + +Overview +******** + +The FRDM-KE15Z is a development board for NXP Kinetis KE1xZ 32-bit +MCU-based platforms. The FRDM-KE15Z contains a robust TSI module +with up to 50 channels which makes this board highly flexible +for touch keys. Offers options for serial +communication, flash programming, and run-control debugging. + +.. figure:: frdm_ke15z.webp + :align: center + :alt: FRDM-KE15Z + +Hardware +******** + +- MKE15Z256VLL7 MCU (up to 72 MHz, 256 KB flash memory, 32 KB RAM) +- OpenSDA Debug Circuit with a virtual serial port +- Touch electrodes in the self-capacitive mode +- Compatible with FRDM-TOUCH, FRDM-MC-LVBLDC, and Arduino® boards +- User Components such as Reset; RGB LED and two user buttons +- 6-axis FXOS8700CQ digital accelerometer and magnetometer + +For more information about the KE1xZ SoC and the FRDM-KE15Z board, see +these NXP reference documents: + +- `KE1XZ SOC Website`_ +- `FRDM-KE15Z Datasheet`_ +- `FRDM-KE15Z Reference Manual`_ +- `FRDM-KE15Z Website`_ +- `FRDM-KE15Z User Guide`_ +- `FRDM-KE15Z Schematics`_ + +Supported Features +================== + +The frdm_ke15z board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | uart polling; | +| | | uart interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/nxp/frdm_ke15z/frdm_ke15z_defconfig`. + +Other hardware features are not currently supported by the port. + +System Clock +============ + +The KE15 SoC is configured to run at 48 MHz using the FIRC. + +Serial Port +=========== + +The KE15 SoC has three UARTs. UART1 is configured for the console. + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Configuring a Debug Probe +========================= + +A debug probe is used for both flashing and debugging the board. This board is +configured by default to use Linkserver. + +Early versions of this board have an outdated version of the OpenSDA bootloader +and require an update. Please see the `DAPLink Bootloader Update`_ page for +instructions to update from the CMSIS-DAP bootloader to the DAPLink bootloader. + +Option 1: Linkserver +------------------------------------------------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the default CMSIS-DAP firmware included in +the on-board debugger. + +Linkserver is the default for this board, ``west flash`` and ``west debug`` will +call the linkserver runner. + +Option 2: :ref:`opensda-jlink-onboard-debug-probe` +-------------------------------------------------- + +Install the :ref:`jlink-debug-host-tools` and make sure they are in your search +path. + +Follow the instructions in :ref:`opensda-jlink-onboard-debug-probe` to program +the `OpenSDA J-Link Firmware for FRDM-KE15Z`_. +Use the ``-r jlink`` option with west to use the jlink runner. + +.. code-block:: console + + west flash -r jlink + +Configuring a Console +===================== + +Regardless of your choice in debug probe, we will use the OpenSDA +microcontroller as a usb-to-serial adapter for the serial console. + +Connect a USB cable from your PC to J5. + +Use the following settings with your serial terminal of choice (minicom, putty, +etc.): + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Flashing +======== + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke15z + :goals: flash + +Open a serial terminal, reset the board (press the SW1 button), and you should +see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-3478-gb923667860b1 *** + Hello World! frdm_ke15z/mke15z7 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke15z + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + ***** Booting Zephyr OS v3.6.0-xxx-gxxxxxxxxxxxx ***** + Hello World! frdm_ke15z + +.. _KE1XZ SoC Website: + https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/ke-series-arm-cortex-m4-m0-plus/ke1xz-arm-cortex-m0-plus-5v-main-stream-mcu-with-nxp-touch-and-can-control:KE1xZ + +.. _FRDM-KE15Z Datasheet: + https://www.nxp.com/docs/en/data-sheet/KE1xZP100M72SF0.pdf + +.. _FRDM-KE15Z Reference Manual: + https://www.nxp.com/webapp/Download?colCode=KE1XZP100M72SF0RM + +.. _FRDM-KE15Z Website: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/freedom-development-platform-for-kinetis-ke1xmcus:FRDM-KE15Z + +.. _FRDM-KE15Z User Guide: + https://www.nxp.com/document/guide/get-started-with-the-frdm-ke15z:NGS-FRDM-KE15Z + +.. _FRDM-KE15Z Schematics: + https://www.nxp.com/webapp/Download?colCode=FRDM-KE15Z-SCH-DESIGNFILES + +.. _DAPLink Bootloader Update: + https://os.mbed.com/blog/entry/DAPLink-bootloader-update/ + +.. _OpenSDA J-Link Firmware for FRDM-KE15Z: + https://www.segger.com/downloads/jlink/OpenSDA_FRDM-KE15Z diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi b/boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi new file mode 100644 index 00000000000000..b004d91e60c04c --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + lpuart1_default: lpuart1_default { + group0 { + pinmux = , + ; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; +}; diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z.dts b/boards/nxp/frdm_ke15z/frdm_ke15z.dts new file mode 100644 index 00000000000000..0a1c341b0008d2 --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z.dts @@ -0,0 +1,76 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_ke15z-pinctrl.dtsi" +#include + +/ { + model = "NXP Freedom KE15Z board"; + compatible = "nxp,ke15z", "nxp,mke15z7"; + + aliases { + led0 = &green_led; + led1 = &blue_led; + led2 = &red_led; + sw0 = &user_button_0; + sw1 = &user_button_1; + }; + + chosen { + zephyr,sram = &sram_u; + zephyr,flash = &flash0; + zephyr,console = &lpuart1; + zephyr,shell-uart = &lpuart1; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpiod 0 GPIO_ACTIVE_LOW>; + label = "RED LED"; + }; + green_led: led_1 { + gpios = <&gpiod 16 GPIO_ACTIVE_LOW>; + label = "GREEN LED"; + }; + blue_led: led_2 { + gpios = <&gpiod 15 GPIO_ACTIVE_LOW>; + label = "BLUE LED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_0: button_0 { + label = "User SW3"; + gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + user_button_1: button_1 { + label = "User SW2"; + gpios = <&gpiob 11 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; +}; + +&lpuart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&lpuart1_default>; + pinctrl-names = "default"; +}; + +&gpiob { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z.yaml b/boards/nxp/frdm_ke15z/frdm_ke15z.yaml new file mode 100644 index 00000000000000..9a2a7ac4b272b9 --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z.yaml @@ -0,0 +1,13 @@ +identifier: frdm_ke15z +name: NXP FRDM-KE15Z +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +flash: 256 +ram: 24 +supported: + - gpio + - uart diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z_defconfig b/boards/nxp/frdm_ke15z/frdm_ke15z_defconfig new file mode 100644 index 00000000000000..69a85bdc43dda6 --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z_defconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# GPIO Controller +CONFIG_GPIO=y + +# Clock Control +CONFIG_CLOCK_CONTROL=y + +# Enable pin controller +CONFIG_PINCTRL=y diff --git a/drivers/clock_control/clock_control_mcux_scg.c b/drivers/clock_control/clock_control_mcux_scg.c index 690c133dd16a85..526bb06bc7d5f7 100644 --- a/drivers/clock_control/clock_control_mcux_scg.c +++ b/drivers/clock_control/clock_control_mcux_scg.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019-2021 Vestas Wind Systems A/S + * Copyright 2024 NXP * * Based on clock_control_mcux_sim.c, which is: * Copyright (c) 2017, NXP @@ -60,33 +61,57 @@ static int mcux_scg_get_rate(const struct device *dev, case KINETIS_SCG_FIRC_CLK: clock_name = kCLOCK_ScgFircClk; break; +#if (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) case KINETIS_SCG_SPLL_CLK: clock_name = kCLOCK_ScgSysPllClk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) */ +#if (defined(FSL_FEATURE_SCG_HAS_LPFLL) && FSL_FEATURE_SCG_HAS_LPFLL) + case KINETIS_SCG_SPLL_CLK: + clock_name = kCLOCK_ScgLpFllClk; + break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_LPFLL) && FSL_FEATURE_SCG_HAS_LPFLL) */ +#if (defined(FSL_FEATURE_SCG_HAS_SOSCDIV1) && FSL_FEATURE_SCG_HAS_SOSCDIV1) case KINETIS_SCG_SOSC_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgSysOscAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SOSCDIV1) && FSL_FEATURE_SCG_HAS_SOSCDIV1) */ case KINETIS_SCG_SOSC_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgSysOscAsyncDiv2Clk; break; +#if (defined(FSL_FEATURE_SCG_HAS_SIRCDIV1) && FSL_FEATURE_SCG_HAS_SIRCDIV1) case KINETIS_SCG_SIRC_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgSircAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SIRCDIV1) && FSL_FEATURE_SCG_HAS_SIRCDIV1) */ case KINETIS_SCG_SIRC_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgSircAsyncDiv2Clk; break; +#if (defined(FSL_FEATURE_FSL_FEATURE_SCG_HAS_FIRCDIV1) && FSL_FEATURE_SCG_HAS_FIRCDIV1) case KINETIS_SCG_FIRC_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgFircAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_FSL_FEATURE_SCG_HAS_FIRCDIV1) && FSL_FEATURE_SCG_HAS_FIRCDIV1) */ case KINETIS_SCG_FIRC_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgFircAsyncDiv2Clk; break; +#if (defined(FSL_FEATURE_SCG_HAS_SPLLDIV1) && FSL_FEATURE_SCG_HAS_SPLLDIV1) case KINETIS_SCG_SPLL_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgSysPllAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLLDIV1) && FSL_FEATURE_SCG_HAS_SPLLDIV1) */ +#if (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) case KINETIS_SCG_SPLL_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgSysPllAsyncDiv2Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) */ +#if (defined(FSL_FEATURE_SCG_HAS_FLLDIV1) && FSL_FEATURE_SCG_HAS_FLLDIV1) + case KINETIS_SCG_LPFLL_ASYNC_DIV2_CLK: + clock_name = kCLOCK_ScgSysLPFllAsyncDiv2Clk; + break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_FLLDIV1) && FSL_FEATURE_SCG_HAS_FLLDIV1) */ + + default: LOG_ERR("Unsupported clock name"); return -EINVAL; From d0882e6be1798d403d077367e2f79e9032e9ca4b Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1227/1389] tests: drivers: gpio: gpio_basic_api: Added KE15Z Overlay file. Added Overlay for testing GPIO on FRDM_KE15Z Signed-off-by: Emilio Benavente --- .../gpio_basic_api/boards/frdm_ke15z.overlay | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/frdm_ke15z.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/frdm_ke15z.overlay b/tests/drivers/gpio/gpio_basic_api/boards/frdm_ke15z.overlay new file mode 100644 index 00000000000000..68c941f0cd5dc8 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/frdm_ke15z.overlay @@ -0,0 +1,17 @@ +/* + * Copyright NXP 2024 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&gpioc { + status = "okay"; +}; + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpioc 8 0>; /* Arduino D0 */ + in-gpios = <&gpioc 9 0>; /* Arduino D1 */ + }; +}; From 6131e5dcc6ec69b7325b43a6f1663a912e52070d Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1228/1389] tests: pm/power_mgmt: Increase test coverage Test device API for when a device does not implement device pm. Signed-off-by: Flavio Ceolin --- .../pm/power_mgmt/boards/native_sim.overlay | 4 ++ tests/subsys/pm/power_mgmt/src/main.c | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/tests/subsys/pm/power_mgmt/boards/native_sim.overlay b/tests/subsys/pm/power_mgmt/boards/native_sim.overlay index 8cd648a06e3d4f..a66ce9d00256ab 100644 --- a/tests/subsys/pm/power_mgmt/boards/native_sim.overlay +++ b/tests/subsys/pm/power_mgmt/boards/native_sim.overlay @@ -20,4 +20,8 @@ device_d: device_d { compatible = "test-device-pm"; }; + + device_e: device_e { + compatible = "test-device-pm"; + }; }; diff --git a/tests/subsys/pm/power_mgmt/src/main.c b/tests/subsys/pm/power_mgmt/src/main.c index d0ee2b08722ff7..10746b49021c28 100644 --- a/tests/subsys/pm/power_mgmt/src/main.c +++ b/tests/subsys/pm/power_mgmt/src/main.c @@ -37,6 +37,19 @@ static const struct device *const device_a = static const struct device *const device_c = DEVICE_DT_GET(DT_INST(2, test_device_pm)); +/* + * This device does not support PM. It is used to check + * the behavior of the PM subsystem when a device does not + * support PM. + */ +static const struct device *const device_e = + DEVICE_DT_GET(DT_INST(4, test_device_pm)); + +DEVICE_DT_DEFINE(DT_INST(4, test_device_pm), NULL, + NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + NULL); + /* * According with the initialization level, devices A, B and C are * initialized in the following order A -> B -> C. @@ -443,6 +456,35 @@ ZTEST(power_management_1cpu, test_force_state) k_sleep(K_SECONDS(1U)); } +ZTEST(power_management_1cpu, test_device_without_pm) +{ + pm_device_busy_set(device_e); + + /* Since this device does not support PM, it should not be set busy */ + zassert_false(pm_device_is_busy(device_e)); + + /* No device should be busy */ + zassert_false(pm_device_is_any_busy()); + + /* Lets ensure that nothing happens */ + pm_device_busy_clear(device_e); + + /* Check the status. Since PM is enabled but this device does not support it. + * It should return -ENOSYS + */ + zassert_equal(pm_device_state_get(device_e, NULL), -ENOSYS); + + /* Try to forcefully change the state should also return an error */ + zassert_equal(pm_device_action_run(device_e, PM_DEVICE_ACTION_SUSPEND), -ENOSYS); + + /* Confirming the device is powered */ + zassert_true(pm_device_is_powered(device_e)); + + /* Test wakeup functionality */ + zassert_false(pm_device_wakeup_enable(device_e, true)); + zassert_false(pm_device_wakeup_is_enabled(device_e)); +} + void power_management_1cpu_teardown(void *data) { pm_notifier_unregister(¬ifier); From 0df656e6329ab226c1a137f4664e0093b1180758 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1229/1389] pm: device_runtime: Fix usage API Fix pm_device_runtime_usage() API for isr safe devices. Signed-off-by: Flavio Ceolin --- subsys/pm/device_runtime.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/subsys/pm/device_runtime.c b/subsys/pm/device_runtime.c index 51cdd74e4a4938..d574f0356c9bfc 100644 --- a/subsys/pm/device_runtime.c +++ b/subsys/pm/device_runtime.c @@ -570,9 +570,18 @@ int pm_device_runtime_usage(const struct device *dev) return -ENOTSUP; } - (void)k_sem_take(&pm->lock, K_FOREVER); - usage = pm->base.usage; - k_sem_give(&pm->lock); + if (atomic_test_bit(&dev->pm_base->flags, PM_DEVICE_FLAG_ISR_SAFE)) { + struct pm_device_isr *pm_sync = dev->pm_isr; + k_spinlock_key_t k = k_spin_lock(&pm_sync->lock); + + usage = pm_sync->base.usage; + + k_spin_unlock(&pm_sync->lock, k); + } else { + (void)k_sem_take(&pm->lock, K_FOREVER); + usage = pm->base.usage; + k_sem_give(&pm->lock); + } return usage; } From ff6ac815dbf4d5267e43515ec22e3e581a735758 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1230/1389] tests: pm/device_runtime: Test pm_device_runtime_usage Add tests covering possible branches in pm_device_runtime_usage() Signed-off-by: Flavio Ceolin --- tests/subsys/pm/device_runtime_api/src/main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/subsys/pm/device_runtime_api/src/main.c b/tests/subsys/pm/device_runtime_api/src/main.c index 74f46eaf755362..ba4482ac8f3001 100644 --- a/tests/subsys/pm/device_runtime_api/src/main.c +++ b/tests/subsys/pm/device_runtime_api/src/main.c @@ -94,6 +94,7 @@ ZTEST(device_runtime_api, test_api) /* device is initially suspended */ (void)pm_device_state_get(test_dev, &state); zassert_equal(state, PM_DEVICE_STATE_SUSPENDED); + zassert_equal(pm_device_runtime_usage(test_dev), 0); /*** get + put ***/ @@ -107,6 +108,7 @@ ZTEST(device_runtime_api, test_api) /* usage: 1, +1, resume: no */ ret = pm_device_runtime_get(test_dev); zassert_equal(ret, 0); + zassert_equal(pm_device_runtime_usage(test_dev), 2); /* usage: 2, -1, suspend: no */ ret = pm_device_runtime_put(test_dev); @@ -118,6 +120,7 @@ ZTEST(device_runtime_api, test_api) /* usage: 1, -1, suspend: yes */ ret = pm_device_runtime_put(test_dev); zassert_equal(ret, 0); + zassert_equal(pm_device_runtime_usage(test_dev), 0); (void)pm_device_state_get(test_dev, &state); zassert_equal(state, PM_DEVICE_STATE_SUSPENDED); @@ -125,12 +128,14 @@ ZTEST(device_runtime_api, test_api) /* usage: 0, -1, suspend: no (unbalanced call) */ ret = pm_device_runtime_put(test_dev); zassert_equal(ret, -EALREADY); + zassert_equal(pm_device_runtime_usage(test_dev), 0); /*** get + asynchronous put until suspended ***/ /* usage: 0, +1, resume: yes */ ret = pm_device_runtime_get(test_dev); zassert_equal(ret, 0); + zassert_equal(pm_device_runtime_usage(test_dev), 1); (void)pm_device_state_get(test_dev, &state); zassert_equal(state, PM_DEVICE_STATE_ACTIVE); @@ -140,11 +145,13 @@ ZTEST(device_runtime_api, test_api) /* usage: 1, -1, suspend: yes (queued) */ ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT); zassert_equal(ret, 0); + zassert_equal(pm_device_runtime_usage(test_dev), 0); if (IS_ENABLED(CONFIG_TEST_PM_DEVICE_ISR_SAFE)) { /* In sync mode async put is equivalent as normal put. */ (void)pm_device_state_get(test_dev, &state); zassert_equal(state, PM_DEVICE_STATE_SUSPENDED); + zassert_equal(pm_device_runtime_usage(test_dev), 0); } else { (void)pm_device_state_get(test_dev, &state); zassert_equal(state, PM_DEVICE_STATE_SUSPENDING); @@ -156,6 +163,7 @@ ZTEST(device_runtime_api, test_api) /* usage: 0, -1, suspend: no (unbalanced call) */ ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT); zassert_equal(ret, -EALREADY); + zassert_equal(pm_device_runtime_usage(test_dev), 0); /* unblock test driver and let it finish */ test_driver_pm_done(test_dev); @@ -250,6 +258,7 @@ ZTEST(device_runtime_api, test_api) /* Put operation should fail due the state be locked. */ ret = pm_device_runtime_disable(test_dev); zassert_equal(ret, 0); + zassert_equal(pm_device_runtime_usage(test_dev), -ENOTSUP); } DEVICE_DEFINE(pm_unsupported_device, "PM Unsupported", NULL, NULL, NULL, NULL, From 959feb1dbce53253cac3ea0c40a8fcb7a34d640f Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1231/1389] net: lib: dhcpv4: goto INIT on IF down, not RENEWING When the interface goes down, the safest thing to do is to return to the INIT state, as there is no guarantee that any state is preserved upon the interface coming back up again. This is particularly the case with WiFi. Signed-off-by: Jordan Yates --- subsys/net/lib/dhcpv4/dhcpv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/lib/dhcpv4/dhcpv4.c b/subsys/net/lib/dhcpv4/dhcpv4.c index e1db51ebfcd066..d0ea25edc49437 100644 --- a/subsys/net/lib/dhcpv4/dhcpv4.c +++ b/subsys/net/lib/dhcpv4/dhcpv4.c @@ -1406,7 +1406,7 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb, if (iface->config.dhcpv4.state == NET_DHCPV4_BOUND) { iface->config.dhcpv4.attempts = 0U; - iface->config.dhcpv4.state = NET_DHCPV4_RENEWING; + iface->config.dhcpv4.state = NET_DHCPV4_INIT; NET_DBG("enter state=%s", net_dhcpv4_state_name( iface->config.dhcpv4.state)); /* Remove any bound address as interface is gone */ From f431f9d1190e09906da6dd16a014caab124a4e51 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1232/1389] kernel: Relax loop in z_smp_global_lock() Updates z_smp_global_lock() to follow the pattern used in spinlocks to relax the loop between atomic_cas() attempts. Signed-off-by: Peter Mitsis --- kernel/smp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/smp.c b/kernel/smp.c index 704bfcd9caa9bf..a56595252789a9 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -60,6 +60,7 @@ unsigned int z_smp_global_lock(void) if (!_current->base.global_lock_count) { while (!atomic_cas(&global_lock, 0, 1)) { + arch_spin_relax(); } } From 1dfd56952133b153fad9e758a47a07b5f88c8b99 Mon Sep 17 00:00:00 2001 From: Mike Szczys Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1233/1389] twister: fix serial connection for flash_before The --flash-before flag allows devices to be flashed before the serial connection is established. However, the implementation was incomplete and only worked if the port address already existed at the start of the run. This is incompatible with devices that implement the USB in software (eg: USB-CDC). This commit fixes the implementation to delay setting up the connection until after the device is flashed, and to retry the connection for two seconds after flashing to give the device time to enumerate as a USB device. Signed-off-by: Mike Szczys --- .../twister_harness/device/device_adapter.py | 31 ++++++++++++++++--- .../src/twister_harness/plugin.py | 7 +++++ .../twister_harness/twister_harness_config.py | 2 ++ .../pylib/twister/twisterlib/environment.py | 2 +- scripts/pylib/twister/twisterlib/harness.py | 3 ++ 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py index b5560650c1b6cf..3f73045f899fee 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py @@ -14,6 +14,7 @@ import time from datetime import datetime from pathlib import Path +from serial import SerialException from twister_harness.exceptions import ( TwisterHarnessException, @@ -69,14 +70,23 @@ def launch(self) -> None: if self.device_config.type != 'hardware': self._flash_and_run() + self._device_run.set() + self._start_reader_thread() + self.connect() + return self._device_run.set() self._start_reader_thread() - self.connect() - if self.device_config.type == 'hardware': + if self.device_config.flash_before: + # For hardware devices with shared USB or software USB, connect after flashing. + # Retry for up to 10 seconds for USB-CDC based devices to enumerate. + self._flash_and_run() + self.connect(retry_s = 10) + else: # On hardware, flash after connecting to COM port, otherwise some messages # from target can be lost. + self.connect() self._flash_and_run() def close(self) -> None: @@ -89,7 +99,7 @@ def close(self) -> None: self._device_run.clear() self._join_reader_thread() - def connect(self) -> None: + def connect(self, retry_s: int = 0) -> None: """Connect to device - allow for output gathering.""" if self.is_device_connected(): logger.debug('Device already connected') @@ -98,7 +108,20 @@ def connect(self) -> None: msg = 'Cannot connect to not working device' logger.error(msg) raise TwisterHarnessException(msg) - self._connect_device() + + if retry_s > 0: + retry_cycles = retry_s * 10 + for i in range(retry_cycles): + try: + self._connect_device() + break + except SerialException: + if i == retry_cycles - 1: + raise + time.sleep(0.1) + else: + self._connect_device() + self._device_connected.set() def disconnect(self) -> None: diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py index 34a09aa38f5368..60537608357a10 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py @@ -84,6 +84,13 @@ def pytest_addoption(parser: pytest.Parser): '--device-serial-pty', help='Script for controlling pseudoterminal.' ) + twister_harness_group.addoption( + '--flash-before', + type=bool, + help='Flash device before attaching to serial port' + 'This is useful for devices that share the same port for programming' + 'and serial console, or use soft-USB, where flash must come first.' + ) twister_harness_group.addoption( '--west-flash-extra-args', help='Extend parameters for west flash. ' diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py index ece190c630f885..6ab26c3e8f4161 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py @@ -26,6 +26,7 @@ class DeviceConfig: id: str = '' product: str = '' serial_pty: str = '' + flash_before: bool = False west_flash_extra_args: list[str] = field(default_factory=list, repr=False) name: str = '' pre_script: Path | None = None @@ -62,6 +63,7 @@ def create(cls, config: pytest.Config) -> TwisterHarnessConfig: id=config.option.device_id, product=config.option.device_product, serial_pty=config.option.device_serial_pty, + flash_before=bool(config.option.flash_before), west_flash_extra_args=west_flash_extra_args, pre_script=_cast_to_path(config.option.pre_script), post_script=_cast_to_path(config.option.post_script), diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index dcd8fe9189cf87..85b7cdb371e102 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -178,7 +178,7 @@ def add_parse_arguments(parser = None): parser.add_argument("--flash-before", action="store_true", default=False, help="""Flash device before attaching to serial port. This is useful for devices that share the same port for programming - and serial console, where flash must come first. + and serial console, or use soft-USB, where flash must come first. """) test_or_build.add_argument( diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 6fd6dae73a899d..b0925c0fce0960 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -408,6 +408,9 @@ def _generate_parameters_for_hardware(self, handler: Handler): if hardware.post_script: command.append(f'--post-script={hardware.post_script}') + if hardware.flash_before: + command.append(f'--flash-before={hardware.flash_before}') + return command def run_command(self, cmd, timeout): From c7feb40a8120f592835152445a4be8083f8f86ff Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1234/1389] board: mimxrt1010_evk: add linkserver support linkserver supports rt1010_evk from 1.5.30 Signed-off-by: Hake Huang --- boards/nxp/mimxrt1010_evk/board.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boards/nxp/mimxrt1010_evk/board.cmake b/boards/nxp/mimxrt1010_evk/board.cmake index d482b24e322a48..ec24e040231d33 100644 --- a/boards/nxp/mimxrt1010_evk/board.cmake +++ b/boards/nxp/mimxrt1010_evk/board.cmake @@ -6,5 +6,8 @@ board_runner_args(pyocd "--target=mimxrt1010") board_runner_args(jlink "--device=MIMXRT1011") +board_runner_args(linkserver "--device=MIMXRT1011xxxxx:EVK-MIMXRT1010") + +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) From 93b6238ee8fdf588f0219d3bae38db2c057e2941 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1235/1389] board: mimxrt1010_evk: add linkserver support docs add support docs Signed-off-by: Hake Huang --- boards/nxp/mimxrt1010_evk/doc/index.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/boards/nxp/mimxrt1010_evk/doc/index.rst b/boards/nxp/mimxrt1010_evk/doc/index.rst index f830b49aab5473..438b038baea32b 100644 --- a/boards/nxp/mimxrt1010_evk/doc/index.rst +++ b/boards/nxp/mimxrt1010_evk/doc/index.rst @@ -181,6 +181,24 @@ Attach a J-Link 10-pin connector to J55. Check that jumpers J61 and J62 are **off** (they are on by default when boards ship from the factory) to ensure SWD signals are disconnected from the OpenSDA microcontroller. +Using LinkServer +---------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. To use LinkServer the on board CMSIS-DAP firmware need updated with +LPCScrypt installed with LinkServer. + +To enter board debuger FW update mode, connect J22 first, and power cycle board. +For more details please refer to `Debug_Probe_Firmware_Programming.pdf`, which is +installed with LinkServer. + +.. code-block:: console + + :Ubuntu/Mac: scripts/program_CMSIS + :Windows: scripts/program_CMSIS.cmd + +You may also se the ``-r linkserver`` option with West to use the LinkServer. + Configuring a Console ===================== From 06e7ef940733adee25dbec4583cfbe0a32e107ce Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1236/1389] Lib: SMF Modify HSM operation for UML-Style transitions Modify the SMF such that state transitions from parent states choose the correct Least Common Ancestor based on the transition source rather than the current state. SMF set as experimental. Signed-off-by: Glenn Andrews --- doc/releases/migration-guide-3.7.rst | 8 + doc/releases/release-notes-3.7.rst | 3 + doc/services/smf/index.rst | 118 +++--- include/zephyr/smf.h | 40 +- lib/smf/smf.c | 274 +++++++++----- tests/lib/smf/CMakeLists.txt | 2 +- ...s_smf.c => test_lib_self_transition_smf.c} | 344 +++++++++++------- tests/lib/smf/src/test_lib_smf.h | 2 +- 8 files changed, 498 insertions(+), 293 deletions(-) rename tests/lib/smf/src/{test_lib_initial_transitions_smf.c => test_lib_self_transition_smf.c} (51%) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 4c1fccd2e3a328..cc9a8b1bce7a56 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -493,6 +493,14 @@ State Machine Framework now independent of the values of :kconfig:option:`CONFIG_SMF_ANCESTOR_SUPPORT` and :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION`. If the additional arguments are not used, they have to be set to ``NULL``. (:github:`71250`) +* SMF now follows a more UML-like transition flow when the transition source is a parent of the + state called by :c:func:`smf_run_state`. Exit actions up to (but not including) the Least Common + Ancestor of the transition source and target state will be executed, as will entry actions from + (but not including) the LCA down to the target state. (:github:`71675`) +* Previously, calling :c:func:`smf_set_state` with a ``new_state`` set to NULL would execute all + exit actions from the current state to the topmost parent, with the expectation the topmost exit + action would terminate the state machine. Passing ``NULL`` is now not allowed. Instead create a + 'terminate' state at the top level, and call :c:func:`smf_set_terminate` from its entry action. ZBus ==== diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index b460b1c13bd6d8..aff99963d78889 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -375,6 +375,9 @@ Libraries / Subsystems * State Machine Framework * The :c:macro:`SMF_CREATE_STATE` macro now always takes 5 arguments. + * Transition sources that are parents of the state that was run now choose the correct Least + Common Ancestor for executing Exit and Entry Actions. + * Passing ``NULL`` to :c:func:`smf_set_state` is now not allowed. * Storage diff --git a/doc/services/smf/index.rst b/doc/services/smf/index.rst index 169ee507ec4b4f..9b5ee62af76421 100644 --- a/doc/services/smf/index.rst +++ b/doc/services/smf/index.rst @@ -39,7 +39,7 @@ By default, a state can have no ancestor states, resulting in a flat state machine. But to enable the creation of a hierarchical state machine, the :kconfig:option:`CONFIG_SMF_ANCESTOR_SUPPORT` option must be enabled. -By default, the hierarchical state machine does not support initial transitions +By default, the hierarchical state machines do not support initial transitions to child states on entering a superstate. To enable them the :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION` option must be enabled. @@ -87,31 +87,29 @@ from parent state S0 to child state S2:: }; To set the initial state, the :c:func:`smf_set_initial` function should be -called. It has the following prototype: -``void smf_set_initial(smf_ctx *ctx, smf_state *state)`` +called. To transition from one state to another, the :c:func:`smf_set_state` -function is used and it has the following prototype: -``void smf_set_state(smf_ctx *ctx, smf_state *state)`` +function is used. .. note:: If :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION` is not set, :c:func:`smf_set_initial` and :c:func:`smf_set_state` function should not be passed a parent state as the parent state does not know which child state to transition to. Transitioning to a parent state is OK if an initial transition to a child state is defined. A well-formed - HSM will have initial transitions defined for all parent states. + HSM should have initial transitions defined for all parent states. -.. note:: While the state machine is running, smf_set_state should only be - called from the Entry and Run functions. Calling smf_set_state from the - Exit functions doesn't make sense and will generate a warning. +.. note:: While the state machine is running, :c:func:`smf_set_state` should + only be called from the Entry or Run function. Calling + :c:func:`smf_set_state` from Exit functions will generate a warning in the + log and no transition will occur. State Machine Execution ======================= To run the state machine, the :c:func:`smf_run_state` function should be called in some application dependent way. An application should cease calling -smf_run_state if it returns a non-zero value. The function has the following -prototype: ``int32_t smf_run_state(smf_ctx *ctx)`` +smf_run_state if it returns a non-zero value. Preventing Parent Run Actions ============================= @@ -124,13 +122,38 @@ State Machine Termination ========================= To terminate the state machine, the :c:func:`smf_set_terminate` function -should be called. It can be called from the entry, run, or exit action. The -function takes a non-zero user defined value that's returned by the -:c:func:`smf_run_state` function. The function has the following prototype: -``void smf_set_terminate(smf_ctx *ctx, int32_t val)`` +should be called. It can be called from the entry, run, or exit actions. The +function takes a non-zero user defined value that will be returned by the +:c:func:`smf_run_state` function. + +UML State Machines +================== + +SMF follows UML hierarchical state machine rules for transitions i.e., the +entry and exit actions of the least common ancestor are not executed on +transition, unless said transition is a transition to self. + +The UML Specification for StateMachines may be found in chapter 14 of the UML +specification available here: https://www.omg.org/spec/UML/ + +SMF breaks from UML rules in: + +1. Executing the actions associated with the transition within the context + of the source state, rather than after the exit actions are performed. +2. Only allowing external transitions to self, not to sub-states. A transition + from a superstate to a child state is treated as a local transition. +3. Prohibiting transitions using :c:func:`smf_set_state` in exit actions. + +SMF also does not provide any pseudostates except the Initial Pseudostate. +Terminate pseudostates can be modelled by calling :c:func:`smf_set_terminate` +from the entry action of a 'terminate' state. Orthogonal regions are modelled +by calling :c:func:`smf_run_state` for each region. + +State Machine Examples +====================== Flat State Machine Example -========================== +************************** This example turns the following state diagram into code using the SMF, where the initial state is S0. @@ -232,7 +255,7 @@ Code:: } Hierarchical State Machine Example -================================== +********************************** This example turns the following state diagram into code using the SMF, where S0 and S1 share a parent state and S0 is the initial state. @@ -342,17 +365,14 @@ When designing hierarchical state machines, the following should be considered: re-execute the ancestor\'s entry action or execute the exit action. For example, the parent_entry function is not called when transitioning from S0 to S1, nor is the parent_exit function called. - - Ancestor exit actions are executed after the sibling exit actions. For - example, the s1_exit function is called before the parent_exit function - is called. + - Ancestor exit actions are executed after the exit action of the current + state. For example, the s1_exit function is called before the parent_exit + function is called. - The parent_run function only executes if the child_run function does not call either :c:func:`smf_set_state` or :c:func:`smf_set_handled`. - - Transitions to self in super-states containing sub-states are not supported. - Transitions to self from the most-nested child state are supported and will - call the exit and entry function of the child state correctly. Event Driven State Machine Example -================================== +********************************** Events are not explicitly part of the State Machine Framework but an event driven state machine can be implemented using Zephyr :ref:`events`. @@ -499,47 +519,55 @@ Code:: } } -Hierarchical State Machine Example With Initial Transitions -=========================================================== +State Machine Example With Initial Transitions And Transition To Self +********************************************************************* + +:zephyr_file:`tests/lib/smf/src/test_lib_self_transition_smf.c` defines a state +machine for testing the initial transitions and transitions to self in a parent +state. The statechart for this test is below. -:zephyr_file:`tests/lib/smf/src/test_lib_initial_transitions_smf.c` defines -a state machine for testing initial transitions and :c:func:`smf_set_handled`. -The statechart for this test is below. .. graphviz:: - :caption: Test state machine for initial transitions and ``smf_set_handled`` + :caption: Test state machine for UML State Transitions digraph smf_hierarchical_initial { compound=true; node [style = rounded]; - smf_set_initial [shape=plaintext]; + "smf_set_initial()" [shape=plaintext fontname=Courier]; ab_init_state [shape = point]; STATE_A [shape = box]; STATE_B [shape = box]; STATE_C [shape = box]; STATE_D [shape = box]; + DC[shape=point height=0 width=0 label=<>] - subgraph cluster_ab { - label = "PARENT_AB"; + subgraph cluster_root { + label = "ROOT"; style = rounded; - ab_init_state -> STATE_A; - STATE_A -> STATE_B; - } - subgraph cluster_c { - label = "PARENT_C"; - style = rounded; - STATE_C -> STATE_C + subgraph cluster_ab { + label = "PARENT_AB"; + style = rounded; + ab_init_state -> STATE_A; + STATE_A -> STATE_B; + } + + subgraph cluster_c { + label = "PARENT_C"; + style = rounded; + STATE_B -> STATE_C [ltail=cluster_ab] + } + + STATE_C -> DC [ltail=cluster_c, dir=none]; + DC -> STATE_C [lhead=cluster_c]; + STATE_C -> STATE_D } - smf_set_initial -> STATE_A [lhead=cluster_ab] - STATE_B -> STATE_C - STATE_C -> STATE_D + "smf_set_initial()" -> STATE_A [lhead=cluster_ab] } - API Reference -************* +============= .. doxygengroup:: smf diff --git a/include/zephyr/smf.h b/include/zephyr/smf.h index ba0191272648b9..5b5f303630da8a 100644 --- a/include/zephyr/smf.h +++ b/include/zephyr/smf.h @@ -18,26 +18,27 @@ /** * @brief State Machine Framework API * @defgroup smf State Machine Framework API + * @version 0.1.0 * @ingroup os_services * @{ */ /** - * @brief Macro to create a hierarchical state. + * @brief Macro to create a hierarchical state with initial transitions. * - * @param _entry State entry function - * @param _run State run function - * @param _exit State exit function + * @param _entry State entry function or NULL + * @param _run State run function or NULL + * @param _exit State exit function or NULL * @param _parent State parent object or NULL * @param _initial State initial transition object or NULL */ -#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ -{ \ - .entry = _entry, \ - .run = _run, \ - .exit = _exit, \ - IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \ - IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \ +#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ +{ \ + .entry = _entry, \ + .run = _run, \ + .exit = _exit, \ + IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \ + IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \ } /** @@ -72,6 +73,7 @@ struct smf_state { const state_execution run; /** Optional method that will be run when this state exists */ const state_execution exit; +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT /** * Optional parent state that contains common entry/run/exit * implementation among various child states. @@ -79,8 +81,8 @@ struct smf_state { * run: Parent function executes AFTER child function. * exit: Parent function executes AFTER child function. * - * Note: When transitioning between two child states with a shared parent, - * that parent's exit and entry functions do not execute. + * Note: When transitioning between two child states with a shared + * parent, that parent's exit and entry functions do not execute. */ const struct smf_state *parent; @@ -89,7 +91,8 @@ struct smf_state { * Optional initial transition state. NULL for leaf states. */ const struct smf_state *initial; -#endif +#endif /* CONFIG_SMF_INITIAL_TRANSITION */ +#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ }; /** Defines the current context of the state machine. */ @@ -98,6 +101,11 @@ struct smf_ctx { const struct smf_state *current; /** Previous state the state machine executed */ const struct smf_state *previous; + +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + /** Currently executing state (which may be a parent) */ + const struct smf_state *executing; +#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ /** * This value is set by the set_terminate function and * should terminate the state machine when its set to a @@ -122,8 +130,8 @@ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state); /** * @brief Changes a state machines state. This handles exiting the previous - * state and entering the target state. A common parent state will not - * exited nor be re-entered. + * state and entering the target state. For HSMs the entry and exit + * actions of the Least Common Ancestor will not be run. * * @param ctx State machine context * @param new_state State to transition to (NULL is valid and exits all states) diff --git a/lib/smf/smf.c b/lib/smf/smf.c index ecc107407440a0..fb0c95c574f235 100644 --- a/lib/smf/smf.c +++ b/lib/smf/smf.c @@ -9,24 +9,22 @@ #include LOG_MODULE_REGISTER(smf); -/* - * Private structure (to this file) used to track state machine context. - * The structure is not used directly, but instead to cast the "internal" - * member of the smf_ctx structure. +/** + * @brief Private structure (to this file) used to track state machine context. + * The structure is not used directly, but instead to cast the "internal" + * member of the smf_ctx structure. */ struct internal_ctx { - bool new_state : 1; - bool terminate : 1; - bool exit : 1; - bool handled : 1; + bool new_state: 1; + bool terminate: 1; + bool is_exit: 1; + bool handled: 1; }; -static bool share_paren(const struct smf_state *test_state, - const struct smf_state *target_state) +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT +static bool share_paren(const struct smf_state *test_state, const struct smf_state *target_state) { - for (const struct smf_state *state = test_state; - state != NULL; - state = state->parent) { + for (const struct smf_state *state = test_state; state != NULL; state = state->parent) { if (target_state == state) { return true; } @@ -35,21 +33,10 @@ static bool share_paren(const struct smf_state *test_state, return false; } -static bool last_state_share_paren(struct smf_ctx *const ctx, - const struct smf_state *state) -{ - /* Get parent state of previous state */ - if (!ctx->previous) { - return false; - } - - return share_paren(ctx->previous->parent, state); -} - static const struct smf_state *get_child_of(const struct smf_state *states, const struct smf_state *parent) { - for (const struct smf_state *tmp = states; ; tmp = tmp->parent) { + for (const struct smf_state *tmp = states;; tmp = tmp->parent) { if (tmp->parent == parent) { return tmp; } @@ -68,22 +55,55 @@ static const struct smf_state *get_last_of(const struct smf_state *states) } /** - * @brief Execute all ancestor entry actions + * @brief Find the Least Common Ancestor (LCA) of two states + * + * @param source transition source + * @param dest transition destination + * @return LCA state, or NULL if states have no LCA. + */ +static const struct smf_state *get_lca_of(const struct smf_state *source, + const struct smf_state *dest) +{ + for (const struct smf_state *ancestor = source->parent; ancestor != NULL; + ancestor = ancestor->parent) { + if (ancestor == dest) { + return ancestor->parent; + } else if (share_paren(dest, ancestor)) { + return ancestor; + } + } + + return NULL; +} + +/** + * @brief Executes all entry actions from the direct child of topmost to the new state * * @param ctx State machine context - * @param target The entry actions of this target's ancestors are executed + * @param new_state State we are transitioning to + * @param topmost State we are entering from. Its entry action is not executed * @return true if the state machine should terminate, else false */ -__unused static bool smf_execute_ancestor_entry_actions( - struct smf_ctx *const ctx, const struct smf_state *target) +static bool smf_execute_all_entry_actions(struct smf_ctx *const ctx, + const struct smf_state *new_state, + const struct smf_state *topmost) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; - for (const struct smf_state *to_execute = get_last_of(target); - to_execute != NULL && to_execute != target; - to_execute = get_child_of(target, to_execute)) { - /* Execute parent state's entry */ - if (!last_state_share_paren(ctx, to_execute) && to_execute->entry) { + if (new_state == topmost) { + /* There are no child states, so do nothing */ + return false; + } + + for (const struct smf_state *to_execute = get_child_of(new_state, topmost); + to_execute != NULL && to_execute != new_state; + to_execute = get_child_of(new_state, to_execute)) { + /* Execute every entry action EXCEPT that of the topmost state */ + if (to_execute->entry) { + /* Keep track of the executing entry action in case it calls + * smf_set_State() + */ + ctx->executing = to_execute; to_execute->entry(ctx); /* No need to continue if terminate was set */ @@ -93,6 +113,16 @@ __unused static bool smf_execute_ancestor_entry_actions( } } + /* and execute the new state entry action */ + if (new_state->entry) { + new_state->entry(ctx); + + /* No need to continue if terminate was set */ + if (internal->terminate) { + return true; + } + } + return false; } @@ -103,9 +133,9 @@ __unused static bool smf_execute_ancestor_entry_actions( * @param target The run actions of this target's ancestors are executed * @return true if the state machine should terminate, else false */ -__unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) +static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; /* Execute all run actions in reverse order */ /* Return if the current state switched states */ @@ -126,9 +156,10 @@ __unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) } /* Try to run parent run actions */ - for (const struct smf_state *tmp_state = ctx->current->parent; - tmp_state != NULL; + for (const struct smf_state *tmp_state = ctx->current->parent; tmp_state != NULL; tmp_state = tmp_state->parent) { + /* Keep track of where we are in case an ancestor calls smf_set_state() */ + ctx->executing = tmp_state; /* Execute parent run action */ if (tmp_state->run) { tmp_state->run(ctx); @@ -156,39 +187,35 @@ __unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) } /** - * @brief Execute all ancestor exit actions + * @brief Executes all exit actions from ctx->current to the direct child of topmost * * @param ctx State machine context - * @param target The exit actions of this target's ancestors are executed + * @param topmost State we are exiting to. Its exit action is not executed * @return true if the state machine should terminate, else false */ -__unused static bool smf_execute_ancestor_exit_actions( - struct smf_ctx *const ctx, const struct smf_state *target) +static bool smf_execute_all_exit_actions(struct smf_ctx *const ctx, const struct smf_state *topmost) { - struct internal_ctx * const internal = (void *) &ctx->internal; - - /* Execute all parent exit actions in reverse order */ + struct internal_ctx *const internal = (void *)&ctx->internal; - for (const struct smf_state *tmp_state = ctx->current->parent; - tmp_state != NULL; - tmp_state = tmp_state->parent) { - if ((target == NULL || !share_paren(target->parent, tmp_state)) && - tmp_state->exit) { - tmp_state->exit(ctx); + for (const struct smf_state *to_execute = ctx->current; to_execute != topmost; + to_execute = to_execute->parent) { + if (to_execute->exit) { + to_execute->exit(ctx); - /* No need to continue if terminate was set */ + /* No need to continue if terminate was set in the exit action */ if (internal->terminate) { return true; } } } + return false; } +#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) { - struct internal_ctx * const internal = (void *) &ctx->internal; - + struct internal_ctx *const internal = (void *)&ctx->internal; #ifdef CONFIG_SMF_INITIAL_TRANSITION /* @@ -199,98 +226,150 @@ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) init_state = init_state->initial; } #endif - internal->exit = false; + + internal->is_exit = false; internal->terminate = false; ctx->current = init_state; ctx->previous = NULL; ctx->terminate_val = 0; - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - internal->new_state = false; +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + ctx->executing = init_state; + const struct smf_state *topmost = get_last_of(init_state); - if (smf_execute_ancestor_entry_actions(ctx, init_state)) { + /* Execute topmost state entry action, since smf_execute_all_entry_actions() + * doesn't + */ + if (topmost->entry) { + topmost->entry(ctx); + if (internal->terminate) { + /* No need to continue if terminate was set */ return; } } - /* Now execute the initial state's entry action */ + if (smf_execute_all_entry_actions(ctx, init_state, topmost)) { + /* No need to continue if terminate was set */ + return; + } +#else + /* execute entry action if it exists */ if (init_state->entry) { init_state->entry(ctx); } +#endif } -void smf_set_state(struct smf_ctx *const ctx, const struct smf_state *target) +void smf_set_state(struct smf_ctx *const ctx, const struct smf_state *new_state) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; + + if (new_state == NULL) { + LOG_ERR("new_state cannot be NULL"); + return; + } /* - * It does not make sense to call set_state in an exit phase of a state + * It does not make sense to call smf_set_state in an exit phase of a state * since we are already in a transition; we would always ignore the * intended state to transition into. */ - if (internal->exit) { - LOG_WRN("Calling %s from exit action", __func__); + if (internal->is_exit) { + LOG_ERR("Calling %s from exit action", __func__); return; } - internal->exit = true; +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + const struct smf_state *topmost; + + if (share_paren(ctx->executing, new_state)) { + /* new state is a parent of where we are now*/ + topmost = new_state; + } else if (share_paren(new_state, ctx->executing)) { + /* we are a parent of the new state */ + topmost = ctx->executing; + } else { + /* not directly related, find LCA */ + topmost = get_lca_of(ctx->executing, new_state); + } + + internal->is_exit = true; + internal->new_state = true; - /* Execute the current states exit action */ - if (ctx->current->exit) { - ctx->current->exit(ctx); + /* call all exit actions up to (but not including) the topmost */ + if (smf_execute_all_exit_actions(ctx, topmost)) { + /* No need to continue if terminate was set in the exit action */ + return; + } - /* - * No need to continue if terminate was set in the - * exit action - */ + /* if self-transition, call the exit action */ + if ((ctx->executing == new_state) && (new_state->exit)) { + new_state->exit(ctx); + + /* No need to continue if terminate was set in the exit action */ if (internal->terminate) { return; } } - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - internal->new_state = true; + internal->is_exit = false; + + /* if self transition, call the entry action */ + if ((ctx->executing == new_state) && (new_state->entry)) { + new_state->entry(ctx); - if (smf_execute_ancestor_exit_actions(ctx, target)) { + /* No need to continue if terminate was set in the entry action */ + if (internal->terminate) { return; } } - - internal->exit = false; - #ifdef CONFIG_SMF_INITIAL_TRANSITION /* * The final target will be the deepest leaf state that * the target contains. Set that as the real target. */ - while (target->initial) { - target = target->initial; + while (new_state->initial) { + new_state = new_state->initial; } #endif /* update the state variables */ ctx->previous = ctx->current; - ctx->current = target; + ctx->current = new_state; - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - if (smf_execute_ancestor_entry_actions(ctx, target)) { + /* call all entry actions (except those of topmost) */ + if (smf_execute_all_entry_actions(ctx, new_state, topmost)) { + /* No need to continue if terminate was set in the entry action */ + return; + } +#else + /* Flat state machines have a very simple transition: */ + if (ctx->current->exit) { + internal->is_exit = true; + ctx->current->exit(ctx); + /* No need to continue if terminate was set in the exit action */ + if (internal->terminate) { return; } + internal->is_exit = false; } + /* update the state variables */ + ctx->previous = ctx->current; + ctx->current = new_state; - /* Now execute the target entry action */ if (ctx->current->entry) { ctx->current->entry(ctx); - /* - * If terminate was set, it will be handled in the - * smf_run_state function - */ + /* No need to continue if terminate was set in the entry action */ + if (internal->terminate) { + return; + } } +#endif } void smf_set_terminate(struct smf_ctx *ctx, int32_t val) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; internal->terminate = true; ctx->terminate_val = val; @@ -305,22 +384,25 @@ void smf_set_handled(struct smf_ctx *ctx) int32_t smf_run_state(struct smf_ctx *const ctx) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; /* No need to continue if terminate was set */ if (internal->terminate) { return ctx->terminate_val; } +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + ctx->executing = ctx->current; +#endif + if (ctx->current->run) { ctx->current->run(ctx); } - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - if (smf_execute_ancestor_run_actions(ctx)) { - return ctx->terminate_val; - } +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + if (smf_execute_ancestor_run_actions(ctx)) { + return ctx->terminate_val; } - +#endif return 0; } diff --git a/tests/lib/smf/CMakeLists.txt b/tests/lib/smf/CMakeLists.txt index 08844e75aa62b2..3e793f984426c9 100644 --- a/tests/lib/smf/CMakeLists.txt +++ b/tests/lib/smf/CMakeLists.txt @@ -7,7 +7,7 @@ project(smf) target_sources(app PRIVATE src/main.c) if(CONFIG_SMF_INITIAL_TRANSITION) - target_sources(app PRIVATE src/test_lib_initial_transitions_smf.c) + target_sources(app PRIVATE src/test_lib_self_transition_smf.c) elseif(CONFIG_SMF_ANCESTOR_SUPPORT) target_sources(app PRIVATE src/test_lib_hierarchical_smf.c src/test_lib_hierarchical_5_ancestor_smf.c) diff --git a/tests/lib/smf/src/test_lib_initial_transitions_smf.c b/tests/lib/smf/src/test_lib_self_transition_smf.c similarity index 51% rename from tests/lib/smf/src/test_lib_initial_transitions_smf.c rename to tests/lib/smf/src/test_lib_self_transition_smf.c index 2e00dc2d553d90..c78e6fa04a5228 100644 --- a/tests/lib/smf/src/test_lib_initial_transitions_smf.c +++ b/tests/lib/smf/src/test_lib_self_transition_smf.c @@ -1,6 +1,7 @@ /* * Copyright 2024 Glenn Andrews * based on test_lib_hierarchical_smf.c + * Copyright 2021 The Chromium OS Authors * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,82 +10,100 @@ #include /* - * Hierarchical Test Transition: + * Hierarchical Test Transition to self: * - * PARENT_AB_ENTRY --> A_ENTRY --> A_RUN --> PARENT_AB_RUN ---| - * | - * |----------------------------------------------------------| - * | - * |--> A_EXIT --> B_ENTRY --> B_RUN --> B_EXIT --------------| - * | - * |----------------------------------------------------------| - * | - * |--> PARENT_AB_EXIT --> PARENT_C_ENTRY --> C_ENTRY --------| - * | - * |----------------------------------------------------------| - * | - * |--> C_RUN(#1) --> C_RUN(#2) --> C_EXIT --> PARENT_C_RUN --| - * | - * |----------------------------------------------------------| - * | - * |--> PARENT_C_EXIT + * This implements a hierarchical state machine using UML rules and demonstrates + * initial transitions, transitions to self (in PARENT_C) and smf_set_handled (in STATE_B) + * + * The order of entry, exit and run actions is given in the ordering of the test_value[] array. */ #define TEST_OBJECT(o) ((struct test_object *)o) -#define SMF_RUN 4 - -/* Initial Setup */ -#define PARENT_AB_ENTRY_BIT (1 << 0) -#define STATE_A_ENTRY_BIT (1 << 1) - -/* Run 0 */ -#define STATE_A_RUN_BIT (1 << 2) -#define PARENT_AB_RUN_BIT (1 << 3) -#define STATE_A_EXIT_BIT (1 << 4) -#define STATE_B_ENTRY_BIT (1 << 5) - -/* Run 1 */ -#define STATE_B_RUN_BIT (1 << 6) -#define STATE_B_EXIT_BIT (1 << 7) -#define PARENT_AB_EXIT_BIT (1 << 8) -#define PARENT_C_ENTRY_BIT (1 << 9) -#define STATE_C_ENTRY_BIT (1 << 10) - -/* Run 2 */ -#define STATE_C_1ST_RUN_BIT (1 << 11) - -/* Run 3 */ -#define STATE_C_2ND_RUN_BIT (1 << 12) -#define PARENT_C_RUN_BIT (1 << 13) -#define STATE_C_EXIT_BIT (1 << 14) -#define PARENT_C_EXIT_BIT (1 << 15) - -#define TEST_PARENT_ENTRY_VALUE_NUM 0 -#define TEST_PARENT_RUN_VALUE_NUM 3 -#define TEST_PARENT_EXIT_VALUE_NUM 8 -#define TEST_ENTRY_VALUE_NUM 1 +#define SMF_RUN 5 + +/* Initial Setup: Testing initial transitions */ +#define ROOT_ENTRY_BIT BIT(0) +#define PARENT_AB_ENTRY_BIT BIT(1) +#define STATE_A_ENTRY_BIT BIT(2) + +/* Run 0: normal state transition */ +#define STATE_A_RUN_BIT BIT(3) +#define STATE_A_EXIT_BIT BIT(4) +#define STATE_B_ENTRY_BIT BIT(5) + +/* Run 1: Test smf_set_handled() */ +#define STATE_B_1ST_RUN_BIT BIT(6) + +/* Run 2: Normal state transition via parent */ +#define STATE_B_2ND_RUN_BIT BIT(7) +#define PARENT_AB_RUN_BIT BIT(8) +#define STATE_B_EXIT_BIT BIT(9) +#define PARENT_AB_EXIT_BIT BIT(10) +#define PARENT_C_1ST_ENTRY_BIT BIT(11) +#define STATE_C_1ST_ENTRY_BIT BIT(12) + +/* Run 3: PARENT_C executes transition to self */ +#define STATE_C_1ST_RUN_BIT BIT(13) +#define PARENT_C_RUN_BIT BIT(14) +#define STATE_C_1ST_EXIT_BIT BIT(15) +#define PARENT_C_1ST_EXIT_BIT BIT(16) +#define PARENT_C_2ND_ENTRY_BIT BIT(17) +#define STATE_C_2ND_ENTRY_BIT BIT(18) + +/* Run 4: Test transition from parent state */ +#define STATE_C_2ND_RUN_BIT BIT(19) +#define STATE_C_2ND_EXIT_BIT BIT(20) +#define PARENT_C_2ND_EXIT_BIT BIT(21) + +/* Unused functions: Error checks if set */ +#define ROOT_RUN_BIT BIT(22) +#define ROOT_EXIT_BIT BIT(23) + +/* Number of state transitions for each test: */ +#define TEST_VALUE_NUM 22 +#define TEST_PARENT_ENTRY_VALUE_NUM 1 +#define TEST_PARENT_RUN_VALUE_NUM 8 +#define TEST_PARENT_EXIT_VALUE_NUM 10 +#define TEST_ENTRY_VALUE_NUM 2 #define TEST_RUN_VALUE_NUM 6 -#define TEST_EXIT_VALUE_NUM 14 -#define TEST_VALUE_NUM 16 +#define TEST_EXIT_VALUE_NUM 15 + +/* + * Note: Test values are taken before the appropriate test bit for that state is set i.e. if + * ROOT_ENTRY_BIT is BIT(0), test_value for root_entry() will be BIT_MASK(0) not BIT_MASK(1) + */ static uint32_t test_value[] = { - 0x00, /* PARENT_AB_ENTRY */ - 0x01, /* STATE_A_ENTRY */ - 0x03, /* STATE_A_RUN */ - 0x07, /* PARENT_AB_RUN */ - 0x0f, /* STATE_A_EXIT */ - 0x1f, /* STATE_B_ENTRY */ - 0x3f, /* STATE_B_RUN */ - 0x7f, /* STATE_B_EXIT */ - 0xff, /* PARENT_AB_EXIT */ - 0x1ff, /* PARENT_C_ENTRY */ - 0x3ff, /* STATE_C_ENTRY */ - 0x7ff, /* STATE_C_1ST_RUN */ - 0xfff, /* STATE_C_2ND_RUN */ - 0x1fff, /* STATE_C_EXIT */ - 0x3fff, /* PARENT_C_RUN */ - 0x7fff, /* PARENT_C_EXIT */ - 0xffff, /* FINAL VALUE */ + /* Initial Setup */ + BIT_MASK(0), /* ROOT_ENTRY_BIT */ + BIT_MASK(1), /* PARENT_AB_ENTRY_BIT */ + BIT_MASK(2), /* STATE_A_ENTRY_BIT */ + /* Run 0 */ + BIT_MASK(3), /* STATE_A_RUN_BIT */ + BIT_MASK(4), /* STATE_A_EXIT_BIT */ + BIT_MASK(5), /* STATE_B_ENTRY_BIT */ + /* Run 1 */ + BIT_MASK(6), /* STATE_B_1ST_RUN_BIT */ + /* Run 2 */ + BIT_MASK(7), /* STATE_B_2ND_RUN_BIT */ + BIT_MASK(8), /* PARENT_AB_RUN_BIT */ + BIT_MASK(9), /* STATE_B_EXIT_BIT */ + BIT_MASK(10), /* PARENT_AB_EXIT_BIT */ + BIT_MASK(11), /* PARENT_C_1ST_ENTRY_BIT */ + BIT_MASK(12), /* STATE_C_1ST_ENTRY_BIT */ + /* Run 3 */ + BIT_MASK(13), /* STATE_C_1ST_RUN_BIT */ + BIT_MASK(14), /* PARENT_C_RUN_BIT */ + BIT_MASK(15), /* STATE_C_1ST_EXIT_BIT */ + BIT_MASK(16), /* PARENT_C_1ST_EXIT_BIT */ + BIT_MASK(17), /* PARENT_C_2ND_ENTRY_BIT */ + BIT_MASK(18), /* STATE_C_2ND_ENTRY_BIT */ + /* Run 4 */ + BIT_MASK(19), /* STATE_C_2ND_RUN_BIT */ + BIT_MASK(20), /* STATE_C_2ND_EXIT_BIT */ + BIT_MASK(21), /* PARENT_C_2ND_EXIT_BIT */ + /* Post-run Check */ + BIT_MASK(22), /* FINAL_VALUE */ }; /* Forward declaration of test_states */ @@ -92,6 +111,7 @@ static const struct smf_state test_states[]; /* List of all TypeC-level states */ enum test_state { + ROOT, PARENT_AB, PARENT_C, STATE_A, @@ -110,6 +130,17 @@ enum terminate_action { EXIT }; +#define B_ENTRY_FIRST_TIME BIT(0) +#define B_RUN_FIRST_TIME BIT(1) +#define PARENT_C_ENTRY_FIRST_TIME BIT(2) +#define C_RUN_FIRST_TIME BIT(3) +#define C_ENTRY_FIRST_TIME BIT(4) +#define C_EXIT_FIRST_TIME BIT(5) + +#define FIRST_TIME_BITS \ + (B_ENTRY_FIRST_TIME | B_RUN_FIRST_TIME | PARENT_C_ENTRY_FIRST_TIME | C_RUN_FIRST_TIME | \ + C_ENTRY_FIRST_TIME | C_EXIT_FIRST_TIME) + static struct test_object { struct smf_ctx ctx; uint32_t transition_bits; @@ -118,14 +149,47 @@ static struct test_object { uint32_t first_time; } test_obj; -static void parent_ab_entry(void *obj) +static void root_entry(void *obj) { struct test_object *o = TEST_OBJECT(obj); o->tv_idx = 0; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test Parent AB entry failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Root entry failed"); + + o->transition_bits |= ROOT_ENTRY_BIT; +} + +static void root_run(void *obj) +{ + struct test_object *o = TEST_OBJECT(obj); + + o->tv_idx++; + + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Root run failed"); + + o->transition_bits |= ROOT_RUN_BIT; + + /* Return to parent run state */ +} + +static void root_exit(void *obj) +{ + struct test_object *o = TEST_OBJECT(obj); + + o->tv_idx++; + + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Root exit failed"); + o->transition_bits |= ROOT_EXIT_BIT; +} + +static void parent_ab_entry(void *obj) +{ + struct test_object *o = TEST_OBJECT(obj); + + o->tv_idx++; + + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Parent AB entry failed"); if (o->terminate == PARENT_ENTRY) { smf_set_terminate(obj, -1); @@ -141,8 +205,7 @@ static void parent_ab_run(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test Parent AB run failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Parent AB run failed"); if (o->terminate == PARENT_RUN) { smf_set_terminate(obj, -1); @@ -151,7 +214,7 @@ static void parent_ab_run(void *obj) o->transition_bits |= PARENT_AB_RUN_BIT; - smf_set_state(SMF_CTX(obj), &test_states[STATE_B]); + smf_set_state(SMF_CTX(obj), &test_states[STATE_C]); } static void parent_ab_exit(void *obj) @@ -160,8 +223,7 @@ static void parent_ab_exit(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test Parent AB exit failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Parent AB exit failed"); if (o->terminate == PARENT_EXIT) { smf_set_terminate(obj, -1); @@ -177,9 +239,13 @@ static void parent_c_entry(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test Parent C entry failed"); - o->transition_bits |= PARENT_C_ENTRY_BIT; + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Parent C entry failed"); + if (o->first_time & PARENT_C_ENTRY_FIRST_TIME) { + o->first_time &= ~PARENT_C_ENTRY_FIRST_TIME; + o->transition_bits |= PARENT_C_1ST_ENTRY_BIT; + } else { + o->transition_bits |= PARENT_C_2ND_ENTRY_BIT; + } } static void parent_c_run(void *obj) @@ -188,14 +254,11 @@ static void parent_c_run(void *obj) o->tv_idx++; - if (o->first_time) { - /* This state should not be reached */ - zassert_true(0, "Test Parent C run failed"); - } else { - o->transition_bits |= PARENT_C_RUN_BIT; + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Parent C run failed"); - smf_set_state(SMF_CTX(obj), &test_states[STATE_D]); - } + o->transition_bits |= PARENT_C_RUN_BIT; + + smf_set_state(SMF_CTX(obj), &test_states[PARENT_C]); } static void parent_c_exit(void *obj) @@ -204,9 +267,14 @@ static void parent_c_exit(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test Parent C exit failed"); - o->transition_bits |= PARENT_C_EXIT_BIT; + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test Parent C exit failed"); + + if (o->first_time & B_ENTRY_FIRST_TIME) { + o->first_time &= ~B_ENTRY_FIRST_TIME; + o->transition_bits |= PARENT_C_1ST_EXIT_BIT; + } else { + o->transition_bits |= PARENT_C_2ND_EXIT_BIT; + } } static void state_a_entry(void *obj) @@ -215,8 +283,7 @@ static void state_a_entry(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State A entry failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State A entry failed"); if (o->terminate == ENTRY) { smf_set_terminate(obj, -1); @@ -232,12 +299,11 @@ static void state_a_run(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State A run failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State A run failed"); o->transition_bits |= STATE_A_RUN_BIT; - /* Return to parent run state */ + smf_set_state(SMF_CTX(obj), &test_states[STATE_B]); } static void state_a_exit(void *obj) @@ -246,8 +312,7 @@ static void state_a_exit(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State A exit failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State A exit failed"); o->transition_bits |= STATE_A_EXIT_BIT; } @@ -257,8 +322,8 @@ static void state_b_entry(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State B entry failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State B entry failed"); + o->transition_bits |= STATE_B_ENTRY_BIT; } @@ -268,17 +333,21 @@ static void state_b_run(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State B run failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State B run failed"); if (o->terminate == RUN) { smf_set_terminate(obj, -1); return; } - o->transition_bits |= STATE_B_RUN_BIT; - - smf_set_state(SMF_CTX(obj), &test_states[STATE_C]); + if (o->first_time & B_RUN_FIRST_TIME) { + o->first_time &= ~B_RUN_FIRST_TIME; + o->transition_bits |= STATE_B_1ST_RUN_BIT; + smf_set_handled(SMF_CTX(obj)); + } else { + o->transition_bits |= STATE_B_2ND_RUN_BIT; + /* bubble up to PARENT_AB */ + } } static void state_b_exit(void *obj) @@ -287,8 +356,8 @@ static void state_b_exit(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State B exit failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State B exit failed"); + o->transition_bits |= STATE_B_EXIT_BIT; } @@ -298,9 +367,13 @@ static void state_c_entry(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State C entry failed"); - o->transition_bits |= STATE_C_ENTRY_BIT; + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State C entry failed"); + if (o->first_time & C_ENTRY_FIRST_TIME) { + o->first_time &= ~C_ENTRY_FIRST_TIME; + o->transition_bits |= STATE_C_1ST_ENTRY_BIT; + } else { + o->transition_bits |= STATE_C_2ND_ENTRY_BIT; + } } static void state_c_run(void *obj) @@ -309,16 +382,15 @@ static void state_c_run(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State C run failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State C run failed"); - if (o->first_time) { - o->first_time = false; + if (o->first_time & C_RUN_FIRST_TIME) { + o->first_time &= ~C_RUN_FIRST_TIME; o->transition_bits |= STATE_C_1ST_RUN_BIT; - smf_set_handled(SMF_CTX(obj)); - } else { /* Do nothing, Let parent handle it */ + } else { o->transition_bits |= STATE_C_2ND_RUN_BIT; + smf_set_state(SMF_CTX(obj), &test_states[STATE_D]); } } @@ -328,15 +400,19 @@ static void state_c_exit(void *obj) o->tv_idx++; - zassert_equal(o->transition_bits, test_value[o->tv_idx], - "Test State C exit failed"); + zassert_equal(o->transition_bits, test_value[o->tv_idx], "Test State C exit failed"); if (o->terminate == EXIT) { smf_set_terminate(obj, -1); return; } - o->transition_bits |= STATE_C_EXIT_BIT; + if (o->first_time & C_EXIT_FIRST_TIME) { + o->first_time &= ~C_EXIT_FIRST_TIME; + o->transition_bits |= STATE_C_1ST_EXIT_BIT; + } else { + o->transition_bits |= STATE_C_2ND_EXIT_BIT; + } } static void state_d_entry(void *obj) @@ -357,26 +433,27 @@ static void state_d_exit(void *obj) } static const struct smf_state test_states[] = { - [PARENT_AB] = SMF_CREATE_STATE(parent_ab_entry, parent_ab_run, - parent_ab_exit, NULL, &test_states[STATE_A]), - [PARENT_C] = SMF_CREATE_STATE(parent_c_entry, parent_c_run, - parent_c_exit, NULL, &test_states[STATE_C]), + [ROOT] = SMF_CREATE_STATE(root_entry, root_run, root_exit, NULL, &test_states[PARENT_AB]), + [PARENT_AB] = SMF_CREATE_STATE(parent_ab_entry, parent_ab_run, parent_ab_exit, + &test_states[ROOT], &test_states[STATE_A]), + [PARENT_C] = SMF_CREATE_STATE(parent_c_entry, parent_c_run, parent_c_exit, + &test_states[ROOT], &test_states[STATE_C]), [STATE_A] = SMF_CREATE_STATE(state_a_entry, state_a_run, state_a_exit, &test_states[PARENT_AB], NULL), [STATE_B] = SMF_CREATE_STATE(state_b_entry, state_b_run, state_b_exit, &test_states[PARENT_AB], NULL), [STATE_C] = SMF_CREATE_STATE(state_c_entry, state_c_run, state_c_exit, &test_states[PARENT_C], NULL), - [STATE_D] = SMF_CREATE_STATE(state_d_entry, state_d_run, state_d_exit, - NULL, NULL), + [STATE_D] = SMF_CREATE_STATE(state_d_entry, state_d_run, state_d_exit, &test_states[ROOT], + NULL), }; -ZTEST(smf_tests, test_smf_initial_transitions) +ZTEST(smf_tests, test_smf_self_transition) { /* A) Test state transitions */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = NONE; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); @@ -386,15 +463,14 @@ ZTEST(smf_tests, test_smf_initial_transitions) } } - zassert_equal(TEST_VALUE_NUM, test_obj.tv_idx, - "Incorrect test value index"); + zassert_equal(TEST_VALUE_NUM, test_obj.tv_idx, "Incorrect test value index"); zassert_equal(test_obj.transition_bits, test_value[test_obj.tv_idx], "Final state not reached"); /* B) Test termination in parent entry action */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = PARENT_ENTRY; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); @@ -412,7 +488,7 @@ ZTEST(smf_tests, test_smf_initial_transitions) /* C) Test termination in parent run action */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = PARENT_RUN; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); @@ -430,7 +506,7 @@ ZTEST(smf_tests, test_smf_initial_transitions) /* D) Test termination in parent exit action */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = PARENT_EXIT; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); @@ -448,7 +524,7 @@ ZTEST(smf_tests, test_smf_initial_transitions) /* E) Test termination in child entry action */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = ENTRY; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); @@ -466,7 +542,7 @@ ZTEST(smf_tests, test_smf_initial_transitions) /* F) Test termination in child run action */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = RUN; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); @@ -484,7 +560,7 @@ ZTEST(smf_tests, test_smf_initial_transitions) /* G) Test termination in child exit action */ test_obj.transition_bits = 0; - test_obj.first_time = 1; + test_obj.first_time = FIRST_TIME_BITS; test_obj.terminate = EXIT; smf_set_initial((struct smf_ctx *)&test_obj, &test_states[PARENT_AB]); diff --git a/tests/lib/smf/src/test_lib_smf.h b/tests/lib/smf/src/test_lib_smf.h index 6296352fb73e8d..032dec06f79aa2 100644 --- a/tests/lib/smf/src/test_lib_smf.h +++ b/tests/lib/smf/src/test_lib_smf.h @@ -10,6 +10,6 @@ void test_smf_flat(void); void test_smf_hierarchical(void); void test_smf_hierarchical_5_ancestors(void); -void test_smf_initial_transitions(void); +void test_smf_self_transition(void); #endif /* ZEPHYR_TEST_LIB_SMF_H_ */ From 9d3a781728a6bc02de9eeffeb72245481aaee972 Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1237/1389] docs: bitarray: fix missing documentation for method sys_bitarray_xor that was added recently. Signed-off-by: Lucas Romero --- include/zephyr/sys/bitarray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/sys/bitarray.h b/include/zephyr/sys/bitarray.h index ebd18081cc53ca..35ee721ddf799c 100644 --- a/include/zephyr/sys/bitarray.h +++ b/include/zephyr/sys/bitarray.h @@ -168,7 +168,7 @@ int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *p int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, size_t *offset); -/* +/** * Calculates the bit-wise XOR of two bitarrays in a region. * The result is stored in the first bitarray passed in (@p dst). * Both bitarrays must be of the same size. From 6946c983de653f85fa5e833c212821bdda73404c Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Sun, 26 May 2024 22:39:33 +0200 Subject: [PATCH 1238/1389] tests: net: net_pkt: Fix typo This fixes what seems to be a copy and paste error. Signed-off-by: Reto Schneider --- tests/net/net_pkt/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/net_pkt/src/main.c b/tests/net/net_pkt/src/main.c index 73e20fba51af34..7dd3f8fd716590 100644 --- a/tests/net/net_pkt/src/main.c +++ b/tests/net/net_pkt/src/main.c @@ -1265,7 +1265,7 @@ ZTEST(net_pkt_test_suite, test_net_pkt_shallow_clone_append_buf_0) ZTEST(net_pkt_test_suite, test_net_pkt_shallow_clone_append_buf_1) { - test_net_pkt_shallow_clone_append_buf(2); + test_net_pkt_shallow_clone_append_buf(1); } ZTEST(net_pkt_test_suite, test_net_pkt_shallow_clone_append_buf_2) From a048f71e886caa64452da8d6fc8a6ef607bbdff1 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1239/1389] tests: drivers: uart: uart_pm fix 'rxbuf' may be used uninitialized Fix for uart_pm/src/main.c:106:23: error: 'rxbuf' may be used uninitialized [-Werror=maybe-uninitialized] string.h:62:10: note: by argument 2 of type 'const void *' to 'memcmp' 62 | int memcmp (const void *, const void *, size_t); | ^~~~~~ tests/drivers/uart/uart_pm/src/main.c:69:17: note: 'rxbuf' declared here 69 | uint8_t rxbuf[32]; | ^~~~~ Signed-off-by: Piotr Kosycarz --- tests/drivers/uart/uart_pm/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drivers/uart/uart_pm/src/main.c b/tests/drivers/uart/uart_pm/src/main.c index 07e75ec8dd654a..e28d55efb3317d 100644 --- a/tests/drivers/uart/uart_pm/src/main.c +++ b/tests/drivers/uart/uart_pm/src/main.c @@ -66,7 +66,7 @@ static void async_callback(const struct device *dev, struct uart_event *evt, voi static bool async_verify(const struct device *dev, bool active) { char txbuf[] = "test"; - uint8_t rxbuf[32]; + uint8_t rxbuf[32] = { 0 }; volatile bool tx_done = false; int err; From 0da168e36c447319cb7ccdef6f207529d6a562bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1240/1389] samples: drivers: adc_sequence: Fix expected console output regex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a missing space in the regular expression that defines the expected console output so that it matches what the sample actually produces. Signed-off-by: Andrzej Głąbek --- samples/drivers/adc/adc_sequence/sample.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/drivers/adc/adc_sequence/sample.yaml b/samples/drivers/adc/adc_sequence/sample.yaml index f9f657b4fbb006..5f6436c076d696 100644 --- a/samples/drivers/adc/adc_sequence/sample.yaml +++ b/samples/drivers/adc/adc_sequence/sample.yaml @@ -16,6 +16,6 @@ tests: harness_config: type: multi_line regex: - - "ADC sequence reading\\[\\d+\\]:" + - "ADC sequence reading \\[\\d+\\]:" - "- .+, channel \\d+, \\d+ sequence samples:" - "- - \\d+ (= \\d+mV)|(\\(value in mV not available\\))" From af63134c56a2290b92b890b2d90503eaa5d4808c Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1241/1389] tests: net: socket: getaddrinfo: Increase ztest stack size The ztest stack was to low to execute tests on some platforms (spotted on nrf52840dk/nrf52840), hence increase it. Signed-off-by: Robert Lubos --- tests/net/socket/getaddrinfo/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/net/socket/getaddrinfo/prj.conf b/tests/net/socket/getaddrinfo/prj.conf index 7b98922798d170..986f25150343aa 100644 --- a/tests/net/socket/getaddrinfo/prj.conf +++ b/tests/net/socket/getaddrinfo/prj.conf @@ -23,6 +23,7 @@ CONFIG_DNS_SERVER1="[::1]:15353" CONFIG_DNS_SERVER2="127.0.0.1:15353" CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_ZTEST=y # User mode requirements From c398d716a5ebaef881083e9c5130eb50f27a0a5a Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1242/1389] net: tls_credentials: Add missing base64.h header inclusion base64_encode() was used w/o including the base64.h header. This commit fixes it. Signed-off-by: Robert Lubos --- subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c index 95c41984de2f5d..6752f8dd506d81 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c +++ b/subsys/net/lib/tls_credentials/tls_credentials_digest_raw.c @@ -19,6 +19,7 @@ #if defined(CONFIG_PSA_WANT_ALG_SHA_256) && defined(CONFIG_BASE64) #include +#include int credential_digest_raw(struct tls_credential *credential, void *dest, size_t *len) { From e8c5deb80911b438540eab29b21ebffc4efae200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1243/1389] tests: temp: Add overlay for nRF54L15 DK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support to activate testing on TEMP. Signed-off-by: Karol Lasończyk --- .../temp_sensor/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/drivers/sensor/temp_sensor/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/tests/drivers/sensor/temp_sensor/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/tests/drivers/sensor/temp_sensor/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..435e4f4a6ccf81 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,3 @@ +temp_sensor: &temp { + status = "okay"; +}; From 7bf2fb2a6009bbeaadf8100ec9c5f9bece28fbd4 Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1244/1389] samples/subsys/shell/shell_module/overlays: revert to the default prompt This commits reverts two targets back to the default prompt in the Shell Sample: * intel_socfpga_agilex_socdk * intel_socfpga_agilex5_socdk Signed-off-by: Filip Kokosinski --- .../shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf | 3 --- .../shell/shell_module/boards/intel_socfpga_agilex_socdk.conf | 3 --- 2 files changed, 6 deletions(-) diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf index b96ff81fe83394..f05bf210213ccf 100644 --- a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf @@ -5,9 +5,6 @@ CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SHELL_STACK_SIZE=8192 -# Setting the Shell prompt -CONFIG_SHELL_PROMPT_UART="agilex5$ " - # Setting the max argc CONFIG_SHELL_ARGC_MAX=12 diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf index 22a3788b1b80a2..bc86125f5d585d 100644 --- a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf @@ -5,9 +5,6 @@ CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SHELL_STACK_SIZE=8192 -# Setting the Shell prompt -CONFIG_SHELL_PROMPT_UART="agilex$ " - # Setting the max argc CONFIG_SHELL_ARGC_MAX=12 From 950ddeed2762938763b529460d1a90181ea4e1b9 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1245/1389] cmake: modules: extensions: Check for missing blobs in zephyr_blobs_verify Add a separate warning/error message if a blob is missing. Signed-off-by: Pieter De Gendt --- cmake/modules/extensions.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 158321bf4a3f7a..315890732c3217 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -1760,9 +1760,11 @@ function(zephyr_blobs_verify) message(VERBOSE "Verifying blob \"${path}\"") - # Each path that has a correct sha256 is prefixed with an A - if(NOT "A ${path}" IN_LIST BLOBS_LIST) - message(${msg_lvl} "Blob for path \"${path}\" isn't valid.") + if(NOT EXISTS "${path}") + message(${msg_lvl} "Blob for path \"${path}\" missing. Update with: west blobs fetch") + elseif(NOT "A ${path}" IN_LIST BLOBS_LIST) + # Each path that has a correct sha256 is prefixed with an A + message(${msg_lvl} "Blob for path \"${path}\" isn't valid. Update with: west blobs fetch") endif() endforeach() else() @@ -1773,7 +1775,9 @@ function(zephyr_blobs_verify) message(VERBOSE "Verifying blob \"${path}\"") - if(NOT "${status}" STREQUAL "A") + if(NOT EXISTS "${path}") + message(${msg_lvl} "Blob for path \"${path}\" missing. Update with: west blobs fetch ${BLOBS_VERIFY_MODULE}") + elseif(NOT "${status}" STREQUAL "A") message(${msg_lvl} "Blob for path \"${path}\" isn't valid. Update with: west blobs fetch ${BLOBS_VERIFY_MODULE}") endif() endforeach() From 61064dd05b2d1b234f6ccd8170da47a1613c913c Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1246/1389] x86: ia32: linker: move bss/noinit sections after data section With this change, bss/noinit sections are excluded from generated kernel binary. Smaller image size saves storage space and reduces loading time. Signed-off-by: Dong Wang --- include/zephyr/arch/x86/ia32/linker.ld | 68 +++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index a0e2f5c6732ebd..0d1e67147c49ab 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -417,43 +417,10 @@ SECTIONS _app_smem_num_words = _app_smem_size >> 2; #endif /* CONFIG_USERSPACE */ - SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD),) - { - MMU_PAGE_ALIGN_PERM -#if !defined(CONFIG_USERSPACE) - _image_ram_start = .; -#endif - /* - * For performance, BSS section is forced to be both 4 byte aligned and - * a multiple of 4 bytes. - */ - . = ALIGN(4); - __kernel_ram_start = .; - __bss_start = .; - - *(.bss) - *(".bss.*") - *(COMMON) - *(".kernel_bss.*") - - /* - * As memory is cleared in words only, it is simpler to ensure the BSS - * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. - */ - . = ALIGN(4); - __bss_end = .; - } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - __bss_num_words = (__bss_end - __bss_start) >> 2; - -#include - - MMU_PAGE_ALIGN_PERM - - SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) { + MMU_PAGE_ALIGN_PERM __data_region_start = .; __data_start = .; @@ -503,6 +470,39 @@ SECTIONS MMU_PAGE_ALIGN __data_region_end = .; + SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD),) + { + MMU_PAGE_ALIGN_PERM +#if !defined(CONFIG_USERSPACE) + _image_ram_start = .; +#endif + /* + * For performance, BSS section is forced to be both 4 byte aligned and + * a multiple of 4 bytes. + */ + . = ALIGN(4); + __kernel_ram_start = .; + __bss_start = .; + + *(.bss) + *(".bss.*") + *(COMMON) + *(".kernel_bss.*") + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + . = ALIGN(4); + __bss_end = .; + } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + __bss_num_words = (__bss_end - __bss_start) >> 2; + +#include + + MMU_PAGE_ALIGN_PERM + /* All unused memory also owned by the kernel for heaps */ __kernel_ram_end = KERNEL_BASE_ADDR + KERNEL_RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; From 125b86991ce8f65542453eb17a316b6310000312 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1247/1389] drivers: crypto: smartbond: Add support for PM This commit should add all the functionality needed for the crypto driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios --- drivers/crypto/crypto_smartbond.c | 64 ++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/crypto_smartbond.c b/drivers/crypto/crypto_smartbond.c index 5b003875b93f26..9a9d1edeff9950 100644 --- a/drivers/crypto/crypto_smartbond.c +++ b/drivers/crypto/crypto_smartbond.c @@ -12,7 +12,11 @@ #include #include #include +#include #include +#include +#include +#include #include LOG_MODULE_REGISTER(crypto_smartbond_crypto, CONFIG_CRYPTO_LOG_LEVEL); @@ -114,6 +118,21 @@ static void smartbond_crypto_isr(const void *arg) } } +static inline void crypto_smartbond_pm_policy_state_lock_get(const struct device *dev) +{ + /* + * Prevent the SoC from entering the normal sleep state as PDC does not support + * waking up the application core following AES/HASH events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); +} + +static inline void crypto_smartbond_pm_policy_state_lock_put(const struct device *dev) +{ + /* Allow the SoC to enter the normal sleep state once AES/HASH operations are done. */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); +} + static bool crypto_smartbond_lock_session(const struct device *dev) { bool lock = false; @@ -123,6 +142,9 @@ static bool crypto_smartbond_lock_session(const struct device *dev) if (!in_use) { in_use = true; + /* Prevent sleep as long as a cryptographic session is in place */ + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + crypto_smartbond_pm_policy_state_lock_get(dev); crypto_smartbond_set_status(true); lock = true; } @@ -141,6 +163,8 @@ static void crypto_smartbond_unlock_session(const struct device *dev) if (in_use) { in_use = false; crypto_smartbond_set_status(false); + crypto_smartbond_pm_policy_state_lock_put(dev); + da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); } k_sem_give(&data->session_sem); @@ -913,6 +937,33 @@ static struct crypto_driver_api crypto_smartbond_driver_api = { .query_hw_caps = crypto_smartbond_query_hw_caps }; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int crypto_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* + * No need to perform any actions here as the AES/HASH controller + * should already be turned off. + */ + break; + case PM_DEVICE_ACTION_RESUME: + /* + * No need to perform any actions here as the AES/HASH controller + * will be initialized upon acquiring a cryptographic session. + */ + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + static int crypto_smartbond_init(const struct device *dev) { struct crypto_smartbond_data *data = dev->data; @@ -931,9 +982,17 @@ static int crypto_smartbond_init(const struct device *dev) IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_crypto_isr, DEVICE_DT_INST_GET(0), 0); + /* Controller should be initialized once a crypyographic session is requested */ crypto_smartbond_set_status(false); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#else return 0; +#endif } /* @@ -944,10 +1003,13 @@ static int crypto_smartbond_init(const struct device *dev) BUILD_ASSERT((inst) == 0, \ "multiple instances are not supported"); \ \ + PM_DEVICE_DT_INST_DEFINE(inst, crypto_smartbond_pm_action); \ + \ static struct crypto_smartbond_data crypto_smartbond_data_##inst; \ \ DEVICE_DT_INST_DEFINE(0, \ - crypto_smartbond_init, NULL, \ + crypto_smartbond_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &crypto_smartbond_data_##inst, NULL, \ POST_KERNEL, \ CONFIG_CRYPTO_INIT_PRIORITY, \ From ccfd49a97b61a7835e5e31090f3432ccbd7db33e Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1248/1389] drivers: spi: stm32: add runtime PM support Add runtime power management suppor to the STM32 SPI driver. This allows the driver to be suspended when not in use, and as a stop effect removes the need to suspend/resume around each transition to stop mode. Signed-off-by: Aurelien Jarno --- drivers/spi/spi_ll_stm32.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 39ee5c2451ec6e..7b557ebd07b5c1 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -20,6 +20,7 @@ LOG_MODULE_REGISTER(spi_ll_stm32); #include #include #include +#include #ifdef CONFIG_SPI_STM32_DMA #include #include @@ -82,6 +83,7 @@ static void spi_stm32_pm_policy_state_lock_get(const struct device *dev) if (IS_ENABLED(CONFIG_PM_S2RAM)) { pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_RAM, PM_ALL_SUBSTATES); } + pm_device_runtime_get(dev); } } } @@ -93,6 +95,7 @@ static void spi_stm32_pm_policy_state_lock_put(const struct device *dev) if (data->pm_policy_state_on) { data->pm_policy_state_on = false; + pm_device_runtime_put(dev); pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); if (IS_ENABLED(CONFIG_PM_S2RAM)) { pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_RAM, PM_ALL_SUBSTATES); @@ -1224,7 +1227,7 @@ static int spi_stm32_init(const struct device *dev) spi_context_unlock_unconditionally(&data->ctx); - return 0; + return pm_device_runtime_enable(dev); } #ifdef CONFIG_PM_DEVICE From 21e88e51fed2788b6644b6a1bd4cde617fe69688 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1249/1389] soc: st: stm32: stm32g0x: enable ART flash cache accelerator Enable instruction cache and prefetching on STM32G0X SoC family. Signed-off-by: Aurelien Jarno --- soc/st/stm32/stm32g0x/soc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/soc/st/stm32/stm32g0x/soc.c b/soc/st/stm32/stm32g0x/soc.c index 77c66858a2f77b..bab4e3dbca24a8 100644 --- a/soc/st/stm32/stm32g0x/soc.c +++ b/soc/st/stm32/stm32g0x/soc.c @@ -16,8 +16,8 @@ #include #include -#if defined(SYSCFG_CFGR1_UCPD1_STROBE) || defined(SYSCFG_CFGR1_UCPD2_STROBE) #include +#if defined(SYSCFG_CFGR1_UCPD1_STROBE) || defined(SYSCFG_CFGR1_UCPD2_STROBE) #include #endif /* SYSCFG_CFGR1_UCPD1_STROBE || SYSCFG_CFGR1_UCPD2_STROBE */ @@ -81,6 +81,10 @@ static void stm32g0_disable_dead_battery(void) */ static int stm32g0_init(void) { + /* Enable ART Accelerator I-cache and prefetch */ + LL_FLASH_EnableInstCache(); + LL_FLASH_EnablePrefetch(); + /* Update CMSIS SystemCoreClock variable (HCLK) */ /* At reset, system core clock is set to 16 MHz from HSI */ SystemCoreClock = 16000000; From 0d963be050057d40e8f094e233320ba72171ec75 Mon Sep 17 00:00:00 2001 From: Jason Murphy Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1250/1389] samples: net: add secure MQTT sensor/actuator device sample This sample demonstrates the implementation of an (industrial) IoT sensor/actuator device. The application uses the MQTT protocol to securely send sensor data to a remote MQTT broker, while responding to commands received over the MQTT connection. Signed-off-by: Jason Murphy --- .../CMakeLists.txt | 11 + .../net/secure_mqtt_sensor_actuator/Kconfig | 58 ++ .../secure_mqtt_sensor_actuator/README.rst | 219 ++++++++ .../boards/adi_eval_adin1110ebz.overlay | 15 + .../overlay-static-insecure.conf | 18 + .../overlay-static.conf | 8 + .../net/secure_mqtt_sensor_actuator/prj.conf | 59 ++ .../secure_mqtt_sensor_actuator/sample.yaml | 33 ++ .../secure_mqtt_sensor_actuator/src/device.c | 138 +++++ .../secure_mqtt_sensor_actuator/src/device.h | 56 ++ .../secure_mqtt_sensor_actuator/src/main.c | 140 +++++ .../src/mqtt_client.c | 510 ++++++++++++++++++ .../src/mqtt_client.h | 43 ++ .../src/tls_config/cert.h | 45 ++ 14 files changed, 1353 insertions(+) create mode 100644 samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt create mode 100644 samples/net/secure_mqtt_sensor_actuator/Kconfig create mode 100644 samples/net/secure_mqtt_sensor_actuator/README.rst create mode 100644 samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay create mode 100644 samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf create mode 100644 samples/net/secure_mqtt_sensor_actuator/overlay-static.conf create mode 100644 samples/net/secure_mqtt_sensor_actuator/prj.conf create mode 100644 samples/net/secure_mqtt_sensor_actuator/sample.yaml create mode 100644 samples/net/secure_mqtt_sensor_actuator/src/device.c create mode 100644 samples/net/secure_mqtt_sensor_actuator/src/device.h create mode 100644 samples/net/secure_mqtt_sensor_actuator/src/main.c create mode 100644 samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c create mode 100644 samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h create mode 100644 samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h diff --git a/samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt b/samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt new file mode 100644 index 00000000000000..af4feece2dc506 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(secure_mqtt_sensor_actuator) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config) diff --git a/samples/net/secure_mqtt_sensor_actuator/Kconfig b/samples/net/secure_mqtt_sensor_actuator/Kconfig new file mode 100644 index 00000000000000..19d15187acf26d --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/Kconfig @@ -0,0 +1,58 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Secure MQTT Sensor Actuator Sample Application" + +config NET_SAMPLE_MQTT_BROKER_HOSTNAME + string "Hostname of MQTT broker" + default "test.mosquitto.org" + help + MQTT broker's hostname or IP address. + +config NET_SAMPLE_MQTT_BROKER_PORT + string "MQTT Broker Connection Port" + default "8883" + help + Port through which the application should connect to the MQTT broker. + Secure MQTT uses port 8883. + +config NET_SAMPLE_MQTT_PUB_TOPIC + string "The MQTT topic the application should publish data to" + default "zephyr_sample/sensor" + +config NET_SAMPLE_MQTT_SUB_TOPIC_CMD + string "The MQTT topic the application will receive commands on" + default "zephyr_sample/command" + +config NET_SAMPLE_MQTT_PUBLISH_INTERVAL + int "Interval between MQTT publishes (in seconds)" + default 3 + help + This config determines the frequency at which MQTT publishes occur. + +choice NET_SAMPLE_MQTT_QOS + prompt "Quality of Service level used for MQTT publish and subscribe" + default NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE + +config NET_SAMPLE_MQTT_QOS_0_AT_MOST_ONCE + bool "QoS 0 / At most once delivery" + help + No acknowledgment needed for published message. + +config NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE + bool "QoS 1 / At least once delivery" + help + If acknowledgment expected for published message, duplicate messages permitted. + +config NET_SAMPLE_MQTT_QOS_2_EXACTLY_ONCE + bool "QoS 2 / Exactly once delivery" + help + Acknowledgment expected and message shall be published only once. + +endchoice + +config NET_SAMPLE_MQTT_PAYLOAD_SIZE + int "Size of MQTT payload in bytes" + default 128 + +source "Kconfig.zephyr" diff --git a/samples/net/secure_mqtt_sensor_actuator/README.rst b/samples/net/secure_mqtt_sensor_actuator/README.rst new file mode 100644 index 00000000000000..b2ff6a1573c148 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/README.rst @@ -0,0 +1,219 @@ +.. zephyr:code-sample:: secure-mqtt-sensor-actuator + :name: Secure MQTT Sensor/Actuator + :relevant-api: mqtt_socket sensor_interface + + Implement an MQTT-based IoT sensor/actuator device + +Overview +******** + +This sample demonstrates the implementation of an IoT sensor/actuator device. +The application uses the MQTT protocol to securely send sensor data +to a remote MQTT broker, while responding to commands received over MQTT. + +Features: + +- Establishing network connectivity using a DHCPv4 lease +- Establishing a secure MQTT connection (using TLS 1.2) to MQTT broker +- Publishing temperature sensor data in JSON format to the MQTT broker at a user-defined interval +- Subscribing to user-defined topic(s) on MQTT broker +- Responding to commands received over the network (LED control) +- Handling of MQTT connection, re-connecting and keep-alive +- Network status LED + +Requirements +************ +- Board with network capability (tested with adi_eval_adin1110ebz) +- `Eclipse Mosquitto`_ MQTT broker +- DHCP server +- Network connection between the board and Mosquitto broker + +Build and Running +***************** +This application relies on an network connection between the board and an MQTT broker. +This broker can exist locally (e.g. on a host PC) or a publicly available MQTT broker + can be used. +For quick sampling/testing, a configuration is provided to connect to a local MQTT broker +without security, using a static IP address. + +Hardware Setup +============== +If using Ethernet, connect the board to the MQTT broker. This may be your host PC +(for locally hosted Mosquitto broker) or your internet router +(to connect to the public Mosquitto broker). +If required, connect a temperature sensor to the board. + +Software Setup +============== +The temperature sensor should be aliased in devicetree as ``ambient-temp0``. +If a board does not include an on-board temperature sensor, one can be connected externally +and a board overlay file used to add the sensor and alias: + +.. code-block:: devicetree + + / { + aliases { + ambient-temp0 = &adt7420; + }; + }; + }; + +It is possible to use other types of sensors, by adding them in devicetree and by changing +``SENSOR_CHAN`` :file:`in device.c` to match the desired sensor type. + +There are a few ways to configure the application: + +.. list-table:: + + * - :file:`prj.conf` + - Default config: Secure MQTT, dynamic IP address (DHCP) + + * - :file:`overlay-static.conf` + - Secure MQTT, static IP address + + * - :file:`overlay-static-insecure.conf` + - Unsecure MQTT, static IP address + +**Default Config:** + +Using the default config, the application will use DHCP to acquire an IP address and attempt +to securely connect to an MQTT broker using TLS 1.2. + +- The MQTT broker to which the board will connect is specified by + ``CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME``. + By default, this is set to test.mosquitto.org. +- Connecting securely using TLS, requires the inclusion of the broker's CA certificate + in the application. +- Download the CA certificate in DER or PEM format from https://test.mosquitto.org +- In :file:`tls_config/cert.h`, set ``ca_certificate[]`` to the contents of the cert. +- By connecting the board to your internet router, it should automatically be assigned + an IPv4 address using DHCP. +- The application will then attempt to connect to the public Mosquitto broker + and begin publishing data. +- It is also possible to connect securely to a locally hosted MQTT broker. + This will require provisioning of certificates. + The CA cert should be included in the build as described above. + ``CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME`` should be configured to match the + local broker hostname/IP address. + Depending on the CA cert being used, additional MbedTLS config options may need to be enabled. + This can be done using Kconfig or using a custom MbedTLS config file + (see modules/mbedtls/Kconfig). + See https://mosquitto.org/man/mosquitto-tls-7.html for more info on setting up + TLS support for Mosquitto locally. +- A DHCP server can be installed on the host PC to handle assigning an IP to the board + e.g. dnsmasq (Linux) or DHCP Server for Windows (Windows). +- Build the sample with default config: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/secure_mqtt_sensor_actuator + :board: adi_eval_adin1110ebz + :goals: build + :compact: + +**Static IP Config:** + +Use the :file:`overlay-static.conf` Kconfig overlay to disable DHCP and use +a static IP address config. +The device, gateway, and DNS server IP addresses should be set according to +your local network configuration. + +.. zephyr-app-commands:: + :zephyr-app: samples/net/secure_mqtt_sensor_actuator + :board: adi_eval_adin1110ebz + :conf: "prj.conf overlay-static.conf" + :goals: build + :compact: + +**Static IP/Unsecure MQTT Config:** + +Use the :file:`overlay-static-insecure.conf` Kconfig overlay to disable TLS and DHCP. +This config requires connecting to a locally hosted Mosquitto MQTT broker. + +- In :file:`overlay-static-insecure.conf`, set the IP address of the board and the Mosquitto + broker (i.e. IP address of Ethernet port on host PC). These addresses should be in the + same subnet e.g. 192.0.2.1 and 192.0.2.2. +- On your host PC, install Mosquitto. +- Create a file called ``unsecure.conf`` with the following content: + +.. code-block:: console + + listener 1883 0.0.0.0 + allow_anonymous true + + +- Start a Mosquitto broker using the configuration file: + +.. code-block:: console + + $ sudo mosquitto -v -c unsecure.conf + +- Build the sample with quick test config: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/secure_mqtt_sensor_actuator + :board: adi_eval_adin1110ebz + :conf: "prj.conf overlay-static-insecure.conf" + :goals: build + :compact: + +Using the Sample +================ +- Once the board establishes an MQTT connection with the Mosquitto broker, the network + LED will turn on and the board will begin publishing sensor readings in JSON format + at a regular interval determined by ``CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL``. + +- Use Mosquitto to subscribe to the sensor data being sent from the board: + +.. code-block:: console + + $ mosquitto_sub -d -h -t zephyr_sample/sensor + +- The application will subscribe to a topic determined by ``CONFIG_NET_SAMPLE_MQTT_SUB_TOPIC_CMD``. + If a supported command string is received by the board on this topic, the board will execute + an associated command handler function. + Supported commands (defined in :file:`device.c`): + + - ``led_on``, turn on board LED + - ``led_off``, turn off board LED + +- Use Mosquitto to publish these commands to the MQTT broker: + +.. code-block:: console + + $ mosquitto_pub -d -h --cafile -t zephyr_sample/command -m "led_on" + +- The Quality of Service (QoS) level that is used for MQTT publishing and + subscriptions can be configured using Kconfig. + +Sample output +============= + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-2212-g2c9c4f3733e9 *** + [00:00:00.181,000] app_device: Device adt7420@48 is ready + [00:00:00.181,000] app_device: Device leds is ready + [00:00:00.181,000] app_main: MAC Address: 00:E0:FE:FE:DA:C8 + [00:00:00.181,000] app_main: Bringing up network.. + [00:00:00.801,000] net_dhcpv4: Received: 192.168.1.17 + [00:00:00.801,000] app_main: Network connectivity up! + [00:00:00.818,000] app_mqtt: Connecting to MQTT broker @ 91.121.93.94 + [00:00:01.154,000] net_mqtt: Connect completed + [00:00:01.197,000] app_mqtt: Connected to MQTT broker! + [00:00:01.197,000] app_mqtt: Hostname: test.mosquitto.org + [00:00:01.198,000] app_mqtt: Client ID: adi_eval_adin1110ebz_9a + [00:00:01.198,000] app_mqtt: Port: 8883 + [00:00:01.198,000] app_mqtt: TLS: Enabled + [00:00:01.198,000] app_mqtt: Subscribing to 1 topic(s) + [00:00:01.238,000] app_mqtt: SUBACK packet ID: 5841 + [00:00:04.200,000] app_mqtt: Published to topic 'zephyr_sample/sensor', QoS 1 + [00:00:04.319,000] app_mqtt: PUBACK packet ID: 1 + [00:00:07.202,000] app_mqtt: Published to topic 'zephyr_sample/sensor', QoS 1 + [00:00:07.323,000] app_mqtt: PUBACK packet ID: 2 + [00:00:10.204,000] app_mqtt: Published to topic 'zephyr_sample/sensor', QoS 1 + [00:00:10.322,000] app_mqtt: PUBACK packet ID: 3 + [00:00:12.769,000] app_mqtt: MQTT payload received! + [00:00:12.769,000] app_mqtt: topic: 'zephyr_sample/command', payload: led_on + [00:00:12.770,000] app_device: Executing device command: led_on + +.. _Eclipse Mosquitto: https://mosquitto.org/download/ diff --git a/samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay b/samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay new file mode 100644 index 00000000000000..8182bb8b230a02 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&adin1110 { + mdio { + /* Enable link status LED */ + ethernet-phy@1 { + led0-en; + led1-en; + }; + }; +}; diff --git a/samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf b/samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf new file mode 100644 index 00000000000000..33655bfe4e10b6 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf @@ -0,0 +1,18 @@ +# Config to disable TLS and DHCPv4, allowing insecure MQTT and a static IP address. +# This allows quick testing of the application without need for a DHCP server or secure MQTT broker set up. +# Only recommended for quick sampling/testing. +# Usage: west build -b -- -DOVERLAY_CONFIG=overlay-static-insecure.conf + +# Disable MQTT with TLS +CONFIG_MQTT_LIB_TLS=n + +# Disable DHCP +CONFIG_NET_DHCPV4=n + +# Insecure MQTT uses port 1883 +CONFIG_NET_SAMPLE_MQTT_BROKER_PORT="1883" + +# Static IP address config +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME="192.0.2.2" diff --git a/samples/net/secure_mqtt_sensor_actuator/overlay-static.conf b/samples/net/secure_mqtt_sensor_actuator/overlay-static.conf new file mode 100644 index 00000000000000..69737f64078f80 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/overlay-static.conf @@ -0,0 +1,8 @@ +CONFIG_NET_DHCPV4=n +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" diff --git a/samples/net/secure_mqtt_sensor_actuator/prj.conf b/samples/net/secure_mqtt_sensor_actuator/prj.conf new file mode 100644 index 00000000000000..b87eaa2c348f5f --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/prj.conf @@ -0,0 +1,59 @@ +# Enable network stack +CONFIG_NETWORKING=y +CONFIG_NET_LOG=y + +# Enable IPv4 +CONFIG_NET_IPV4=y + +# Enable IPv6 +CONFIG_NET_IPV6=y + +# Enable TCP +CONFIG_NET_TCP=y + +# Enable DHCP +CONFIG_NET_DHCPV4=y + +# Enable Sockets (used by MQTT lib) +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y + +# Enable MQTT +CONFIG_MQTT_LIB=y +CONFIG_MQTT_LIB_TLS=y + +# Enable Mbed TLS +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=60000 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y +CONFIG_MBEDTLS_SERVER_NAME_INDICATION=y + +# Enable JSON +CONFIG_JSON_LIBRARY=y + +# Enable net conn manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Enable device hostname +CONFIG_NET_HOSTNAME_ENABLE=y + +# Enable Posix API functionality +CONFIG_POSIX_API=y + +# Enable sensor API +CONFIG_SENSOR=y + +# Enable LED API +CONFIG_LED=y + +# Main stack size +CONFIG_MAIN_STACK_SIZE=2048 + +# System work queue stack size +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# Increase Rx net buffers +CONFIG_NET_BUF_RX_COUNT=100 diff --git a/samples/net/secure_mqtt_sensor_actuator/sample.yaml b/samples/net/secure_mqtt_sensor_actuator/sample.yaml new file mode 100644 index 00000000000000..44b9a4d7d2a3a9 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/sample.yaml @@ -0,0 +1,33 @@ +sample: + name: Secure MQTT Sensor/Actuator Sample +tests: + sample.net.secure_mqtt_sensor_actuator: + harness: net + tags: + - net + - mqtt + - sensors + filter: dt_alias_exists("ambient-temp0") + integration_platforms: + - adi_eval_adin1110ebz + sample.net.secure_mqtt_sensor_actuator.staticip: + harness: net + extra_args: OVERLAY_CONFIG="overlay-static.conf" + tags: + - net + - mqtt + - sensors + filter: dt_alias_exists("ambient-temp0") + integration_platforms: + - native_sim + sample.net.secure_mqtt_sensor_actuator.staticip_insecure: + harness: net + extra_args: OVERLAY_CONFIG="overlay-static-insecure.conf" + tags: + - net + - mqtt + - sensors + filter: dt_alias_exists("ambient-temp0") + integration_platforms: + - adi_eval_adin1110ebz + - native_sim diff --git a/samples/net/secure_mqtt_sensor_actuator/src/device.c b/samples/net/secure_mqtt_sensor_actuator/src/device.c new file mode 100644 index 00000000000000..7ac800e43e20c7 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/device.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(app_device, LOG_LEVEL_DBG); + +#include +#include +#include +#include + +#include "device.h" + +#define SENSOR_CHAN SENSOR_CHAN_AMBIENT_TEMP +#define SENSOR_UNIT "Celsius" + +/* Devices */ +static const struct device *sensor = DEVICE_DT_GET_OR_NULL(DT_ALIAS(ambient_temp0)); +static const struct device *leds = DEVICE_DT_GET_OR_NULL(DT_INST(0, gpio_leds)); + +/* Command handlers */ +static void led_on_handler(void) +{ + device_write_led(LED_USER, LED_ON); +} + +static void led_off_handler(void) +{ + device_write_led(LED_USER, LED_OFF); +} + +/* Supported device commands */ +struct device_cmd device_commands[] = { + {"led_on", led_on_handler}, + {"led_off", led_off_handler} +}; + +const size_t num_device_commands = ARRAY_SIZE(device_commands); + +/* Command dispatcher */ +void device_command_handler(uint8_t *command) +{ + for (int i = 0; i < num_device_commands; i++) { + if (strcmp(command, device_commands[i].command) == 0) { + LOG_INF("Executing device command: %s", device_commands[i].command); + return device_commands[i].handler(); + } + } + LOG_ERR("Unknown command: %s", command); +} + +int device_read_sensor(struct sensor_sample *sample) +{ + int rc; + struct sensor_value sensor_val; + + /* Read sample only if a real sensor device is present + * otherwise return a dummy value + */ + if (sensor == NULL) { + sample->unit = SENSOR_UNIT; + sample->value = 20.0 + (double)sys_rand32_get() / UINT32_MAX * 5.0; + return 0; + } + + rc = sensor_sample_fetch(sensor); + if (rc) { + LOG_ERR("Failed to fetch sensor sample [%d]", rc); + return rc; + } + + rc = sensor_channel_get(sensor, SENSOR_CHAN, &sensor_val); + if (rc) { + LOG_ERR("Failed to get sensor channel [%d]", rc); + return rc; + } + + sample->unit = SENSOR_UNIT; + sample->value = sensor_value_to_double(&sensor_val); + return rc; +} + +int device_write_led(enum led_id led_idx, enum led_state state) +{ + int rc; + + switch (state) { + case LED_OFF: + if (leds == NULL) { + LOG_INF("LED %d OFF", led_idx); + break; + } + led_off(leds, led_idx); + break; + case LED_ON: + if (leds == NULL) { + LOG_INF("LED %d ON", led_idx); + break; + } + led_on(leds, led_idx); + break; + default: + LOG_ERR("Invalid LED state setting"); + rc = -EINVAL; + break; + } + + return rc; +} + +bool devices_ready(void) +{ + bool rc = true; + + /* Check readiness only if a real sensor device is present */ + if (sensor != NULL) { + if (!device_is_ready(sensor)) { + LOG_ERR("Device %s is not ready", sensor->name); + rc = false; + } else { + LOG_INF("Device %s is ready", sensor->name); + } + } + + if (leds != NULL) { + if (!device_is_ready(leds)) { + LOG_ERR("Device %s is not ready", leds->name); + rc = false; + } else { + LOG_INF("Device %s is ready", leds->name); + } + } + + return rc; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/src/device.h b/samples/net/secure_mqtt_sensor_actuator/src/device.h new file mode 100644 index 00000000000000..ad09b9d3efa906 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/device.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +/** @brief Sensor sample structure */ +struct sensor_sample { + const char *unit; + int value; +}; + +/** @brief Available board LEDs */ +enum led_id { + LED_NET, /* Network status LED*/ + LED_USER /* User LED */ +}; + +/** @brief LED states */ +enum led_state { + LED_OFF, + LED_ON +}; + +/** @brief Device command consisting of a command string + * and associated handler function pointer + */ +struct device_cmd { + const char *command; + void (*handler)(); +}; + +/** + * @brief Check if all devices are ready + */ +bool devices_ready(void); + +/** + * @brief Read sample from the sensor + */ +int device_read_sensor(struct sensor_sample *sample); + +/** + * @brief Write to a board LED + */ +int device_write_led(enum led_id led_idx, enum led_state state); + +/** + * @brief Handler function for commands received over MQTT + */ +void device_command_handler(uint8_t *command); + +#endif /* __DEVICE_H__ */ diff --git a/samples/net/secure_mqtt_sensor_actuator/src/main.c b/samples/net/secure_mqtt_sensor_actuator/src/main.c new file mode 100644 index 00000000000000..64993139e90071 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/main.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(app_main, LOG_LEVEL_DBG); + +#include +#include +#include +#include +#include + +#include "mqtt_client.h" +#include "device.h" + +#define NET_L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) + +/* MQTT client struct */ +static struct mqtt_client client_ctx; + +/* MQTT publish work item */ +struct k_work_delayable mqtt_publish_work; + +static struct net_mgmt_event_callback net_l4_mgmt_cb; + +/* Network connection semaphore */ +K_SEM_DEFINE(net_conn_sem, 0, 1); + +static void net_l4_evt_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + switch (mgmt_event) { + case NET_EVENT_L4_CONNECTED: + k_sem_give(&net_conn_sem); + LOG_INF("Network connectivity up!"); + break; + case NET_EVENT_L4_DISCONNECTED: + LOG_INF("Network connectivity down!"); + break; + default: + break; + } +} + +/** Print the device's MAC address to console */ +void log_mac_addr(struct net_if *iface) +{ + struct net_linkaddr *mac; + + mac = net_if_get_link_addr(iface); + + LOG_INF("MAC Address: %02X:%02X:%02X:%02X:%02X:%02X", + mac->addr[0], mac->addr[1], mac->addr[3], + mac->addr[3], mac->addr[4], mac->addr[5]); +} + +/** The system work queue is used to handle periodic MQTT publishing. + * Work queuing begins when the MQTT connection is established. + * Use CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL to set the publish frequency. + */ + +static void publish_work_handler(struct k_work *work) +{ + int rc; + + if (mqtt_connected) { + rc = app_mqtt_publish(&client_ctx); + if (rc != 0) { + LOG_INF("MQTT Publish failed [%d]", rc); + } + k_work_reschedule(&mqtt_publish_work, + K_SECONDS(CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL)); + } else { + k_work_cancel_delayable(&mqtt_publish_work); + } +} + +int main(void) +{ + int rc; + struct net_if *iface; + + devices_ready(); + + iface = net_if_get_default(); + if (iface == NULL) { + LOG_ERR("No network interface configured"); + return -ENETDOWN; + } + + log_mac_addr(iface); + + /* Register callbacks for L4 events */ + net_mgmt_init_event_callback(&net_l4_mgmt_cb, &net_l4_evt_handler, NET_L4_EVENT_MASK); + net_mgmt_add_event_callback(&net_l4_mgmt_cb); + + LOG_INF("Bringing up network.."); + +#if defined(CONFIG_NET_DHCPV4) + net_dhcpv4_start(iface); +#else + /* If using static IP, L4 Connect callback will happen, + * before conn mgr is initialised, so resend events here + * to check for connectivity + */ + conn_mgr_mon_resend_status(); +#endif + + /* Wait for network to come up */ + while (k_sem_take(&net_conn_sem, K_MSEC(MSECS_NET_POLL_TIMEOUT)) != 0) { + LOG_INF("Waiting for network connection.."); + } + + rc = app_mqtt_init(&client_ctx); + if (rc != 0) { + LOG_ERR("MQTT Init failed [%d]", rc); + return rc; + } + + /* Initialise MQTT publish work item */ + k_work_init_delayable(&mqtt_publish_work, publish_work_handler); + + /* Thread main loop */ + while (1) { + /* Block until MQTT connection is up */ + app_mqtt_connect(&client_ctx); + + /* We are now connected, begin queueing periodic MQTT publishes */ + k_work_reschedule(&mqtt_publish_work, + K_SECONDS(CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL)); + + /* Handle MQTT inputs and connection */ + app_mqtt_run(&client_ctx); + } + + return rc; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c new file mode 100644 index 00000000000000..3fdb6f3abf4794 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(app_mqtt, LOG_LEVEL_DBG); + +#include +#include +#include +#include +#include + +#include "mqtt_client.h" +#include "device.h" + +/* Buffers for MQTT client */ +static uint8_t rx_buffer[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; +static uint8_t tx_buffer[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; + +/* MQTT payload buffer */ +static uint8_t payload_buf[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; + +/* MQTT broker details */ +static struct sockaddr_storage broker; + +/* Socket descriptor */ +static struct zsock_pollfd fds[1]; +static int nfds; + +/* JSON payload format */ +static const struct json_obj_descr sensor_sample_descr[] = { + JSON_OBJ_DESCR_PRIM(struct sensor_sample, unit, JSON_TOK_STRING), + JSON_OBJ_DESCR_PRIM(struct sensor_sample, value, JSON_TOK_NUMBER), +}; + +/* MQTT connectivity status flag */ +bool mqtt_connected; + +/* MQTT client ID buffer */ +static uint8_t client_id[50]; + +#if defined(CONFIG_MQTT_LIB_TLS) +#include "tls_config/cert.h" + +/* This should match the CN field in the server's CA cert */ +#define TLS_SNI_HOSTNAME CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME +#define APP_CA_CERT_TAG 1 + +static const sec_tag_t m_sec_tags[] = { + APP_CA_CERT_TAG, +}; + +/** Register CA certificate for TLS */ +static int tls_init(void) +{ + int rc; + + rc = tls_credential_add(APP_CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificate, sizeof(ca_certificate)); + if (rc < 0) { + LOG_ERR("Failed to register public certificate: %d", rc); + return rc; + } + + return rc; +} +#endif + +static void prepare_fds(struct mqtt_client *client) +{ + if (client->transport.type == MQTT_TRANSPORT_NON_SECURE) { + fds[0].fd = client->transport.tcp.sock; + } +#if defined(CONFIG_MQTT_LIB_TLS) + else if (client->transport.type == MQTT_TRANSPORT_SECURE) { + fds[0].fd = client->transport.tls.sock; + } +#endif + + fds[0].events = ZSOCK_POLLIN; + nfds = 1; +} + +static void clear_fds(void) +{ + nfds = 0; +} + +/** Initialise the MQTT client ID as the board name with random hex postfix */ +static void init_mqtt_client_id(void) +{ + snprintk(client_id, sizeof(client_id), CONFIG_BOARD"_%x", (uint8_t)sys_rand32_get()); +} + +static inline void on_mqtt_connect(void) +{ + mqtt_connected = true; + device_write_led(LED_NET, LED_ON); + LOG_INF("Connected to MQTT broker!"); + LOG_INF("Hostname: %s", CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME); + LOG_INF("Client ID: %s", client_id); + LOG_INF("Port: %s", CONFIG_NET_SAMPLE_MQTT_BROKER_PORT); + LOG_INF("TLS: %s", + IS_ENABLED(CONFIG_MQTT_LIB_TLS) ? "Enabled" : "Disabled"); +} + +static inline void on_mqtt_disconnect(void) +{ + mqtt_connected = false; + clear_fds(); + device_write_led(LED_NET, LED_OFF); + LOG_INF("Disconnected from MQTT broker"); +} + +/** Called when an MQTT payload is received. + * Reads the payload and calls the commands + * handler if a payloads is received on the + * command topic + */ +static void on_mqtt_publish(struct mqtt_client *const client, const struct mqtt_evt *evt) +{ + int rc; + uint8_t payload[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; + + rc = mqtt_read_publish_payload(client, payload, + CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE); + if (rc < 0) { + LOG_ERR("Failed to read received MQTT payload [%d]", rc); + return; + } + /* Place null terminator at end of payload buffer */ + payload[rc] = '\0'; + + LOG_INF("MQTT payload received!"); + LOG_INF("topic: '%s', payload: %s", + evt->param.publish.message.topic.topic.utf8, payload); + + /* If the topic is a command, call the command handler */ + if (strcmp(evt->param.publish.message.topic.topic.utf8, + CONFIG_NET_SAMPLE_MQTT_SUB_TOPIC_CMD) == 0) { + device_command_handler(payload); + } +} + +/** Handler for asynchronous MQTT events */ +static void mqtt_event_handler(struct mqtt_client *const client, const struct mqtt_evt *evt) +{ + switch (evt->type) { + case MQTT_EVT_CONNACK: + if (evt->result != 0) { + LOG_ERR("MQTT Event Connect failed [%d]", evt->result); + break; + } + on_mqtt_connect(); + break; + + case MQTT_EVT_DISCONNECT: + on_mqtt_disconnect(); + break; + + case MQTT_EVT_PINGRESP: + LOG_INF("PINGRESP packet"); + break; + + case MQTT_EVT_PUBACK: + if (evt->result != 0) { + LOG_ERR("MQTT PUBACK error [%d]", evt->result); + break; + } + + LOG_INF("PUBACK packet ID: %u", evt->param.puback.message_id); + break; + + case MQTT_EVT_PUBREC: + if (evt->result != 0) { + LOG_ERR("MQTT PUBREC error [%d]", evt->result); + break; + } + + LOG_INF("PUBREC packet ID: %u", evt->param.pubrec.message_id); + + const struct mqtt_pubrel_param rel_param = { + .message_id = evt->param.pubrec.message_id + }; + + mqtt_publish_qos2_release(client, &rel_param); + break; + + case MQTT_EVT_PUBREL: + if (evt->result != 0) { + LOG_ERR("MQTT PUBREL error [%d]", evt->result); + break; + } + + LOG_INF("PUBREL packet ID: %u", evt->param.pubrel.message_id); + + const struct mqtt_pubcomp_param rec_param = { + .message_id = evt->param.pubrel.message_id + }; + + mqtt_publish_qos2_complete(client, &rec_param); + break; + + case MQTT_EVT_PUBCOMP: + if (evt->result != 0) { + LOG_ERR("MQTT PUBCOMP error %d", evt->result); + break; + } + + LOG_INF("PUBCOMP packet ID: %u", evt->param.pubcomp.message_id); + break; + + case MQTT_EVT_SUBACK: + if (evt->result == 0x80) { + LOG_ERR("MQTT SUBACK error [%d]", evt->result); + break; + } + + LOG_INF("SUBACK packet ID: %d", evt->param.suback.message_id); + break; + + case MQTT_EVT_PUBLISH: + const struct mqtt_publish_param *p = &evt->param.publish; + + if (p->message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) { + const struct mqtt_puback_param ack_param = { + .message_id = p->message_id + }; + mqtt_publish_qos1_ack(client, &ack_param); + } else if (p->message.topic.qos == MQTT_QOS_2_EXACTLY_ONCE) { + const struct mqtt_pubrec_param rec_param = { + .message_id = p->message_id + }; + mqtt_publish_qos2_receive(client, &rec_param); + } + + on_mqtt_publish(client, evt); + + default: + break; + } +} + +/** Poll the MQTT socket for received data */ +static int poll_mqtt_socket(struct mqtt_client *client, int timeout) +{ + int rc; + + prepare_fds(client); + + if (nfds <= 0) { + return -EINVAL; + } + + rc = zsock_poll(fds, nfds, timeout); + if (rc < 0) { + LOG_ERR("Socket poll error [%d]", rc); + } + + return rc; +} + +/** Retrieves a sensor sample and encodes it in JSON format */ +static int get_mqtt_payload(struct mqtt_binstr *payload) +{ + int rc; + struct sensor_sample sample; + + rc = device_read_sensor(&sample); + if (rc != 0) { + LOG_ERR("Failed to get sensor sample [%d]", rc); + return rc; + } + + rc = json_obj_encode_buf(sensor_sample_descr, ARRAY_SIZE(sensor_sample_descr), + &sample, payload_buf, CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE); + if (rc != 0) { + LOG_ERR("Failed to encode JSON object [%d]", rc); + return rc; + } + + payload->data = payload_buf; + payload->len = strlen(payload->data); + + return rc; +} + +int app_mqtt_publish(struct mqtt_client *client) +{ + int rc; + struct mqtt_publish_param param; + struct mqtt_binstr payload; + static uint16_t msg_id = 1; + struct mqtt_topic topic = { + .topic = { + .utf8 = CONFIG_NET_SAMPLE_MQTT_PUB_TOPIC, + .size = strlen(topic.topic.utf8) + }, + .qos = IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_0_AT_MOST_ONCE) ? 0 : + (IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE) ? 1 : 2) + }; + + rc = get_mqtt_payload(&payload); + if (rc != 0) { + LOG_ERR("Failed to get MQTT payload [%d]", rc); + } + + param.message.topic = topic; + param.message.payload = payload; + param.message_id = msg_id++; + param.dup_flag = 0; + param.retain_flag = 0; + + rc = mqtt_publish(client, ¶m); + if (rc != 0) { + LOG_ERR("MQTT Publish failed [%d]", rc); + } + + LOG_INF("Published to topic '%s', QoS %d", + param.message.topic.topic.utf8, + param.message.topic.qos); + + return rc; +} + +int app_mqtt_subscribe(struct mqtt_client *client) +{ + int rc; + struct mqtt_topic sub_topics[] = { + { + .topic = { + .utf8 = CONFIG_NET_SAMPLE_MQTT_SUB_TOPIC_CMD, + .size = strlen(sub_topics->topic.utf8) + }, + .qos = IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_0_AT_MOST_ONCE) ? 0 : + (IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE) ? 1 : 2) + } + }; + const struct mqtt_subscription_list sub_list = { + .list = sub_topics, + .list_count = ARRAY_SIZE(sub_topics), + .message_id = 5841u + }; + + LOG_INF("Subscribing to %d topic(s)", sub_list.list_count); + + rc = mqtt_subscribe(client, &sub_list); + if (rc != 0) { + LOG_ERR("MQTT Subscribe failed [%d]", rc); + } + + return rc; +} + +/** Process incoming MQTT data and keep the connection alive*/ +int app_mqtt_process(struct mqtt_client *client) +{ + int rc; + + rc = poll_mqtt_socket(client, mqtt_keepalive_time_left(client)); + if (rc != 0) { + if (fds[0].revents & ZSOCK_POLLIN) { + /* MQTT data received */ + rc = mqtt_input(client); + if (rc != 0) { + LOG_ERR("MQTT Input failed [%d]", rc); + return rc; + } + /* Socket error */ + if (fds[0].revents & (ZSOCK_POLLHUP | ZSOCK_POLLERR)) { + LOG_ERR("MQTT socket closed / error"); + return -ENOTCONN; + } + } + } else { + /* Socket poll timed out, time to call mqtt_live() */ + rc = mqtt_live(client); + if (rc != 0) { + LOG_ERR("MQTT Live failed [%d]", rc); + return rc; + } + } + + return 0; +} + +void app_mqtt_run(struct mqtt_client *client) +{ + int rc; + + /* Subscribe to MQTT topics */ + app_mqtt_subscribe(client); + + /* Thread will primarily remain in this loop */ + while (mqtt_connected) { + rc = app_mqtt_process(client); + if (rc != 0) { + break; + } + } + /* Gracefully close connection */ + mqtt_disconnect(client); +} + +void app_mqtt_connect(struct mqtt_client *client) +{ + int rc = 0; + + mqtt_connected = false; + + /* Block until MQTT CONNACK event callback occurs */ + while (!mqtt_connected) { + rc = mqtt_connect(client); + if (rc != 0) { + LOG_ERR("MQTT Connect failed [%d]", rc); + k_msleep(MSECS_WAIT_RECONNECT); + continue; + } + + /* Poll MQTT socket for response */ + rc = poll_mqtt_socket(client, MSECS_NET_POLL_TIMEOUT); + if (rc > 0) { + mqtt_input(client); + } + + if (!mqtt_connected) { + mqtt_abort(client); + } + } +} + +int app_mqtt_init(struct mqtt_client *client) +{ + int rc; + uint8_t broker_ip[NET_IPV4_ADDR_LEN]; + struct sockaddr_in *broker4; + struct addrinfo *result; + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM + }; + + /* Resolve IP address of MQTT broker */ + rc = getaddrinfo(CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME, + CONFIG_NET_SAMPLE_MQTT_BROKER_PORT, &hints, &result); + if (rc != 0) { + LOG_ERR("Failed to resolve broker hostname [%s]", gai_strerror(rc)); + return -EIO; + } + if (result == NULL) { + LOG_ERR("Broker address not found"); + return -ENOENT; + } + + broker4 = (struct sockaddr_in *)&broker; + broker4->sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr; + broker4->sin_family = AF_INET; + broker4->sin_port = ((struct sockaddr_in *)result->ai_addr)->sin_port; + freeaddrinfo(result); + + /* Log resolved IP address */ + inet_ntop(AF_INET, &broker4->sin_addr.s_addr, broker_ip, sizeof(broker_ip)); + LOG_INF("Connecting to MQTT broker @ %s", broker_ip); + + /* MQTT client configuration */ + init_mqtt_client_id(); + mqtt_client_init(client); + client->broker = &broker; + client->evt_cb = mqtt_event_handler; + client->client_id.utf8 = client_id; + client->client_id.size = strlen(client->client_id.utf8); + client->password = NULL; + client->user_name = NULL; + client->protocol_version = MQTT_VERSION_3_1_1; + + /* MQTT buffers configuration */ + client->rx_buf = rx_buffer; + client->rx_buf_size = sizeof(rx_buffer); + client->tx_buf = tx_buffer; + client->tx_buf_size = sizeof(tx_buffer); + + /* MQTT transport configuration */ +#if defined(CONFIG_MQTT_LIB_TLS) + struct mqtt_sec_config *tls_config; + + client->transport.type = MQTT_TRANSPORT_SECURE; + + rc = tls_init(); + if (rc != 0) { + LOG_ERR("TLS init error"); + return rc; + } + + tls_config = &client->transport.tls.config; + tls_config->peer_verify = TLS_PEER_VERIFY_REQUIRED; + tls_config->cipher_list = NULL; + tls_config->sec_tag_list = m_sec_tags; + tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); +#if defined(CONFIG_MBEDTLS_SERVER_NAME_INDICATION) + tls_config->hostname = TLS_SNI_HOSTNAME; +#else + tls_config->hostname = NULL; +#endif /* CONFIG_MBEDTLS_SERVER_NAME_INDICATION */ +#endif /* CONFIG_MQTT_LIB_TLS */ + + return rc; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h new file mode 100644 index 00000000000000..d78c2b05d342af --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MQTT_CLIENT_H__ +#define __MQTT_CLIENT_H__ + +/** MQTT connection timeouts */ +#define MSECS_NET_POLL_TIMEOUT 5000 +#define MSECS_WAIT_RECONNECT 1000 + +/** MQTT connection status flag */ +extern bool mqtt_connected; + +/** + * @brief Initialise the MQTT client & broker configuration + */ +int app_mqtt_init(struct mqtt_client *client); + +/** + * @brief Blocking function that establishes connectivity to the MQTT broker + */ +void app_mqtt_connect(struct mqtt_client *client); + +/** + * @brief Subscribes to user-defined MQTT topics and continuously + * processes incoming data while the MQTT connection is active + */ +void app_mqtt_run(struct mqtt_client *client); + +/** + * @brief Subscribe to user-defined MQTT topics + */ +int app_mqtt_subscribe(struct mqtt_client *client); + +/** + * @brief Publish MQTT payload + */ +int app_mqtt_publish(struct mqtt_client *client); + +#endif /* __MQTT_CLIENT_H__ */ diff --git a/samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h b/samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h new file mode 100644 index 00000000000000..e044f465b9e052 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __CERT_H__ +#define __CERT_H__ + +/* The CA certficate of the MQTT broker should be included here + * The certificate can either be in DER or PEM format. + * A DER certificate can be converted to a byte array using + * "cat ca.crt | sed -e '1d;$d' | base64 -d |xxd -i" + * If using a PEM certifificate, each line should be wrapped in "\r\n" + */ + +/* CA certificate for Mosquitto public broker + * (available from test.mosquitto.org, valid at time of development) + */ +static const unsigned char ca_certificate[] = "-----BEGIN CERTIFICATE-----\r\n" +"MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL\r\n" +"BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG\r\n" +"A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU\r\n" +"BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv\r\n" +"by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE\r\n" +"BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES\r\n" +"MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp\r\n" +"dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ\r\n" +"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg\r\n" +"UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW\r\n" +"Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA\r\n" +"s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH\r\n" +"3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo\r\n" +"E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT\r\n" +"MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV\r\n" +"6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\r\n" +"BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC\r\n" +"6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf\r\n" +"+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK\r\n" +"sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839\r\n" +"LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE\r\n" +"m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=\r\n" +"-----END CERTIFICATE-----\r\n"; + +#endif /* __CERT_H__ */ From 757b381f77ba863c4e54d3323f3a7a9c2e3454d7 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1251/1389] drivers: memc: smartbond: Add support for the memory driver class. Add support for the memory controller by utilizing QSPIC2. The latter is capable to drive both NOR and PSRAM memory devices. For this to work, the RAM driving mode is enabled. Signed-off-by: Ioannis Karachalios --- drivers/memc/CMakeLists.txt | 1 + drivers/memc/Kconfig | 2 + drivers/memc/Kconfig.smartbond | 11 + drivers/memc/memc_smartbond_nor_psram.c | 255 +++++++++++++++++ .../renesas,smartbond-nor-psram.yaml | 260 ++++++++++++++++++ 5 files changed, 529 insertions(+) create mode 100644 drivers/memc/Kconfig.smartbond create mode 100644 drivers/memc/memc_smartbond_nor_psram.c create mode 100644 dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml diff --git a/drivers/memc/CMakeLists.txt b/drivers/memc/CMakeLists.txt index 2e020548610bd3..1648343c18f008 100644 --- a/drivers/memc/CMakeLists.txt +++ b/drivers/memc/CMakeLists.txt @@ -23,3 +23,4 @@ if((DEFINED CONFIG_FLASH_MCUX_FLEXSPI_XIP) AND (DEFINED CONFIG_FLASH)) endif() zephyr_library_sources_ifdef(CONFIG_MEMC_NXP_S32_QSPI memc_nxp_s32_qspi.c) +zephyr_library_sources_ifdef(CONFIG_MEMC_SMARTBOND memc_smartbond_nor_psram.c) diff --git a/drivers/memc/Kconfig b/drivers/memc/Kconfig index f64165573556cd..afab61994af1af 100644 --- a/drivers/memc/Kconfig +++ b/drivers/memc/Kconfig @@ -31,4 +31,6 @@ source "drivers/memc/Kconfig.sifive" source "drivers/memc/Kconfig.nxp_s32" +source "drivers/memc/Kconfig.smartbond" + endif diff --git a/drivers/memc/Kconfig.smartbond b/drivers/memc/Kconfig.smartbond new file mode 100644 index 00000000000000..32cb8c94f467e3 --- /dev/null +++ b/drivers/memc/Kconfig.smartbond @@ -0,0 +1,11 @@ +# Smartbond Cryptographic Accelerator configuration options + +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config MEMC_SMARTBOND + bool "Smartbond NOR/PSRAM memory controller" + depends on DT_HAS_RENESAS_SMARTBOND_NOR_PSRAM_ENABLED + default y + help + Enable Smartbond NOR/PSRAM memory controller. diff --git a/drivers/memc/memc_smartbond_nor_psram.c b/drivers/memc/memc_smartbond_nor_psram.c new file mode 100644 index 00000000000000..37584f99dcc9bc --- /dev/null +++ b/drivers/memc/memc_smartbond_nor_psram.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_smartbond_nor_psram + +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(smartbond_nor_psram, CONFIG_MEMC_LOG_LEVEL); + +#define CLK_AMBA_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(CRG_TOP_CLK_AMBA_REG_ ## _field ## _Msk)) | \ + (((_val) << CRG_TOP_CLK_AMBA_REG_ ## _field ## _Pos) & \ + CRG_TOP_CLK_AMBA_REG_ ## _field ## _Msk) + +#define QSPIC2_CTRLMODE_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Msk) + +#define QSPIC2_BURSTCMDA_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Msk) + +#define QSPIC2_BURSTCMDB_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Msk) + +#define QSPIC2_AWRITECMD_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Msk) + +static void memc_set_status(bool status, int clk_div) +{ + unsigned int key; + uint32_t clk_amba_reg; + + /* Clock AMBA register might be accessed by multiple driver classes */ + key = irq_lock(); + clk_amba_reg = CRG_TOP->CLK_AMBA_REG; + + if (status) { + CLK_AMBA_REG_SET_FIELD(QSPI2_ENABLE, clk_amba_reg, 1); + CLK_AMBA_REG_SET_FIELD(QSPI2_DIV, clk_amba_reg, clk_div); + } else { + CLK_AMBA_REG_SET_FIELD(QSPI2_ENABLE, clk_amba_reg, 0); + } + + CRG_TOP->CLK_AMBA_REG = clk_amba_reg; + irq_unlock(key); +} + +static void memc_automode_configure(void) +{ + uint32_t reg; + + reg = QSPIC2->QSPIC2_CTRLMODE_REG; + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_SRAM_EN, reg, + DT_INST_PROP(0, is_ram)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_USE_32BA, reg, + DT_INST_ENUM_IDX(0, addr_range)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_CLK_MD, reg, + DT_INST_ENUM_IDX(0, clock_mode)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_AUTO_MD, reg, 1); + QSPIC2->QSPIC2_CTRLMODE_REG = reg; + + reg = QSPIC2->QSPIC2_BURSTCMDA_REG; + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_DMY_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_dummy_mode)); + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_ADR_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_addr_mode)); + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_INST_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_inst_mode)); + #if DT_INST_PROP(0, extra_byte_enable) + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_EXT_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_extra_mode)); + #endif + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_INST, reg, + DT_INST_PROP(0, read_cmd)); + #if DT_INST_PROP(0, extra_byte_enable) + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_EXT_BYTE, reg, + DT_INST_PROP(0, extra_byte)); + #endif + QSPIC2->QSPIC2_BURSTCMDA_REG = reg; + + reg = QSPIC2->QSPIC2_BURSTCMDB_REG; + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_DMY_NUM, reg, + DT_INST_ENUM_IDX(0, dummy_bytes_count)); + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_DAT_RX_MD, reg, + DT_INST_ENUM_IDX(0, rx_data_mode)); + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_INST_MD, reg, 0); + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_EXT_BYTE_EN, reg, + DT_INST_PROP(0, extra_byte_enable)); + QSPIC2->QSPIC2_BURSTCMDB_REG = reg; + + reg = QSPIC2->QSPIC2_AWRITECMD_REG; + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_DAT_TX_MD, reg, + DT_INST_ENUM_IDX(0, tx_data_mode)); + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_ADR_TX_MD, reg, + DT_INST_ENUM_IDX(0, tx_addr_mode)); + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_INST_TX_MD, reg, + DT_INST_ENUM_IDX(0, tx_inst_mode)); + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_INST, reg, + DT_INST_PROP(0, write_cmd)); + QSPIC2->QSPIC2_AWRITECMD_REG = reg; +} + +/* Read PSRAM/NOR device ID using JEDEC commands. */ +static bool memc_jedec_read_and_verify_id(QSPIC_TYPE qspi_id) +{ + uint16_t device_density; + bool ret = 0; + qspi_memory_id_t memory_id; + + da1469x_qspi_memory_jedec_read_id(qspi_id, &memory_id); + + device_density = DT_INST_PROP(0, dev_density); + ret |= !(memory_id.id == DT_INST_PROP(0, dev_id)); + ret |= !(memory_id.type == DT_INST_PROP(0, dev_type)); + ret |= !((memory_id.density & (device_density >> 8)) == (device_density & 0xFF)); + + return ret; +} + +static int memc_smartbond_init(const struct device *dev) +{ + uint32_t qspic_ctrlmode_reg; + + /* First QSPI controller is enabled so registers can be accessed */ + memc_set_status(true, DT_INST_PROP_OR(0, clock_div, 0)); + + /* Apply the min. required settings before performing any transaction in manual mode. */ + qspic_ctrlmode_reg = QSPIC2->QSPIC2_CTRLMODE_REG; + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_CLK_MD, qspic_ctrlmode_reg, + DT_INST_ENUM_IDX(0, clock_mode)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_AUTO_MD, qspic_ctrlmode_reg, 0); + QSPIC2->QSPIC2_CTRLMODE_REG = qspic_ctrlmode_reg; + + /* Reset PSRAM/NOR device using JDEC commands */ + da1469x_qspi_memory_jedec_reset(QSPIC2_ID); + + /* Wait till reset is completed */ + k_usleep(DT_INST_PROP(0, reset_delay_us)); + + if (memc_jedec_read_and_verify_id(QSPIC2_ID)) { + LOG_ERR("Device detection failed"); + memc_set_status(false, 0); + + return -EINVAL; + } + +#if DT_INST_PROP(0, enter_qpi_mode) + da1469x_qspi_enter_exit_qpi_mode(QSPIC2_ID, true, DT_INST_PROP(0, enter_qpi_cmd)); +#endif + + /* Should be called prior to switching to auto mode and when the quad bus is selected! */ + da1469x_qspi_set_bus_mode(QSPIC2_ID, QSPI_BUS_MODE_QUAD); + +#if CONFIG_PM_DEVICE_RUNTIME + /* + * Turn off the controller to minimize power consumption. Application is responsible to + * configure/de-configure the controller before interacting with the memory. + */ + memc_set_status(false, 0); + + /* Make sure device is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#else + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + + /* From this point onwards memory device should be seen as memory mapped device. */ + memc_automode_configure(); +#endif + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int memc_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* + * CLK_AMBA_REG, that controlls QSPIC2, is retained during sleep + * (resides in PD_AON). However, unused blocks should be disabled + * to minimize power consumption at sleep. + */ + memc_set_status(false, 0); + + da1469x_pd_release(MCU_PD_DOMAIN_SYS); + break; + case PM_DEVICE_ACTION_RESUME: + + /* + * Mainly, required when in PM runtime mode. When in PM static mode, + * the device will block till an ongoing/pending AMBA bus transfer + * completes. + */ + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + + /* + * QSPIC2 is powered by PD_SYS which is turned off during sleep and + * so QSPIC2 auto mode re-initialization is required. + * + * XXX: It's assumed that memory device's power rail, that should + * be 1V8P, is not turned off and so the device itsef does not + * require re-initialization. Revisit this part if power settings + * are changed in the future, that should include: + * + * 1. Powering off the memory device by turning off 1V8P + * (valid for FLASH/PSRAM). + * 2. Powering down the memory device so it enters the suspend/low-power + * state during sleep (valid for FLASH/NOR devices). + */ + memc_set_status(true, DT_INST_PROP_OR(0, clock_div, 0)); + memc_automode_configure(); + default: + return -ENOTSUP; + } + + return 0; +} +#endif + +#define SMARTBOND_MEMC_INIT(inst) \ + BUILD_ASSERT(inst == 0, "multiple instances are not permitted"); \ + BUILD_ASSERT(DT_INST_PROP(inst, is_ram), \ + "current driver version suports only PSRAM devices"); \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, memc_smartbond_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, memc_smartbond_init, PM_DEVICE_DT_INST_GET(inst), \ + NULL, NULL, \ + POST_KERNEL, CONFIG_MEMC_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_MEMC_INIT) diff --git a/dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml b/dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml new file mode 100644 index 00000000000000..f55e064683bde7 --- /dev/null +++ b/dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml @@ -0,0 +1,260 @@ +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas Smartbond(tm) NOR/PSRAM controller + +include: base.yaml + +compatible: "renesas,smartbond-nor-psram" + +properties: + reg: + required: true + + is-ram: + type: boolean + description: | + If present, the memory controller will be configured to drive PSRAM devices. + + dev-size: + type: int + required: true + description: | + Memory size/capacity in bits. + + dev-type: + type: int + required: true + description: | + Device type, part of device ID, used to verify the memory device used. + + dev-density: + type: int + required: true + description: | + Device density, part of device ID, used to verify the memory device used. + [7:0] should reflect the density value itself and [15:8] should reflect + the mask that should be applied to the returned device ID value. + This is because part of its byte value might contain invalid bits. + + dev-id: + type: int + required: true + description: | + Manufacturer ID, part of device ID, used to verify the memory device used. + + reset-delay-us: + type: int + required: true + description: | + Time in microseconds (us) the memory device can accept the next command following a SW reset. + + read-cs-idle-min-ns: + type: int + required: true + description: | + Min. time, in nanoseconds, the #CS line should remain inactive between + the transmission of two different instructions. + + erase-cs-idle-min-ns: + type: int + description: | + Min. time, in nanoseconds, the #CS line should remain inactive after the execution + of a write enable, erase, erase suspend or erase resume instruction. This setting + is not used if is-ram property is present. + + enter-qpi-cmd: + type: int + description: | + Command to enter the QPI mode supported by a memory device + (should be transmitted in single bus mode). + + exit-qpi-cmd: + type: int + description: | + Command to exit the QPI mode supported by a memory device + (should be transmitted in quad bus mode). + + enter-qpi-mode: + type: boolean + description: | + If present, the memory device will enter the QPI mode which typically reflects that + all bytes be sent in quad bus mode. It's a pre-requisite that read and write + commands, that should be read-cmd and write-cmd respectively, reflect the QPI mode. + + read-cmd: + type: int + default: 0x03 + description: | + Read command for single/burst read accesses in auto mode. Default value is the opcode + for single mode which is supported by all memory devices. + + write-cmd: + type: int + default: 0x02 + description: | + Write command for single/burst write accesses in auto mode. Default value is the opcode + for single mode which is supported by all memory devices. + + clock-mode: + type: string + enum: + - "spi-mode0" + - "spi-mode3" + default: "spi-mode0" + description: | + Clock mode when #CS is idle/inactive + + - Mode0: #CLK is low when #CS is inactive + - Mode3: #CLK is high when #CS is inactive + + Mode0 is selected by default as it should be supported by all memory devices. + + addr-range: + type: string + enum: + - "addr-range-24bit" + - "addr-range-32bit" + default: "addr-range-24bit" + description: | + Address size to use in auto mode. In 24-bit mode up to 16MB can be + accessed whilst in 32-bit mode up to 32MB can be accessed which is + the max. address space supported by QSPICx. Default value is 24-bit + mode which is supported by all memory devices. + + clock-div: + type: int + description: | + Clock divider for QSPIC2 controller. The clock path of + this block is always DIV1 which reflects the current + system clock. + + tcem-max-us: + type: int + description: | + If a non zero value is applied, then Tcem should be taken into + consideration by QSPIC2 so that it can split a burst read/write + access in case the total time exceeds the defined value + (at the cost of extra cycles required for re-sending the instruction, + address and dummy bytes, if any). This setting is meaningful only if + is-ram is present. This value reflects the max. time in microseconds + the #CS line can be driven low in a write/read burst access + (required for the auto-refresh mechanism, when supported). + + dummy-bytes-count: + type: string + required: true + enum: + - "dummy-bytes-count0" + - "dummy-bytes-count1" + - "dummy-bytes-count2" + - "dummy-bytes-count4" + description: | + Number of dummy bytes to send for single/burst read access in auto mode. + + extra-byte-enable: + type: boolean + description: | + If present, the extra byte will be sent after the dummy bytes, if any. + This should be useful if 3 dummy bytes are required. In such a case, + dummy-bytes-count should be set to 2. + + extra-byte: + type: int + description: | + Extra byte to be sent, if extra-byte-enable is present. + + rx-addr-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the address phase for single/burst + read accesses in auto mode. Default value is single mode which should be + supported by all memory devices. + + rx-inst-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the instruction phase for single/burst + read accesses in auto mode. Default value is single mode which should be + supported by all memory devices. + + rx-data-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the data phase for single/burst + read accesses in auto mode. Default value is single mode which should + be supported by all memory devices. + + rx-dummy-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the dummy bytes phase for single/burst + read accesses in auto mode. The single mode should be supported by all + memory devices. + + rx-extra-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + description: | + Describes the mode of SPI bus during the extra byte phase for single/burst + read accesses in auto mode. Default value is single mode which should be + supported by all memory devices. + + tx-addr-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the address phase for single/burst + write accesses in auto mode. Default value is single mode which should + be supported by all memory devices. + + tx-inst-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the instruction phase for single/burst + write accesses in auto mode. The single mode should be supported by all + memory devices. + + tx-data-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the data phase for single/burst + write accesses in auto mode. Default value is single mode which should + be supported by all memory devices. From be0ede7af85ca2932b85d87e1106645cf6dd8c0b Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1252/1389] drivers: clock_control: smartbond: Add support for the memc driver. 1. Update the clock control driver so it can update timing settings for QSPIC2 following system clock transitions (translated based on AHB AMBA bus clock). 2. Remove the QSPIC related subroutines and use the respective HAL API which is now available. 3. Add support for PM (CONFIG_PM_DEVICE). This is required as QSPIC2 register file is powered by PD_SYS which is turned off during device sleep and so registers contents are lost (in contrast to QSPIC which is used to drive the flash memory). Signed-off-by: Ioannis Karachalios --- .../clock_control/clock_control_smartbond.c | 101 +++++++++++------- 1 file changed, 64 insertions(+), 37 deletions(-) diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index 27290f62c53bfe..6da9c88b9a5a93 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -321,30 +323,6 @@ static void smartbond_clock_control_off_by_ord(const struct device *dev, smartbond_clock_control_off(dev, (clock_control_subsys_rate_t)clk); } -static void -qspi_set_read_pipe_delay(uint8_t delay) -{ - QSPIC->QSPIC_CTRLMODE_REG = - (QSPIC->QSPIC_CTRLMODE_REG & ~QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Msk) | - (delay << QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Pos) | - QSPIC_QSPIC_CTRLMODE_REG_QSPIC_RPIPE_EN_Msk; -} - -static void -qspi_set_cs_delay(uint32_t sys_clock_freq, uint32_t read_delay_ns, uint32_t erase_delay_ns) -{ - sys_clock_freq /= 100000; - uint32_t read_delay_cyc = ((read_delay_ns * sys_clock_freq) + 9999) / 10000; - uint32_t erase_delay_cyc = ((erase_delay_ns * sys_clock_freq) + 9999) / 10000; - - QSPIC->QSPIC_BURSTCMDB_REG = - (QSPIC->QSPIC_BURSTCMDB_REG & ~QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Msk) | - read_delay_cyc << QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Pos; - QSPIC->QSPIC_ERASECMDB_REG = - (QSPIC->QSPIC_ERASECMDB_REG & ~QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Msk) | - (erase_delay_cyc << QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Pos); -} - int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk) { int rc = 0; @@ -385,6 +363,33 @@ int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk) return rc; } +static void smartbond_clock_control_update_memory_settings(uint32_t sys_clock_freq) +{ + if (sys_clock_freq > 32000000) { + da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 7); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + da1469x_qspi_set_read_pipe_delay(QSPIC2_ID, 7); +#endif + } else { + da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 2); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + da1469x_qspi_set_read_pipe_delay(QSPIC2_ID, 2); +#endif + } + + da1469x_qspi_set_cs_delay(QSPIC_ID, SystemCoreClock, + DT_PROP(DT_NODELABEL(flash_controller), read_cs_idle_delay), + DT_PROP(DT_NODELABEL(flash_controller), erase_cs_idle_delay)); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + da1469x_qspi_set_cs_delay(QSPIC2_ID, SystemCoreClock, + DT_PROP(DT_NODELABEL(memc), read_cs_idle_min_ns), + DT_PROP_OR(DT_NODELABEL(memc), erase_cs_idle_min_ns, 0)); +#if DT_PROP(DT_NODELABEL(memc), is_ram) + da1469x_qspi_set_tcem(SystemCoreClock, DT_PROP(DT_NODELABEL(memc), tcem_max_us)); +#endif +#endif +} + int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk) { uint32_t sys_clock_freq; @@ -399,12 +404,7 @@ int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk) /* When PLL is selected as system clock qspi read pipe delay must be set to 7 */ if (sys_clock_freq > 32000000) { - qspi_set_read_pipe_delay(7); - qspi_set_cs_delay(SystemCoreClock, - DT_PROP(DT_NODELABEL(flash_controller), - read_cs_idle_delay), - DT_PROP(DT_NODELABEL(flash_controller), - erase_cs_idle_delay)); + smartbond_clock_control_update_memory_settings(sys_clock_freq); } if (sys_clk == SMARTBOND_CLK_RC32M) { @@ -420,12 +420,7 @@ int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk) /* When switching back from PLL to 32MHz read pipe delay may be set to 2 */ if (SystemCoreClock <= 32000000) { - qspi_set_read_pipe_delay(2); - qspi_set_cs_delay(SystemCoreClock, - DT_PROP(DT_NODELABEL(flash_controller), - read_cs_idle_delay), - DT_PROP(DT_NODELABEL(flash_controller), - erase_cs_idle_delay)); + smartbond_clock_control_update_memory_settings(SystemCoreClock); } return 0; @@ -449,6 +444,11 @@ int smartbond_clocks_init(const struct device *dev) ARG_UNUSED(dev); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + /* Make sure QSPIC2 is enabled */ + da1469x_clock_amba_enable(CRG_TOP_CLK_AMBA_REG_QSPI2_ENABLE_Msk); +#endif + #define ENABLE_OSC(clock) smartbond_clock_control_on_by_ord(dev, DT_DEP_ORD(clock)) #define DISABLE_OSC(clock) if (DT_NODE_HAS_STATUS(clock, disabled)) { \ smartbond_clock_control_off_by_ord(dev, DT_DEP_ORD(clock)); \ @@ -488,9 +488,36 @@ static struct clock_control_driver_api smartbond_clock_control_api = { .get_rate = smartbond_clock_control_get_rate, }; +#if CONFIG_PM_DEVICE +static int smartbond_clocks_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + break; + case PM_DEVICE_ACTION_RESUME: +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + /* Make sure QSPIC2 is enabled */ + da1469x_clock_amba_enable(CRG_TOP_CLK_AMBA_REG_QSPI2_ENABLE_Msk); +#endif + /* + * Make sure the flash controller has correct settings as clock restoration + * might have been performed upon waking up. + */ + smartbond_clock_control_update_memory_settings(SystemCoreClock); + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif + +PM_DEVICE_DT_DEFINE(DT_NODELABEL(osc), smartbond_clocks_pm_action); + DEVICE_DT_DEFINE(DT_NODELABEL(osc), &smartbond_clocks_init, - NULL, + PM_DEVICE_DT_GET(DT_NODELABEL(osc)), NULL, NULL, PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, From ef81f6083e495fc227f9b3da099c1e3e97b3189a Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1253/1389] dts: renesas: smartbond: Add support for the memory driver class. Update DTS and board configurations to support memory controller (QSPIC2). Signed-off-by: Ioannis Karachalios --- boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml | 1 + dts/arm/renesas/smartbond/da1469x.dtsi | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml index eb29fd6c559071..942bfe3e07e5f6 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml @@ -21,4 +21,5 @@ supported: - dma - mipi_dbi - display + - memc vendor: renesas diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index a1539c7887e998..fe589f52fb1cbe 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -151,6 +151,13 @@ compatible = "mmio-sram"; }; + psram: memory@32000000 { + compatible = "zephyr,memory-region"; + device_type = "memory"; + reg = <0x32000000 DT_SIZE_K(32768)>; + zephyr,memory-region = "PSRAM"; + }; + qspif: memory@16000000 { compatible = "zephyr,memory-region"; reg = <0x16000000 DT_SIZE_K(32768)>; @@ -380,6 +387,12 @@ block-count = <1>; #dma-cells = <0>; }; + + memc: qspic2@34000000 { + compatible = "renesas,smartbond-nor-psram"; + reg = <0x34000000 0x48>; + status = "disabled"; + }; }; }; From 4c4ae1db665f62aa65185f95c3c3e82a9cd67c74 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:34 +0200 Subject: [PATCH 1254/1389] boards: renesas: dts: Add overlay files to support the MEMC In order to avoid defining almost the same overlays in the available sample codes, tests and user applications, a common overlay file per memory type is demonstrated under the boards dts folder. Currently only the PSRAM interface is supported and the APS6404L PSRAM QSPI memory device is demonstrated. In doing so, an application code will only have to define another overlay file explicitly, under application's board folder, to overwrite the default QSPI controller's settings. In either case, users should explicitly invoke the requested overlay files at 'west build' invokation via the DTC_OVERLAY_FILE system variable. Signed-off-by: Ioannis Karachalios --- .../dts/da1469x_dk_pro_psram.overlay | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay diff --git a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay new file mode 100644 index 00000000000000..5707f111d97ffc --- /dev/null +++ b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + aliases { + sram-ext = &memc; + }; +}; + +/* QSPIC settings for the APS6404L-3SQR QSPI PSRAM memory in QPI mode. */ +&memc { + status = "okay"; + is-ram; + dev-size = ; + dev-type = <0x5D>; + dev-id = <0x0D>; + dev-density = <0xE040>; + reset-delay-us = <50>; + read-cs-idle-min-ns = <18>; + tcem-max-us = <2>; + enter-qpi-mode; + enter-qpi-cmd = <0x35>; + extra-byte-enable; + extra-byte = <0x0>; + dummy-bytes-count = "dummy-bytes-count2"; + read-cmd = <0xEB>; + write-cmd = <0x38>; + rx-inst-mode = "quad-spi"; + rx-addr-mode = "quad-spi"; + rx-data-mode = "quad-spi"; + rx-dummy-mode = "quad-spi"; + rx-extra-mode = "quad-spi"; + tx-inst-mode = "quad-spi"; + tx-addr-mode = "quad-spi"; + tx-data-mode = "quad-spi"; +}; From e34909384001db610d4fdf94e3113f367977e6fe Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1255/1389] samples: drivers: memc: Add support for Smartbond Pro DevKit. Add configuration and overlay files to support the DA1469x development kit. Signed-off-by: Ioannis Karachalios --- samples/drivers/memc/src/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/samples/drivers/memc/src/main.c b/samples/drivers/memc/src/main.c index 1347cce2b12b24..901eb064fb1289 100644 --- a/samples/drivers/memc/src/main.c +++ b/samples/drivers/memc/src/main.c @@ -12,8 +12,14 @@ #include "memc_mcux_flexspi.h" #define FLEXSPI_DEV DEVICE_DT_GET(DT_PARENT(DT_ALIAS(sram_ext))) #define MEMC_PORT DT_REG_ADDR(DT_ALIAS(sram_ext)) -#define MEMC_BASE memc_flexspi_get_ahb_address(FLEXSPI_DEV, MEMC_PORT, 0) +#define MEMC_BASE ((void *)memc_flexspi_get_ahb_address(FLEXSPI_DEV, MEMC_PORT, 0)) #define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), size) / 8) +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_nor_psram) +#include +#define MEMC_BASE ((void *)MCU_QSPIR_M_BASE) +#define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), dev_size) / 8) +#else +#error At least one driver should be selected! #endif void dump_memory(uint8_t *p, uint32_t size) From 8e9b4468cc6a44fa72e3174fa1c0fb10857e448f Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1256/1389] tests: drivers: memc/ram: Add support for Smartbond Pro DevKit. Add configuration and overlay files to support the DA1469x development kit. Signed-off-by: Ioannis Karachalios --- tests/drivers/memc/ram/src/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/drivers/memc/ram/src/main.c b/tests/drivers/memc/ram/src/main.c index 49ce816d4877e4..c8de856aa46f26 100644 --- a/tests/drivers/memc/ram/src/main.c +++ b/tests/drivers/memc/ram/src/main.c @@ -44,6 +44,9 @@ BUF_DEF(sram1); #if DT_NODE_HAS_STATUS(DT_NODELABEL(sram2), okay) BUF_DEF(sram2); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) +BUF_DEF(psram); +#endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(ram0), okay) #define RAM_SIZE DT_REG_SIZE(DT_NODELABEL(ram0)) @@ -96,3 +99,12 @@ ZTEST(test_ram, test_sram2) ztest_test_skip(); #endif } + +ZTEST(test_ram, test_psram) +{ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + test_ram_rw(buf_psram, BUF_SIZE); +#else + ztest_test_skip(); +#endif +} From fbf7178014394c38408cbdc88ffd019a4aa3ba00 Mon Sep 17 00:00:00 2001 From: Rick Bruyninckx Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1257/1389] data: Use designated initializers consistently in macro's This PR updates the json macros to be consistend with C++20 Signed-off-by: Rick Bruyninckx --- include/zephyr/data/json.h | 92 ++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/include/zephyr/data/json.h b/include/zephyr/data/json.h index b8b386d968ac01..7534b3674f69dd 100644 --- a/include/zephyr/data/json.h +++ b/include/zephyr/data/json.h @@ -191,11 +191,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = (sizeof(#field_name_) - 1), \ .type = JSON_TOK_OBJECT_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .object = { \ - .sub_descr = sub_descr_, \ - .sub_descr_len = ARRAY_SIZE(sub_descr_), \ - }, \ + .object = { \ + .sub_descr = sub_descr_, \ + .sub_descr_len = ARRAY_SIZE(sub_descr_), \ }, \ } @@ -277,12 +275,10 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ - elem_type_,), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ + elem_type_,), \ + .n_elements = (max_len_), \ }, \ } @@ -328,13 +324,11 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ - JSON_TOK_OBJECT_START, \ - Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ + JSON_TOK_OBJECT_START, \ + Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ + .n_elements = (max_len_), \ }, \ } @@ -389,15 +383,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR( \ - struct_, len_field_, JSON_TOK_ARRAY_START, \ - Z_JSON_DESCR_ARRAY( \ - elem_descr_, \ - 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR( \ + struct_, len_field_, JSON_TOK_ARRAY_START, \ + Z_JSON_DESCR_ARRAY( \ + elem_descr_, \ + 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ + .n_elements = (max_len_), \ }, \ } @@ -426,15 +418,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#json_field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR( \ - struct_, len_field_, JSON_TOK_ARRAY_START, \ - Z_JSON_DESCR_ARRAY( \ - elem_descr_, \ - 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR( \ + struct_, len_field_, JSON_TOK_ARRAY_START, \ + Z_JSON_DESCR_ARRAY( \ + elem_descr_, \ + 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ + .n_elements = (max_len_), \ }, \ } @@ -483,11 +473,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = (sizeof(json_field_name_) - 1), \ .type = JSON_TOK_OBJECT_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .object = { \ - .sub_descr = sub_descr_, \ - .sub_descr_len = ARRAY_SIZE(sub_descr_), \ - }, \ + .object = { \ + .sub_descr = sub_descr_, \ + .sub_descr_len = ARRAY_SIZE(sub_descr_), \ }, \ } @@ -516,12 +504,10 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(json_field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .array = { \ - .element_descr = \ - Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_,), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = \ + Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_,), \ + .n_elements = (max_len_), \ }, \ } @@ -575,13 +561,11 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(json_field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ - JSON_TOK_OBJECT_START, \ - Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ + JSON_TOK_OBJECT_START, \ + Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ + .n_elements = (max_len_), \ }, \ } From 827e8d4ea67165d851a8800922cafe47097865e2 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1258/1389] include: video: Add XYUV32 pixel format Add XYUV32 pixel format Signed-off-by: Phi Bang Nguyen --- include/zephyr/drivers/video.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index 85f08920119fa7..84b5558390e85e 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -638,6 +638,9 @@ void video_buffer_release(struct video_buffer *buf); /** YUYV pixel format */ #define VIDEO_PIX_FMT_YUYV video_fourcc('Y', 'U', 'Y', 'V') /* 16 Y0-Cb0 Y1-Cr0 */ +/** XYUV32 pixel format */ +#define VIDEO_PIX_FMT_XYUV32 video_fourcc('X', 'Y', 'U', 'V') /* 32 XYUV-8-8-8-8 */ + /** * * @} From ae0f222216241fe3a2c669d038f1aa105968ce92 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1259/1389] drivers: video: csi: Add support for i.MX RT11XX On i.MX RT11XX which has MIPI CSI-2 Rx, image data from the camera sensor after passing through the camera pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be implicitly converted to a 32-bits pixel formats. For example, an input in RGB565 / YUYV (2-bytes format) will become an XRGB32 / XYUV32 (4-bytes format), respectively. Make changes to support this. Signed-off-by: Phi Bang Nguyen --- drivers/video/video_mcux_csi.c | 77 +++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index 77022d037d898c..2e8e4d505084ae 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -44,6 +44,9 @@ static inline unsigned int video_pix_fmt_bpp(uint32_t pixelformat) case VIDEO_PIX_FMT_RGB565: case VIDEO_PIX_FMT_YUYV: return 2; + case VIDEO_PIX_FMT_XRGB32: + case VIDEO_PIX_FMT_XYUV32: + return 4; default: return 0; } @@ -113,6 +116,36 @@ static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, status_t statu return; } +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) +K_HEAP_DEFINE(csi_heap, 1000); +static struct video_format_cap *fmts; +/* + * On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor after passing + * through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be implicitly converted to a + * 32-bits pixel format. For example, an input in RGB565 or YUYV (2-bytes format) will become a + * XRGB32 or XYUV32 (4-bytes format) respectively, at the output of the CSI. + */ +static inline void video_pix_fmt_convert(struct video_format *fmt, bool isGetFmt) +{ + switch (fmt->pixelformat) { + case VIDEO_PIX_FMT_XRGB32: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565; + break; + case VIDEO_PIX_FMT_XYUV32: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV; + break; + case VIDEO_PIX_FMT_RGB565: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565; + break; + case VIDEO_PIX_FMT_YUYV: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV; + break; + } + + fmt->pitch = fmt->width * video_pix_fmt_bpp(fmt->pixelformat); +} +#endif + static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_id ep, struct video_format *fmt) { @@ -120,6 +153,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_ struct video_mcux_csi_data *data = dev->data; unsigned int bpp = video_pix_fmt_bpp(fmt->pixelformat); status_t ret; + struct video_format format = *fmt; if (!bpp || ep != VIDEO_EP_OUT) { return -EINVAL; @@ -127,9 +161,17 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_ data->csi_config.bytesPerPixel = bpp; data->csi_config.linePitch_Bytes = fmt->pitch; +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) + if (fmt->pixelformat != VIDEO_PIX_FMT_XRGB32 && fmt->pixelformat != VIDEO_PIX_FMT_XYUV32) { + return -ENOTSUP; + } + video_pix_fmt_convert(&format, false); + data->csi_config.dataBus = kCSI_DataBus24Bit; +#else + data->csi_config.dataBus = kCSI_DataBus8Bit; +#endif data->csi_config.polarityFlags = kCSI_HsyncActiveHigh | kCSI_DataLatchOnRisingEdge; data->csi_config.workMode = kCSI_GatedClockMode; /* use VSYNC, HSYNC, and PIXCLK */ - data->csi_config.dataBus = kCSI_DataBus8Bit; data->csi_config.useExtVsync = true; data->csi_config.height = fmt->height; data->csi_config.width = fmt->width; @@ -144,7 +186,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_ return -EIO; } - if (config->source_dev && video_set_format(config->source_dev, ep, fmt)) { + if (config->source_dev && video_set_format(config->source_dev, ep, &format)) { return -EIO; } @@ -161,6 +203,9 @@ static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_ } if (config->source_dev && !video_get_format(config->source_dev, ep, fmt)) { +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) + video_pix_fmt_convert(fmt, true); +#endif /* align CSI with source fmt */ return video_mcux_csi_set_fmt(dev, ep, fmt); } @@ -317,6 +362,34 @@ static int video_mcux_csi_get_caps(const struct device *dev, enum video_endpoint /* Just forward to source dev for now */ if (config->source_dev) { err = video_get_caps(config->source_dev, ep, caps); +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) + /* + * On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor + * after passing through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be + * implicitly converted to a 32-bits pixel format. For example, an input in RGB565 + * or YUYV (2-bytes format) will become an XRGB32 or XYUV32 (4-bytes format) + * respectively, at the output of the CSI. So, we change the pixel formats of the + * source caps to reflect this. + */ + int ind = 0; + + while (caps->format_caps[ind].pixelformat) { + ind++; + } + k_heap_free(&csi_heap, fmts); + fmts = k_heap_alloc(&csi_heap, (ind + 1) * sizeof(struct video_format_cap), + K_FOREVER); + + for (int i = 0; i <= ind; i++) { + memcpy(&fmts[i], &caps->format_caps[i], sizeof(fmts[i])); + if (fmts[i].pixelformat == VIDEO_PIX_FMT_RGB565) { + fmts[i].pixelformat = VIDEO_PIX_FMT_XRGB32; + } else if (fmts[i].pixelformat == VIDEO_PIX_FMT_YUYV) { + fmts[i].pixelformat = VIDEO_PIX_FMT_XYUV32; + } + } + caps->format_caps = fmts; +#endif } /* NXP MCUX CSI request at least 2 buffer before starting */ From 959846477713859d0826fbef58903e744685a06f Mon Sep 17 00:00:00 2001 From: Roger Wang Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1260/1389] logging: backend: uart: fix coverity warning This commit is to fix a warning which is reported in Coverity scan after device runtime pm is enabled. Signed-off-by: Roger Wang --- subsys/logging/backends/log_backend_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/logging/backends/log_backend_uart.c b/subsys/logging/backends/log_backend_uart.c index 0cb3e29df1a0a5..ffc72bcb863cfe 100644 --- a/subsys/logging/backends/log_backend_uart.c +++ b/subsys/logging/backends/log_backend_uart.c @@ -189,7 +189,7 @@ static void panic(struct log_backend const *const backend) /* Ensure that the UART device is in active mode */ #if defined(CONFIG_PM_DEVICE_RUNTIME) - pm_device_runtime_get(uart_dev); + (void)pm_device_runtime_get(uart_dev); #elif defined(CONFIG_PM_DEVICE) enum pm_device_state pm_state; int rc; From 2300e278d9d9cb4ac571e1d79e52cc4e33530d2e Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1261/1389] modules: tf-m: nordic: remove problematic include path It made the build of `samples/tfm_integration/tfm_psa_test/sample.tfm.psa_test_crypto` break since the update of Mbed TLS to 3.6.0 (#71118), apparently because `${ZEPHYR_BASE}` wasn't set, and the include doesn't seem to be needed. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/nordic/CMakeLists.txt | 1 - modules/trusted-firmware-m/nordic/ns/CMakeLists.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/modules/trusted-firmware-m/nordic/CMakeLists.txt b/modules/trusted-firmware-m/nordic/CMakeLists.txt index d75b34a8109889..c351f97f906a52 100644 --- a/modules/trusted-firmware-m/nordic/CMakeLists.txt +++ b/modules/trusted-firmware-m/nordic/CMakeLists.txt @@ -14,7 +14,6 @@ set(partition_includes set(board_includes ${CMAKE_BINARY_DIR}/../zephyr/misc/generated/syscalls_links/include - ${ZEPHYR_BASE}/include ) target_include_directories(platform_region_defs diff --git a/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt b/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt index 5bb8cb5bd94ae1..67ee755c25ecae 100644 --- a/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt +++ b/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt @@ -17,7 +17,6 @@ set(partition_includes set(board_includes ${CMAKE_BINARY_DIR}/../zephyr/misc/generated/syscalls_links/include - ${ZEPHYR_BASE}/include ) target_include_directories(platform_region_defs From 7b06270d903ec42da6ad0351b64e2ffdfa2c8308 Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1262/1389] boards: st: steval_stwinbx1: Add BLE support for STEVAL-STWINBX1 board Provide BLE support for STEVAL-STWINBX1 board. Signed-off-by: Ali Hozhabri --- boards/st/steval_stwinbx1/Kconfig.defconfig | 18 ++++++++++++++++++ boards/st/steval_stwinbx1/steval_stwinbx1.dts | 17 +++++++++++++++++ boards/st/steval_stwinbx1/steval_stwinbx1.yaml | 1 + 3 files changed, 36 insertions(+) diff --git a/boards/st/steval_stwinbx1/Kconfig.defconfig b/boards/st/steval_stwinbx1/Kconfig.defconfig index be9fa9523a5398..f10fea5e293b88 100644 --- a/boards/st/steval_stwinbx1/Kconfig.defconfig +++ b/boards/st/steval_stwinbx1/Kconfig.defconfig @@ -5,6 +5,24 @@ if BOARD_STEVAL_STWINBX1 +if BT + +config SPI + default y + +choice BT_HCI_BUS_TYPE + default BT_SPI +endchoice + +config BT_BLUENRG_ACI + default y + +# Disable Flow control +config BT_HCI_ACL_FLOW_CONTROL + default n + +endif # BT + config SPI_STM32_INTERRUPT default y depends on SPI diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.dts b/boards/st/steval_stwinbx1/steval_stwinbx1.dts index d84b9fae9cda42..23eda67338aeca 100644 --- a/boards/st/steval_stwinbx1/steval_stwinbx1.dts +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.dts @@ -159,6 +159,23 @@ stm32_lp_tick_source: &lptim1 { status = "okay"; }; +&spi3 { + pinctrl-0 = <&spi3_sck_pg9 &spi3_miso_pb4 &spi3_mosi_pb5>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&gpioe 1 GPIO_ACTIVE_LOW>; + bluenrg-2@0 { + compatible = "st,hci-spi-v2"; + reg = <0>; + reset-gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; + irq-gpios = <&gpiof 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; + spi-cpha; /* CPHA=1 */ + spi-hold-cs; + spi-max-frequency = ; + reset-assert-duration-ms = <6>; + }; +}; + &i2c2 { pinctrl-0 = <&i2c2_scl_ph4 &i2c2_sda_pf0>; pinctrl-names = "default"; diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.yaml b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml index a12712dda8a1e1..f08afe0d21d132 100644 --- a/boards/st/steval_stwinbx1/steval_stwinbx1.yaml +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml @@ -12,4 +12,5 @@ supported: - gpio - pwm - watchdog + - ble vendor: st From 45378523c6d178073ad1090ef4a30afff3cc44b5 Mon Sep 17 00:00:00 2001 From: Simon Hein Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1263/1389] MAINTAINERS: add doc/safety to documentation area Add the missing doc/safety path to the area documentation. Signed-off-by: Simon Hein --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 09ed1022e28825..fe4526c16f331c 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -852,6 +852,7 @@ Documentation: - doc/project/ - doc/releases/ - doc/security/ + - doc/safety/ - README.rst - doc/substitutions.txt - doc/images/Zephyr-Kite-in-tree.png From 6b01d26950d4c182196a73ace4e5fa615bf935a5 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1264/1389] soc: intel_adsp: ipc: don't call k_sem_init() multiple times k_sem_init() is called for every IPC message sent in intel_adsp_ipc_send_message(). This has not had any side-effects in upstream configurations, but has been linked to a failing run of test_obj_tracking_sanity test case in downstream Zephyr use. Replace k_sem_init() with k_sem_reset() as this is more appropriate API to reset the semaphore count, and ensure deterministic behaviour in case a thread is waiting on the semaphore at time of reset. Suggested-by: Peter Mitsis Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/common/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/intel/intel_adsp/common/ipc.c b/soc/intel/intel_adsp/common/ipc.c index 04503ca35e8f2d..d1a315e5f1c389 100644 --- a/soc/intel/intel_adsp/common/ipc.c +++ b/soc/intel/intel_adsp/common/ipc.c @@ -160,7 +160,7 @@ int intel_adsp_ipc_send_message(const struct device *dev, return -EBUSY; } - k_sem_init(&devdata->sem, 0, 1); + k_sem_reset(&devdata->sem); /* Prevent entering runtime idle state until IPC acknowledgment is received. */ pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); devdata->tx_ack_pending = true; From 2e1d9f8b730f17de2b2897541d4c29838ca9f556 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1265/1389] Bluetooth: host: tests: Switch to one-time adv This patch removes all uses of the adv auto-resume feature in the host bsim tests, except for the test of that feature itself, and instead makes all adv starts explicit. The auto-resume feature is planned for deprecation. And, explicit starting of adv makes what happens in the test more explicit as well. Signed-off-by: Aleksander Wasaznik --- .../bsim/bluetooth/host/att/eatt/src/common.c | 2 +- .../host/att/eatt_notif/src/server_test.c | 2 +- .../gatt/authorization/src/gatt_server_test.c | 2 +- .../host/gatt/caching/src/gatt_server_test.c | 2 +- .../host/gatt/general/src/gatt_server_test.c | 2 +- .../host/gatt/notify/src/gatt_server_test.c | 2 +- .../notify_multiple/src/gatt_server_test.c | 2 +- .../bluetooth/host/iso/cis/CMakeLists.txt | 5 +++ .../host/iso/cis/src/cis_peripheral.c | 25 ++++++------ .../host/l2cap/general/src/main_l2cap_ecred.c | 2 +- .../src/main_l2cap_send_on_connect.c | 2 +- .../l2cap/userdata/src/main_l2cap_userdata.c | 2 +- .../misc/conn_stress/peripheral/src/main.c | 2 +- .../host/misc/disable/CMakeLists.txt | 5 +++ .../bsim/bluetooth/host/misc/disable/prj.conf | 1 + .../host/misc/disable/src/gatt_client_test.c | 4 +- .../host/misc/disable/src/gatt_server_test.c | 12 +----- .../misc/unregister_conn_cb/CMakeLists.txt | 3 ++ .../host/misc/unregister_conn_cb/prj.conf | 1 + .../host/misc/unregister_conn_cb/src/main.c | 38 +++++++++++++------ 20 files changed, 70 insertions(+), 46 deletions(-) diff --git a/tests/bsim/bluetooth/host/att/eatt/src/common.c b/tests/bsim/bluetooth/host/att/eatt/src/common.c index 209292320dea8a..487f5c644b850e 100644 --- a/tests/bsim/bluetooth/host/att/eatt/src/common.c +++ b/tests/bsim/bluetooth/host/att/eatt/src/common.c @@ -140,7 +140,7 @@ void peripheral_setup_and_connect(void) FAIL("Can't enable Bluetooth (err %d)\n", err); } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); } diff --git a/tests/bsim/bluetooth/host/att/eatt_notif/src/server_test.c b/tests/bsim/bluetooth/host/att/eatt_notif/src/server_test.c index 56cb28e1093223..f2aa8a3b4a8040 100644 --- a/tests/bsim/bluetooth/host/att/eatt_notif/src/server_test.c +++ b/tests/bsim/bluetooth/host/att/eatt_notif/src/server_test.c @@ -190,7 +190,7 @@ static void test_main(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_server_test.c index 79962c3168911f..03942821640709 100644 --- a/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_server_test.c @@ -339,7 +339,7 @@ static void test_main(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/gatt/caching/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/caching/src/gatt_server_test.c index 6149378ecb616e..9f1ff58904e6d4 100644 --- a/tests/bsim/bluetooth/host/gatt/caching/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/gatt/caching/src/gatt_server_test.c @@ -101,7 +101,7 @@ static void test_main_common(bool connect_eatt) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); diff --git a/tests/bsim/bluetooth/host/gatt/general/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/general/src/gatt_server_test.c index c266b4739a4c50..e41d568dff818d 100644 --- a/tests/bsim/bluetooth/host/gatt/general/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/gatt/general/src/gatt_server_test.c @@ -159,7 +159,7 @@ static void test_main(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/gatt/notify/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/notify/src/gatt_server_test.c index 551a41ebaadd3f..40d776ba4cb2d8 100644 --- a/tests/bsim/bluetooth/host/gatt/notify/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/gatt/notify/src/gatt_server_test.c @@ -183,7 +183,7 @@ static void setup(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/gatt/notify_multiple/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/notify_multiple/src/gatt_server_test.c index 3083eb767d64c2..05ccb6f39457e3 100644 --- a/tests/bsim/bluetooth/host/gatt/notify_multiple/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/gatt/notify_multiple/src/gatt_server_test.c @@ -145,7 +145,7 @@ static void test_main(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt b/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt index b856e60fcf348b..2e8e50c8f7fd65 100644 --- a/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt +++ b/tests/bsim/bluetooth/host/iso/cis/CMakeLists.txt @@ -16,3 +16,8 @@ zephyr_include_directories( ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ ) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) +target_link_libraries(app PRIVATE + testlib +) diff --git a/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c b/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c index a07ffbb6efb95c..3dc53ba0d29eb1 100644 --- a/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c +++ b/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c @@ -4,15 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include "common.h" #include #include #include +#include + extern enum bst_result_t bst_result; -CREATE_FLAG(flag_iso_connected); CREATE_FLAG(flag_data_received); static const struct bt_data ad[] = { @@ -70,15 +73,11 @@ static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *in static void iso_connected(struct bt_iso_chan *chan) { printk("ISO Channel %p connected\n", chan); - - SET_FLAG(flag_iso_connected); } static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) { printk("ISO Channel %p disconnected (reason 0x%02x)\n", chan, reason); - - UNSET_FLAG(flag_iso_connected); } static int iso_accept(const struct bt_iso_accept_info *info, struct bt_iso_chan **chan) @@ -144,7 +143,7 @@ static void adv_connect(void) { int err; - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); @@ -159,13 +158,15 @@ static void adv_connect(void) static void test_main(void) { init(); - adv_connect(); - WAIT_FOR_FLAG_SET(flag_iso_connected); - WAIT_FOR_FLAG_SET(flag_data_received); - WAIT_FOR_FLAG_UNSET(flag_iso_connected); - WAIT_FOR_FLAG_UNSET(flag_connected); - PASS("Test passed\n"); + while (true) { + adv_connect(); + bt_testlib_conn_wait_free(); + + if (TEST_FLAG(flag_data_received)) { + PASS("Test passed\n"); + } + } } static const struct bst_test_instance test_def[] = { diff --git a/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c b/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c index dbee4d4f3c3e37..7cdb32b9cd2238 100644 --- a/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c +++ b/tests/bsim/bluetooth/host/l2cap/general/src/main_l2cap_ecred.c @@ -449,7 +449,7 @@ static void test_peripheral_main(void) LOG_DBG("Peripheral Bluetooth initialized."); LOG_DBG("Connectable advertising..."); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)", err); return; diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c index 60ed49eb229ca3..e421812d60e176 100644 --- a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c @@ -187,7 +187,7 @@ static void test_peripheral_main(void) register_l2cap_server(); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c b/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c index df5f4c1bffdd78..13637090788f5f 100644 --- a/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c +++ b/tests/bsim/bluetooth/host/l2cap/userdata/src/main_l2cap_userdata.c @@ -151,7 +151,7 @@ static void test_peripheral_main(void) return; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/misc/conn_stress/peripheral/src/main.c b/tests/bsim/bluetooth/host/misc/conn_stress/peripheral/src/main.c index 03d706b6214c90..ab5a13bcf294e4 100644 --- a/tests/bsim/bluetooth/host/misc/conn_stress/peripheral/src/main.c +++ b/tests/bsim/bluetooth/host/misc/conn_stress/peripheral/src/main.c @@ -400,7 +400,7 @@ void test_peripheral_main(void) sprintf(name, "per-%d", get_device_nbr()); bt_set_name(name); - err = bt_le_adv_start(BT_LE_ADV_CONN, NULL, 0, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, NULL, 0, NULL, 0); if (err) { LOG_ERR("Advertising failed to start (err %d)", err); __ASSERT_NO_MSG(err); diff --git a/tests/bsim/bluetooth/host/misc/disable/CMakeLists.txt b/tests/bsim/bluetooth/host/misc/disable/CMakeLists.txt index 78c6674ff11d4b..af4a62820e7163 100644 --- a/tests/bsim/bluetooth/host/misc/disable/CMakeLists.txt +++ b/tests/bsim/bluetooth/host/misc/disable/CMakeLists.txt @@ -12,3 +12,8 @@ zephyr_include_directories( ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ ) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) +target_link_libraries(app PRIVATE + testlib +) diff --git a/tests/bsim/bluetooth/host/misc/disable/prj.conf b/tests/bsim/bluetooth/host/misc/disable/prj.conf index 7bf1c2b09e8604..1b4b23f71b728c 100644 --- a/tests/bsim/bluetooth/host/misc/disable/prj.conf +++ b/tests/bsim/bluetooth/host/misc/disable/prj.conf @@ -1,3 +1,4 @@ +CONFIG_ASSERT=y CONFIG_BT=y CONFIG_BT_DEVICE_NAME="GATT tester" CONFIG_BT_PERIPHERAL=y diff --git a/tests/bsim/bluetooth/host/misc/disable/src/gatt_client_test.c b/tests/bsim/bluetooth/host/misc/disable/src/gatt_client_test.c index 7fd32dccfca98d..824b5eab8fa34b 100644 --- a/tests/bsim/bluetooth/host/misc/disable/src/gatt_client_test.c +++ b/tests/bsim/bluetooth/host/misc/disable/src/gatt_client_test.c @@ -60,7 +60,7 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) UNSET_FLAG(flag_is_connected); } -BT_CONN_CB_DEFINE(conn_callbacks) = { +static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, }; @@ -263,6 +263,8 @@ static void test_main(void) { int err; + bt_conn_cb_register(&conn_callbacks); + for (int i = 0; i < NUM_ITERATIONS; i++) { err = bt_enable(NULL); diff --git a/tests/bsim/bluetooth/host/misc/disable/src/gatt_server_test.c b/tests/bsim/bluetooth/host/misc/disable/src/gatt_server_test.c index 1dc6ec5f96ef25..12ab2f875814b1 100644 --- a/tests/bsim/bluetooth/host/misc/disable/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/misc/disable/src/gatt_server_test.c @@ -10,8 +10,6 @@ extern enum bst_result_t bst_result; CREATE_FLAG(flag_is_connected); -static struct bt_conn *g_conn; - #define NUM_ITERATIONS 10 static void connected(struct bt_conn *conn, uint8_t err) @@ -27,7 +25,6 @@ static void connected(struct bt_conn *conn, uint8_t err) printk("Connected to %s\n", addr); - g_conn = bt_conn_ref(conn); SET_FLAG(flag_is_connected); } @@ -35,17 +32,10 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) { char addr[BT_ADDR_LE_STR_LEN]; - if (conn != g_conn) { - return; - } - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); - bt_conn_unref(g_conn); - - g_conn = NULL; UNSET_FLAG(flag_is_connected); } @@ -154,7 +144,7 @@ static void test_main(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/host/misc/unregister_conn_cb/CMakeLists.txt b/tests/bsim/bluetooth/host/misc/unregister_conn_cb/CMakeLists.txt index 65762a174c2fa1..81042fb740b828 100644 --- a/tests/bsim/bluetooth/host/misc/unregister_conn_cb/CMakeLists.txt +++ b/tests/bsim/bluetooth/host/misc/unregister_conn_cb/CMakeLists.txt @@ -12,3 +12,6 @@ zephyr_include_directories( ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ ) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) +target_link_libraries(app PRIVATE testlib) diff --git a/tests/bsim/bluetooth/host/misc/unregister_conn_cb/prj.conf b/tests/bsim/bluetooth/host/misc/unregister_conn_cb/prj.conf index 2d054ed903179e..80583e565dc442 100644 --- a/tests/bsim/bluetooth/host/misc/unregister_conn_cb/prj.conf +++ b/tests/bsim/bluetooth/host/misc/unregister_conn_cb/prj.conf @@ -1,3 +1,4 @@ +CONFIG_ASSERT=y CONFIG_BT=y CONFIG_BT_DEVICE_NAME="conn tester" CONFIG_BT_PERIPHERAL=y diff --git a/tests/bsim/bluetooth/host/misc/unregister_conn_cb/src/main.c b/tests/bsim/bluetooth/host/misc/unregister_conn_cb/src/main.c index 1461ab69a9c4a4..b351f8b3a800c6 100644 --- a/tests/bsim/bluetooth/host/misc/unregister_conn_cb/src/main.c +++ b/tests/bsim/bluetooth/host/misc/unregister_conn_cb/src/main.c @@ -10,6 +10,8 @@ #include "bstests.h" #include +#include + #include "common.h" CREATE_FLAG(flag_is_connected); @@ -29,7 +31,8 @@ static void connected(struct bt_conn *conn, uint8_t err) printk("conn_callback:Connected to %s\n", addr); - g_conn = conn; + __ASSERT_NO_MSG(g_conn == NULL); + g_conn = bt_conn_ref(conn); SET_FLAG(flag_is_connected); } @@ -46,8 +49,8 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) printk("conn_callback:Disconnected: %s (reason 0x%02x)\n", addr, reason); bt_conn_unref(g_conn); - g_conn = NULL; + UNSET_FLAG(flag_is_connected); } @@ -60,6 +63,7 @@ void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, struct ne { char addr_str[BT_ADDR_LE_STR_LEN]; int err; + struct bt_conn *conn; if (g_conn != NULL) { printk("g_conn != NULL\n"); @@ -82,11 +86,13 @@ void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, struct ne return; } - err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn); + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &conn); if (err != 0) { FAIL("Could not connect to peer: %d", err); } printk("%s: connected to found device\n", __func__); + + bt_conn_unref(conn); } static void connection_info(struct bt_conn *conn, void *user_data) @@ -111,29 +117,36 @@ static void connection_info(struct bt_conn *conn, void *user_data) } } -static void test_peripheral_main(void) +static void start_adv(void) { int err; const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR))}; - err = bt_enable(NULL); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { - FAIL("Bluetooth init failed (err %d)\n", err); + FAIL("Advertising failed to start (err %d)\n", err); return; } - printk("Bluetooth initialized\n"); + printk("Advertising successfully started\n"); +} - bt_conn_cb_register(&conn_callbacks); +static void test_peripheral_main(void) +{ + int err; - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_enable(NULL); if (err != 0) { - FAIL("Advertising failed to start (err %d)\n", err); + FAIL("Bluetooth init failed (err %d)\n", err); return; } - printk("Advertising successfully started\n"); + printk("Bluetooth initialized\n"); + + bt_conn_cb_register(&conn_callbacks); + + start_adv(); WAIT_FOR_FLAG(flag_is_connected); @@ -141,6 +154,9 @@ static void test_peripheral_main(void) bt_conn_cb_unregister(&conn_callbacks); + bt_testlib_conn_wait_free(); + start_adv(); + k_sleep(K_SECONDS(1)); err = bt_disable(); From c28b0f1f7d4ce4e33f3972ee4ea4f1c718f2d165 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1266/1389] soc: nordic: configure run once for nrf54l15 Needed to support sysbuild (app + flpr) with --erase option. Signed-off-by: Piotr Kosycarz --- soc/nordic/soc.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/soc/nordic/soc.yml b/soc/nordic/soc.yml index d3400f78468bbb..8ce0e32cea71f4 100644 --- a/soc/nordic/soc.yml +++ b/soc/nordic/soc.yml @@ -61,6 +61,9 @@ runners: - qualifiers: - nrf9160 - nrf9160/ns + - qualifiers: + - nrf54l15/cpuapp + - nrf54l15/cpuflpr '--erase': - runners: - nrfjprog @@ -79,6 +82,9 @@ runners: - qualifiers: - nrf9160 - nrf9160/ns + - qualifiers: + - nrf54l15/cpuapp + - nrf54l15/cpuflpr '--reset': - runners: - nrfjprog @@ -97,3 +103,6 @@ runners: - qualifiers: - nrf9160 - nrf9160/ns + - qualifiers: + - nrf54l15/cpuapp + - nrf54l15/cpuflpr From afe7e90bb6a7ecd3eb347d7b1179ada10b1b95eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20LOCHE=20-=20MAKEEN=20Energy?= Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1267/1389] gpio: imx: Added IRQ lock for RMW operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPIO API performs unprotected RMW operations that can cause glitching and race conditions when GPIOs are used by different threads or ISRs. Signed-off-by: Jérémy LOCHE - MAKEEN Energy --- drivers/gpio/gpio_imx.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio_imx.c b/drivers/gpio/gpio_imx.c index 68caf1786da873..91159c918c7d1e 100644 --- a/drivers/gpio/gpio_imx.c +++ b/drivers/gpio/gpio_imx.c @@ -82,7 +82,11 @@ static int imx_gpio_configure(const struct device *port, gpio_pin_t pin, /* Init pin configuration struct, and use pinctrl api to apply settings */ __ASSERT_NO_MSG(pin < config->mux_count); + memcpy(&pin_cfg.pinmux, &config->pin_muxes[pin], sizeof(pin_cfg.pinmux)); + + unsigned int key = irq_lock(); + /* cfg register will be set by pinctrl_configure_pins */ pin_cfg.pin_ctrl_flags = reg; pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE); @@ -106,6 +110,8 @@ static int imx_gpio_configure(const struct device *port, gpio_pin_t pin, WRITE_BIT(base->GDIR, pin, 0U); } + irq_unlock(key); + return 0; } @@ -126,8 +132,10 @@ static int imx_gpio_port_set_masked_raw(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, (GPIO_ReadPortInput(base) & ~mask) | (value & mask)); + irq_unlock(key); return 0; } @@ -138,7 +146,9 @@ static int imx_gpio_port_set_bits_raw(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) | pins); + irq_unlock(key); return 0; } @@ -149,7 +159,9 @@ static int imx_gpio_port_clear_bits_raw(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) & ~pins); + irq_unlock(key); return 0; } @@ -160,7 +172,9 @@ static int imx_gpio_port_toggle_bits(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) ^ pins); + irq_unlock(key); return 0; } @@ -232,7 +246,7 @@ static void imx_gpio_port_isr(const struct device *port) struct imx_gpio_data *data = port->data; uint32_t int_status; - int_status = config->base->ISR; + int_status = config->base->ISR & config->base->IMR; config->base->ISR = int_status; From 712f9594623e18b4096ea1df2ad9c5a113f6c147 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1268/1389] debug: implement symtab generation Use pyelftools to extract the symbol table from the link stage executable. Then, filter out the function names and sort them based on their offsets before writing into the `symtab.c`, this is similar to how the `isr_tables` works. To access the structure, simply include the new header: ```c #include ``` Signed-off-by: Yong Cong Sin --- CMakeLists.txt | 14 ++++ doc/releases/release-notes-3.7.rst | 7 ++ include/zephyr/debug/symtab.h | 52 +++++++++++++ scripts/build/gen_symtab.py | 119 +++++++++++++++++++++++++++++ subsys/debug/CMakeLists.txt | 5 ++ subsys/debug/Kconfig | 10 +++ subsys/debug/symtab/CMakeLists.txt | 9 +++ subsys/debug/symtab/symtab.c | 46 +++++++++++ subsys/debug/symtab/symtab_stub.c | 14 ++++ 9 files changed, 276 insertions(+) create mode 100644 include/zephyr/debug/symtab.h create mode 100644 scripts/build/gen_symtab.py create mode 100644 subsys/debug/symtab/CMakeLists.txt create mode 100644 subsys/debug/symtab/symtab.c create mode 100644 subsys/debug/symtab/symtab_stub.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 401060f989cce7..0e9fc7280a9e67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1297,6 +1297,20 @@ if(CONFIG_GEN_ISR_TABLES) set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES isr_tables.c) endif() +if(CONFIG_SYMTAB) + add_custom_command( + OUTPUT symtab.c + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/gen_symtab.py + -k $ + -o symtab.c + DEPENDS ${ZEPHYR_LINK_STAGE_EXECUTABLE} + COMMAND_EXPAND_LISTS + ) + set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES symtab.c) +endif() + if(CONFIG_USERSPACE) set(KOBJECT_HASH_LIST kobject_hash.gperf) set(KOBJECT_HASH_OUTPUT_SRC_PRE kobject_hash_preprocessed.c) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index aff99963d78889..2ca4126c6cb2a0 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -323,6 +323,13 @@ Devicetree Libraries / Subsystems ********************** +* Debug + + * symtab + + * By enabling :kconfig:option:`CONFIG_SYMTAB`, the symbol table will be + generated with Zephyr link stage executable on supported architectures. + * Management * hawkBit diff --git a/include/zephyr/debug/symtab.h b/include/zephyr/debug/symtab.h new file mode 100644 index 00000000000000..a8685cf4ddd935 --- /dev/null +++ b/include/zephyr/debug/symtab.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEBUG_SYMTAB_H_ +#define ZEPHYR_INCLUDE_DEBUG_SYMTAB_H_ + +#include + +/** + * @cond INTERNAL_HIDDEN + */ + +struct z_symtab_entry { + const uint32_t offset; + const char *const name; +}; + +/** + * INTERNAL_HIDDEN @endcond + */ + +struct symtab_info { + /* Absolute address of the first symbol */ + const uintptr_t start_addr; + /* Number of symbol entries */ + const uint32_t length; + /* Symbol entries */ + const struct z_symtab_entry *const entries; +}; + +/** + * @brief Get the pointer to the symbol table. + * + * @return Pointer to the symbol table. + */ +const struct symtab_info *const symtab_get(void); + +/** + * @brief Find the symbol name with a binary search + * + * @param[in] addr Address of the symbol to find + * @param[out] offset Offset of the symbol from the nearest symbol. If the symbol can't be found, + * this will be 0. + * + * @return Name of the nearest symbol if found, otherwise "?" is returned. + */ +const char *const symtab_find_symbol_name(uintptr_t addr, uint32_t *offset); + +#endif /* ZEPHYR_INCLUDE_DEBUG_SYMTAB_H_ */ diff --git a/scripts/build/gen_symtab.py b/scripts/build/gen_symtab.py new file mode 100644 index 00000000000000..a2c767c44613fb --- /dev/null +++ b/scripts/build/gen_symtab.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Meta Platforms +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import sys +import os + +from elftools.elf.elffile import ELFFile +from elftools.elf.descriptions import ( + describe_symbol_type, +) + + +class gen_symtab_log: + + def __init__(self, debug=False): + self.__debug = debug + + def debug(self, text): + """Print debug message if debugging is enabled. + + Note - this function requires config global variable to be initialized. + """ + if self.__debug: + sys.stdout.write(os.path.basename( + sys.argv[0]) + ": " + text + "\n") + + @staticmethod + def error(text): + sys.exit(os.path.basename(sys.argv[0]) + ": error: " + text + "\n") + + def set_debug(self, state): + self.__debug = state + + +log = gen_symtab_log() + + +def parse_args(): + parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) + + parser.add_argument("-k", "--kernel", required=True, + help="Zephyr kernel image") + parser.add_argument("-o", "--output", required=True, + help="Output source file") + parser.add_argument("-d", "--debug", action="store_true", + help="Print additional debugging information") + + return parser.parse_args() + + +class symtab_entry: + def __init__(self, addr, offset, name): + self.addr = addr + self.offset = offset + self.name = name + + +start_addr = 0 +symtab_list = [] + + +def main(): + args = parse_args() + log.set_debug(args.debug) + + with open(args.kernel, "rb") as rf: + elf = ELFFile(rf) + + # Find the symbol table. + symtab = elf.get_section_by_name('.symtab') + + i = 1 + for nsym, symbol in enumerate(symtab.iter_symbols()): # pylint: disable=unused-variable + symbol_type = describe_symbol_type(symbol['st_info']['type']) + symbol_addr = symbol['st_value'] + + if symbol_type == 'FUNC' and symbol_addr != 0: + symtab_list.append(symtab_entry( + symbol_addr, symbol_addr, symbol.name)) + log.debug('%6d: %s %.25s' % ( + i, + hex(symbol_addr), + symbol.name)) + i = i + 1 + + symtab_list.sort(key=lambda x: x.addr, reverse=False) + + # Get the address of the first symbol + start_addr = symtab_list[0].addr + # Use that to calculate the offset of other symbols relative to the first one + for i, entry in enumerate(symtab_list): + entry.offset = entry.addr - start_addr + + with open(args.output, 'w') as wf: + print("/* AUTO-GENERATED by gen_symtab.py, do not edit! */", file=wf) + print("", file=wf) + print("#include ", file=wf) + print("", file=wf) + print( + f"const struct z_symtab_entry z_symtab_entries[{len(symtab_list)}] = {{", file=wf) + for i, entry in enumerate(symtab_list): + print( + f"\t[{i}] = {{.offset = {hex(entry.offset)}, .name = \"{entry.name}\"}}, /* {hex(entry.addr)} */", file=wf) + print(f"}};\n", file=wf) + + print(f"const struct symtab_info z_symtab = {{", file=wf) + print(f"\t.start_addr = {hex(start_addr)},", file=wf) + print(f"\t.length = {len(symtab_list)},", file=wf) + print(f"\t.entries = z_symtab_entries,", file=wf) + print(f"}};\n", file=wf) + + +if __name__ == "__main__": + main() diff --git a/subsys/debug/CMakeLists.txt b/subsys/debug/CMakeLists.txt index d9cbc68b975b86..200e3bcb386626 100644 --- a/subsys/debug/CMakeLists.txt +++ b/subsys/debug/CMakeLists.txt @@ -34,3 +34,8 @@ zephyr_sources_ifdef( CONFIG_MIPI_STP_DECODER mipi_stp_decoder.c ) + +add_subdirectory_ifdef( + CONFIG_SYMTAB + symtab + ) diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 5fd5d9bfd5d2cc..3721261e3d62e5 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -368,6 +368,16 @@ config DEBUG_INFO used by debuggers in debugging the system, or enable additional debugging information to be reported at runtime. +config SYMTAB + bool "Generate symbol table" + help + Generate the symbol table with the offset and name of every + function. + The symbol table can be accessed by including the + header. + + Choose N if you have no idea what is this. + config EXCEPTION_STACK_TRACE bool "Attempt to print stack traces upon exceptions" default y diff --git a/subsys/debug/symtab/CMakeLists.txt b/subsys/debug/symtab/CMakeLists.txt new file mode 100644 index 00000000000000..5e128c8bc3abe3 --- /dev/null +++ b/subsys/debug/symtab/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_library(symtab + symtab.c + symtab_stub.c +) + +target_link_libraries(symtab zephyr_interface) +zephyr_library_link_libraries(symtab) diff --git a/subsys/debug/symtab/symtab.c b/subsys/debug/symtab/symtab.c new file mode 100644 index 00000000000000..98b865a440344e --- /dev/null +++ b/subsys/debug/symtab/symtab.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +const struct symtab_info *const symtab_get(void) +{ + extern const struct symtab_info z_symtab; + + return &z_symtab; +} + +const char *const symtab_find_symbol_name(uintptr_t addr, uint32_t *offset) +{ + const struct symtab_info *const symtab = symtab_get(); + const uint32_t symbol_offset = addr - symtab->start_addr; + uint32_t left = 0, right = symtab->length - 1; + uint32_t ret_offset = 0; + const char *ret_name = "?"; + + while (left <= right) { + uint32_t mid = left + (right - left) / 2; + + if ((symbol_offset >= symtab->entries[mid].offset) && + (symbol_offset < symtab->entries[mid + 1].offset)) { + ret_offset = symbol_offset - symtab->entries[mid].offset; + ret_name = symtab->entries[mid].name; + break; + } else if (symbol_offset < symtab->entries[mid].offset) { + right = mid - 1; + } else { + left = mid + 1; + } + } + + if (offset != NULL) { + *offset = ret_offset; + } + + return ret_name; +} diff --git a/subsys/debug/symtab/symtab_stub.c b/subsys/debug/symtab/symtab_stub.c new file mode 100644 index 00000000000000..a99b85e7aa521f --- /dev/null +++ b/subsys/debug/symtab/symtab_stub.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/** + * These are placeholder variables. They will be replaced by the real ones + * generated by `gen_symtab.py`. + */ +const struct z_symtab_entry *z_symtab_entries; +const struct symtab_info z_symtab; From 74492fa47258a0948c27dfdc9b29f334badd1802 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1269/1389] arch: riscv: use symtab to print function name in stack trace Selecting `CONFIG_EXCEPTION_STACK_TRACE_SYMTAB` will enable the symtab generation which will be used in the stack trace to print the function name of the return address. Updated the `stack_unwind` test to test the symbols in a stack trace. Signed-off-by: Yong Cong Sin --- arch/riscv/core/stacktrace.c | 28 ++++++++++++++++++-- doc/releases/release-notes-3.7.rst | 9 +++++-- subsys/debug/Kconfig | 9 +++++++ tests/arch/common/stack_unwind/testcase.yaml | 15 +++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index a85dcfbd82d84e..1f3676252c66f4 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -26,6 +27,21 @@ struct stackframe { uintptr_t ra; }; +#ifdef CONFIG_RISCV_ENABLE_FRAME_POINTER +#define SFP_FMT "fp: " +#else +#define SFP_FMT "sp: " +#endif + +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB +#define LOG_STACK_TRACE(idx, sfp, ra, name, offset) \ + LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG " [%s+0x%x]", idx, sfp, ra, name, \ + offset) +#else +#define LOG_STACK_TRACE(idx, sfp, ra, name, offset) \ + LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG, idx, sfp, ra) +#endif + static bool in_stack_bound(uintptr_t addr) { #ifdef CONFIG_THREAD_STACK_INFO @@ -82,7 +98,11 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) frame = (struct stackframe *)fp - 1; ra = frame->ra; if (in_text_region(ra)) { - LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, fp, ra); +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); +#endif + LOG_STACK_TRACE(i, fp, ra, name, offset); /* * Increment the iterator only if `ra` is within the text region to get the * most out of it @@ -112,7 +132,11 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) ksp++) { ra = *ksp; if (in_text_region(ra)) { - LOG_ERR(" %2d: sp: " PR_REG " ra: " PR_REG, i, (uintptr_t)ksp, ra); +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); +#endif + LOG_STACK_TRACE(i, (uintptr_t)ksp, ra, name, offset); /* * Increment the iterator only if `ra` is within the text region to get the * most out of it diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 2ca4126c6cb2a0..d30186c7c7307c 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -73,10 +73,15 @@ Architectures * RISC-V - * Implemented frame-pointer based stack unwinding. - * The fatal error message triggered from a fault now contains the callee-saved-registers states. + * Implemented stack unwinding + + * Frame-pointer can be selected to enable precise stack traces at the expense of slightly + increased size and decreased speed. + + * Symbol names can be enabled by selecting :kconfig:option:`CONFIG_EXCEPTION_STACK_TRACE_SYMTAB` + * Xtensa Kernel diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 3721261e3d62e5..819d70343530f4 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -389,6 +389,15 @@ config EXCEPTION_STACK_TRACE print a stack trace of function memory addresses when an exception is reported. +config EXCEPTION_STACK_TRACE_SYMTAB + bool "Print function names in the stack trace" + select SYMTAB + depends on EXCEPTION_STACK_TRACE + help + Enable this if you want to print the function names in the + stack trace output. This will generate the symtab and + can consume a lot of ROM if there's a lot of functions. + # # Miscellaneous debugging options # diff --git a/tests/arch/common/stack_unwind/testcase.yaml b/tests/arch/common/stack_unwind/testcase.yaml index 9f29790f95cdf9..84e00ecbf5910e 100644 --- a/tests/arch/common/stack_unwind/testcase.yaml +++ b/tests/arch/common/stack_unwind/testcase.yaml @@ -50,3 +50,18 @@ tests: regex: - "E: backtrace 0: fp: \\w+ lr: \\w+" - "E: backtrace 1: fp: \\w+ lr: \\w+" + arch.common.stack_unwind.symtab: + arch_allow: + - riscv + integration_platforms: + - qemu_riscv32 + - qemu_riscv64 + extra_args: OVERLAY_CONFIG="enable_fp.conf" + harness_config: + type: multi_line + regex: + - "[func1+\\w+]" + - "[func2+\\w+]" + - "[func1+\\w+]" + - "[func2+\\w+]" + - "[func1+\\w+]" From af4b7cb553c45741a927dac5d85383d2fb09deef Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1270/1389] arch: riscv: print symbol name of `mepc` if `CONFIG_SYMTAB` is enabled The mepc register is the address of the instruction that was interrupted, it will make debugging easier if we know the name of the symbol, so print it if `CONFIG_SYMTAB` is enabled. Signed-off-by: Yong Cong Sin --- arch/riscv/core/fatal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 8efffd37371937..31ead071eb9c24 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -79,7 +80,14 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf #endif /* CONFIG_RISCV_ISA_RV32E */ LOG_ERR(" sp: " PR_REG, z_riscv_get_sp_before_exc(esf)); LOG_ERR(" ra: " PR_REG, esf->ra); +#ifndef CONFIG_SYMTAB LOG_ERR(" mepc: " PR_REG, esf->mepc); +#else + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(esf->mepc, &offset); + + LOG_ERR(" mepc: " PR_REG " [%s+0x%x]", esf->mepc, name, offset); +#endif LOG_ERR("mstatus: " PR_REG, esf->mstatus); LOG_ERR(""); } From 898b9a07725d07956861a78fe07f5a37d4a476ef Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1271/1389] arch: arm64: use symtab to print function name in stack trace Selecting `CONFIG_SYMTAB` will enable the symtab generation which will be used in the stack trace to print the function name of the return address. Added `arm64` to the `arch.common.stack_unwind.symtab` test. Signed-off-by: Yong Cong Sin --- arch/arm64/core/fatal.c | 9 +++++++++ doc/releases/release-notes-3.7.rst | 4 ++++ tests/arch/common/stack_unwind/testcase.yaml | 2 ++ 3 files changed, 15 insertions(+) diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index 84ff767508ed14..92ef0d8a3da8b7 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -13,6 +13,7 @@ * exceptions */ +#include #include #include #include @@ -224,8 +225,16 @@ static void esf_unwind(const z_arch_esf_t *esf) LOG_ERR(""); while (fp != NULL) { lr = fp[1]; +#ifdef CONFIG_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(lr, &offset); + + LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx [%s+0x%x]", + count++, (uint64_t) fp, lr, name, offset); +#else LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx", count++, (uint64_t) fp, lr); +#endif fp = (uint64_t *) fp[0]; } LOG_ERR(""); diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index d30186c7c7307c..334d12ed0535f1 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -71,6 +71,10 @@ Architectures * ARM +* ARM64 + + * Implemented symbol names in the backtraces, enable by selecting :kconfig:option:`CONFIG_SYMTAB` + * RISC-V * The fatal error message triggered from a fault now contains the callee-saved-registers states. diff --git a/tests/arch/common/stack_unwind/testcase.yaml b/tests/arch/common/stack_unwind/testcase.yaml index 84e00ecbf5910e..f57e8b41048b45 100644 --- a/tests/arch/common/stack_unwind/testcase.yaml +++ b/tests/arch/common/stack_unwind/testcase.yaml @@ -53,9 +53,11 @@ tests: arch.common.stack_unwind.symtab: arch_allow: - riscv + - arm64 integration_platforms: - qemu_riscv32 - qemu_riscv64 + - qemu_cortex_a53 extra_args: OVERLAY_CONFIG="enable_fp.conf" harness_config: type: multi_line From 0291d0deb56bd9f1f6c5e2036a4ec17d9784638c Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:35 +0200 Subject: [PATCH 1272/1389] arch: make the max stack frames configurable Current on x86 & risc-v that implement stack trace, the maximum depth of the stack trace is defined by a macro. Introduce a new Kconfig:EXCEPTION_STACK_TRACE_MAX_FRAMES so that this is configurable in software. Signed-off-by: Yong Cong Sin --- arch/riscv/core/stacktrace.c | 2 +- arch/x86/core/fatal.c | 2 +- subsys/debug/Kconfig | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index 1f3676252c66f4..e0c97b642ba3dc 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -20,7 +20,7 @@ uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf); #define PR_REG "%016" PRIxPTR #endif -#define MAX_STACK_FRAMES 8 +#define MAX_STACK_FRAMES CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES struct stackframe { uintptr_t fp; diff --git a/arch/x86/core/fatal.c b/arch/x86/core/fatal.c index 370386d4af96be..a2aea6574987ec 100644 --- a/arch/x86/core/fatal.c +++ b/arch/x86/core/fatal.c @@ -140,7 +140,7 @@ struct stack_frame { #endif }; -#define MAX_STACK_FRAMES 8 +#define MAX_STACK_FRAMES CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES __pinned_func static void unwind_stack(uintptr_t base_ptr, uint16_t cs) diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index 819d70343530f4..00243f49be9673 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -389,6 +389,14 @@ config EXCEPTION_STACK_TRACE print a stack trace of function memory addresses when an exception is reported. +config EXCEPTION_STACK_TRACE_MAX_FRAMES + int "Configures the depth of stack trace" + default 8 + depends on EXCEPTION_STACK_TRACE + help + In the event of a stack trace, this place a limit on the depths + of the stack to examine. + config EXCEPTION_STACK_TRACE_SYMTAB bool "Print function names in the stack trace" select SYMTAB From 958e305e930cea666b0eceb5d75b29270980e56a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1273/1389] maintainers: ite: edit files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only include dts bindings, that start with ite, instead of all containing it. Signed-off-by: Fin Maaß --- MAINTAINERS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index fe4526c16f331c..a980ed92529dc0 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3645,7 +3645,7 @@ ITE Platforms: - drivers/sensor/ite/ - drivers/*/*it8xxx2*.c - drivers/*/*_ite_* - - dts/bindings/*/*ite* + - dts/bindings/*/ite* - dts/riscv/ite/ - soc/ite/ labels: From da83831cc63f574dfaa2439180fc4aba2f050660 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1274/1389] drivers: counter: Add support for Apollo3 SoCs counter This commit adds support for the counter which can be found in Apollo3 SoCs Signed-off-by: Hao Luo --- boards/ambiq/apollo3_evb/apollo3_evb.dts | 32 ++++ boards/ambiq/apollo3_evb/apollo3_evb.yaml | 1 + boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 32 ++++ boards/ambiq/apollo3p_evb/apollo3p_evb.yaml | 1 + drivers/counter/counter_ambiq_timer.c | 169 ++++++++++++++++---- dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 67 +++++++- dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 67 +++++++- dts/bindings/counter/ambiq,counter.yaml | 10 ++ 8 files changed, 350 insertions(+), 29 deletions(-) diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index 9f1cac0b309805..c6a0f70f907414 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -103,6 +103,38 @@ status = "okay"; }; +&counter0 { + status = "okay"; +}; + +&counter1 { + status = "okay"; +}; + +&counter2 { + status = "okay"; +}; + +&counter3 { + status = "okay"; +}; + +&counter4 { + status = "okay"; +}; + +&counter5 { + status = "okay"; +}; + +&counter6 { + status = "okay"; +}; + +&counter7 { + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.yaml b/boards/ambiq/apollo3_evb/apollo3_evb.yaml index f55c135f1d4afc..09275d9e5f82b5 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.yaml +++ b/boards/ambiq/apollo3_evb/apollo3_evb.yaml @@ -10,6 +10,7 @@ toolchain: supported: - uart - watchdog + - counter - gpio - i2c testing: diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index 02acc1bed5705f..902a909cc9f2c6 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -103,6 +103,38 @@ status = "okay"; }; +&counter0 { + status = "okay"; +}; + +&counter1 { + status = "okay"; +}; + +&counter2 { + status = "okay"; +}; + +&counter3 { + status = "okay"; +}; + +&counter4 { + status = "okay"; +}; + +&counter5 { + status = "okay"; +}; + +&counter6 { + status = "okay"; +}; + +&counter7 { + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml index 0ed3fe2929df01..275c1efb6ef4c5 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml @@ -10,6 +10,7 @@ toolchain: supported: - uart - watchdog + - counter - gpio - i2c testing: diff --git a/drivers/counter/counter_ambiq_timer.c b/drivers/counter/counter_ambiq_timer.c index 67df6c5647f690..2036102138dd1f 100644 --- a/drivers/counter/counter_ambiq_timer.c +++ b/drivers/counter/counter_ambiq_timer.c @@ -18,10 +18,11 @@ LOG_MODULE_REGISTER(ambiq_counter, CONFIG_COUNTER_LOG_LEVEL); static void counter_ambiq_isr(void *arg); -#define TIMER_IRQ (DT_INST_IRQN(0)) - struct counter_ambiq_config { struct counter_config_info counter_info; + uint32_t instance; + uint32_t clk_src; + void (*irq_config_func)(void); }; struct counter_ambiq_data { @@ -31,33 +32,76 @@ struct counter_ambiq_data { static struct k_spinlock lock; -static int counter_ambiq_init(const struct device *dev) +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +static void counter_irq_config_func(void) { - am_hal_timer_config_t tc; + /* Apollo3 counters share the same irq number, connect to counter0 once when init and handle + * different banks in counter_ambiq_isr + */ + static bool global_irq_init = true; + + if (!global_irq_init) { + return; + } + + global_irq_init = false; + + /* Shared irq config default to ctimer0. */ + NVIC_ClearPendingIRQ(CTIMER_IRQn); + IRQ_CONNECT(CTIMER_IRQn, DT_INST_IRQ(0, priority), counter_ambiq_isr, DEVICE_DT_INST_GET(0), + 0); + irq_enable(CTIMER_IRQn); +}; +#endif +static int counter_ambiq_init(const struct device *dev) +{ k_spinlock_key_t key = k_spin_lock(&lock); + const struct counter_ambiq_config *cfg = dev->config; + +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + /* Timer configuration */ + am_hal_ctimer_config_t sContTimer; + /* Create 32-bit timer */ + sContTimer.ui32Link = 1; + /* Set up TimerA. */ + sContTimer.ui32TimerAConfig = (AM_HAL_CTIMER_FN_REPEAT | AM_HAL_CTIMER_INT_ENABLE | + (cfg->clk_src << CTIMER_CTRL0_TMRA0CLK_Pos)); + /* Set up TimerB. */ + sContTimer.ui32TimerBConfig = 0; + + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); + + am_hal_ctimer_clear(cfg->instance, AM_HAL_CTIMER_BOTH); + am_hal_ctimer_config(cfg->instance, &sContTimer); + counter_irq_config_func(); +#else + am_hal_timer_config_t tc; am_hal_timer_default_config_set(&tc); - tc.eInputClock = AM_HAL_TIMER_CLOCK_HFRC_DIV16; + tc.eInputClock = cfg->clk_src; tc.eFunction = AM_HAL_TIMER_FN_UPCOUNT; tc.ui32PatternLimit = 0; - am_hal_timer_config(0, &tc); + am_hal_timer_config(cfg->instance, &tc); + cfg->irq_config_func(); +#endif k_spin_unlock(&lock, key); - NVIC_ClearPendingIRQ(TIMER_IRQ); - IRQ_CONNECT(TIMER_IRQ, 0, counter_ambiq_isr, DEVICE_DT_INST_GET(0), 0); - irq_enable(TIMER_IRQ); - return 0; } static int counter_ambiq_start(const struct device *dev) { + const struct counter_ambiq_config *cfg = dev->config; k_spinlock_key_t key = k_spin_lock(&lock); - am_hal_timer_start(0); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_start(cfg->instance, AM_HAL_CTIMER_TIMERA); +#else + am_hal_timer_start(cfg->instance); +#endif k_spin_unlock(&lock, key); @@ -66,9 +110,15 @@ static int counter_ambiq_start(const struct device *dev) static int counter_ambiq_stop(const struct device *dev) { + const struct counter_ambiq_config *cfg = dev->config; + k_spinlock_key_t key = k_spin_lock(&lock); - am_hal_timer_stop(0); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_stop(cfg->instance, AM_HAL_CTIMER_BOTH); +#else + am_hal_timer_stop(cfg->instance); +#endif k_spin_unlock(&lock, key); @@ -77,9 +127,16 @@ static int counter_ambiq_stop(const struct device *dev) static int counter_ambiq_get_value(const struct device *dev, uint32_t *ticks) { + const struct counter_ambiq_config *cfg = dev->config; + k_spinlock_key_t key = k_spin_lock(&lock); - *ticks = am_hal_timer_read(0); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + *ticks = (am_hal_ctimer_read(cfg->instance, AM_HAL_CTIMER_TIMERA)) | + (am_hal_ctimer_read(cfg->instance, AM_HAL_CTIMER_TIMERB) << 16); +#else + *ticks = am_hal_timer_read(cfg->instance); +#endif k_spin_unlock(&lock, key); @@ -91,21 +148,34 @@ static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id, { ARG_UNUSED(chan_id); struct counter_ambiq_data *data = dev->data; + const struct counter_ambiq_config *cfg = dev->config; uint32_t now; counter_ambiq_get_value(dev, &now); k_spinlock_key_t key = k_spin_lock(&lock); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_int_clear(AM_HAL_CTIMER_INT_TIMERA0C0); + am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA0C0); + + if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { + am_hal_ctimer_compare_set(cfg->instance, AM_HAL_CTIMER_BOTH, 0, + now + alarm_cfg->ticks); + } else { + am_hal_ctimer_compare_set(cfg->instance, AM_HAL_CTIMER_BOTH, 0, alarm_cfg->ticks); + } +#else /* Enable interrupt, due to counter_ambiq_cancel_alarm() disables it*/ - am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); - am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { - am_hal_timer_compare1_set(0, now + alarm_cfg->ticks); + am_hal_timer_compare1_set(cfg->instance, now + alarm_cfg->ticks); } else { - am_hal_timer_compare1_set(0, alarm_cfg->ticks); + am_hal_timer_compare1_set(cfg->instance, alarm_cfg->ticks); } +#endif data->user_data = alarm_cfg->user_data; data->callback = alarm_cfg->callback; @@ -118,12 +188,19 @@ static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id, static int counter_ambiq_cancel_alarm(const struct device *dev, uint8_t chan_id) { ARG_UNUSED(chan_id); - + const struct counter_ambiq_config *cfg = dev->config; k_spinlock_key_t key = k_spin_lock(&lock); - am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_int_disable(AM_HAL_CTIMER_INT_TIMERA0C0); /* Reset the compare register */ - am_hal_timer_compare1_set(0, 0); + am_hal_ctimer_compare_set(cfg->instance, AM_HAL_CTIMER_BOTH, 0, 0); +#else + am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); + /* Reset the compare register */ + am_hal_timer_compare1_set(cfg->instance, 0); +#endif + k_spin_unlock(&lock, key); return 0; @@ -163,33 +240,71 @@ static const struct counter_driver_api counter_api = { .get_top_value = counter_ambiq_get_top_value, }; +#define APOLLO3_HANDLE_SHARED_TIMER_IRQ(n) \ + static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \ + struct counter_ambiq_data *const data_##n = dev_##n->data; \ + uint32_t status_##n = CTIMERn(n)->INTSTAT; \ + status_##n &= CTIMERn(n)->INTEN; \ + if (status_##n) { \ + CTIMERn(n)->INTCLR = AM_HAL_CTIMER_INT_TIMERA0C0; \ + counter_ambiq_get_value(dev_##n, &now); \ + if (data_##n->callback) { \ + data_##n->callback(dev_##n, 0, now, data_##n->user_data); \ + } \ + } + static void counter_ambiq_isr(void *arg) { + uint32_t now = 0; + +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + ARG_UNUSED(arg); + + DT_INST_FOREACH_STATUS_OKAY(APOLLO3_HANDLE_SHARED_TIMER_IRQ) +#else const struct device *dev = (const struct device *)arg; struct counter_ambiq_data *data = dev->data; - uint32_t now = 0; + const struct counter_ambiq_config *cfg = dev->config; - am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); counter_ambiq_get_value(dev, &now); if (data->callback) { data->callback(dev, 0, now, data->user_data); } +#endif } +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +/* Apollo3 counters share the same irq number, connect irq here will cause build error, so we + * leave this function blank here and do it in counter_irq_config_func + */ +#define AMBIQ_COUNTER_CONFIG_FUNC(idx) static void counter_irq_config_func_##idx(void){}; +#else +#define AMBIQ_COUNTER_CONFIG_FUNC(idx) \ + static void counter_irq_config_func_##idx(void) \ + { \ + NVIC_ClearPendingIRQ(DT_INST_IRQN(idx)); \ + IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), counter_ambiq_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_INST_IRQN(idx)); \ + }; +#endif + #define AMBIQ_COUNTER_INIT(idx) \ - \ + static void counter_irq_config_func_##idx(void); \ static struct counter_ambiq_data counter_data_##idx; \ - \ static const struct counter_ambiq_config counter_config_##idx = { \ + .instance = (DT_INST_REG_ADDR(idx) - DT_INST_REG_ADDR(0)) / DT_INST_REG_SIZE(idx), \ + .clk_src = DT_INST_PROP(idx, clk_source), \ .counter_info = {.max_top_value = UINT32_MAX, \ - .freq = 6000000, \ + .freq = DT_INST_PROP(idx, clock_frequency), \ .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ .channels = 1}, \ + .irq_config_func = counter_irq_config_func_##idx, \ }; \ - \ + AMBIQ_COUNTER_CONFIG_FUNC(idx) \ DEVICE_DT_INST_DEFINE(idx, counter_ambiq_init, NULL, &counter_data_##idx, \ &counter_config_##idx, PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ &counter_api); - DT_INST_FOREACH_STATUS_OKAY(AMBIQ_COUNTER_INIT); diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index 0005102b69727a..5935352068da81 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -70,8 +70,73 @@ counter0: counter@40008000 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008000 0x20>; interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter1: counter@40008020 { + compatible = "ambiq,counter"; + reg = <0x40008020 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter2: counter@40008040 { + compatible = "ambiq,counter"; + reg = <0x40008040 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter3: counter@40008060 { + compatible = "ambiq,counter"; + reg = <0x40008060 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter4: counter@40008080 { + compatible = "ambiq,counter"; + reg = <0x40008080 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter5: counter@400080a0 { + compatible = "ambiq,counter"; + reg = <0x400080A0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter6: counter@400080c0 { + compatible = "ambiq,counter"; + reg = <0x400080C0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter7: counter@400080e0 { + compatible = "ambiq,counter"; + reg = <0x400080E0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; status = "disabled"; }; diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index dc578356bf1437..d4063fb98cf85c 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -70,8 +70,73 @@ counter0: counter@40008000 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008000 0x20>; interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter1: counter@40008020 { + compatible = "ambiq,counter"; + reg = <0x40008020 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter2: counter@40008040 { + compatible = "ambiq,counter"; + reg = <0x40008040 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter3: counter@40008060 { + compatible = "ambiq,counter"; + reg = <0x40008060 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter4: counter@40008080 { + compatible = "ambiq,counter"; + reg = <0x40008080 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter5: counter@400080a0 { + compatible = "ambiq,counter"; + reg = <0x400080A0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter6: counter@400080c0 { + compatible = "ambiq,counter"; + reg = <0x400080C0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter7: counter@400080e0 { + compatible = "ambiq,counter"; + reg = <0x400080E0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; status = "disabled"; }; diff --git a/dts/bindings/counter/ambiq,counter.yaml b/dts/bindings/counter/ambiq,counter.yaml index 7ae915c4d21559..63399c06cae7c7 100644 --- a/dts/bindings/counter/ambiq,counter.yaml +++ b/dts/bindings/counter/ambiq,counter.yaml @@ -13,3 +13,13 @@ properties: interrupts: required: true + + clock-frequency: + type: int + required: true + description: Counter clock frequency + + clk-source: + type: int + required: true + description: Counter clock source From 537a3c018055134eba3babe46ba2ed4d9c7aaca1 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1275/1389] drivers: counter: Change apollo4p counter base address Changed apollo4p counter base address to match the updated counter driver. Signed-off-by: Hao Luo --- dts/arm/ambiq/ambiq_apollo4p.dtsi | 6 ++++-- dts/arm/ambiq/ambiq_apollo4p_blue.dtsi | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dts/arm/ambiq/ambiq_apollo4p.dtsi b/dts/arm/ambiq/ambiq_apollo4p.dtsi index aa95ff80c9adb3..b7ce6461e359e6 100644 --- a/dts/arm/ambiq/ambiq_apollo4p.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p.dtsi @@ -96,10 +96,12 @@ status = "okay"; }; - counter0: counter@40008000 { + counter0: counter@40008200 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008200 0x20>; interrupts = <67 0>; + clock-frequency = ; + clk-source = <1>; status = "disabled"; }; diff --git a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi index dfc2f59de3d700..7f4d7145877fbf 100644 --- a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi @@ -78,10 +78,12 @@ status = "okay"; }; - counter0: counter@40008000 { + counter0: counter@40008200 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008200 0x20>; interrupts = <67 0>; + clock-frequency = ; + clk-source = <1>; status = "disabled"; }; From f6bada1827628b5f7a83e1a4d6e25dad623d5597 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1276/1389] mbedtls: add configuration file for PSA features Adding a Kconfig and a header file to control which PSA features are to be used from MbedTLS: - new kconfig symbols are placed in a separate header file (Kconfig.psa) and are guarded by MBEDTLS_PSA_CRYPTO_CLIENT. The reason for this is that TLS/X509 can either rely on PSA functions provided by MbedTLS (when MBEDTLS_PSA_CRYPTO_C is defined) or TFM (when BUILD_WITH_TFM is selected). Therefore we could not make these new Kconfigs depending on MBEDTLS_PSA_CRYPTO_C. - by default all PSA symbols are enabled, but they can be disabled by respective Kconfigs in order to reduce the image size. - the new header file (config-psa-generic.h) mimics what config-tls-generic.h does for MbedTLS builtin symbols: it enables a build symbol for every Kconfig one. The name is kept identical in the 2 cases (a part from the initial CONFIG_ in order to simplify the mechanism). - MBEDTLS_PSA_CRYPTO_CONFIG is finally enabled whenever there is any PSA crypto provider (either MBEDTLS_PSA_CRYPTO_C or TFM) Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.psa | 342 +++++++++++++++++- modules/mbedtls/configs/config-psa.h | 351 +++++++++++++++++++ modules/mbedtls/configs/config-tls-generic.h | 7 +- scripts/ci/check_compliance.py | 1 + 4 files changed, 696 insertions(+), 5 deletions(-) create mode 100644 modules/mbedtls/configs/config-psa.h diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index 35200a9d2f4f2a..e6121ed9173b1a 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -1,6 +1,10 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +# This file was automatically generated by create_psa_files.py +# from: ../../../modules/crypto/mbedtls/include/psa/crypto_config.h. +# Do not edit it manually. + config MBEDTLS_PSA_CRYPTO_CLIENT bool default y @@ -8,7 +12,343 @@ config MBEDTLS_PSA_CRYPTO_CLIENT if MBEDTLS_PSA_CRYPTO_CLIENT +config PSA_CRYPTO_ENABLE_ALL + bool "All PSA crypto features" + +config PSA_WANT_ALG_CBC_NO_PADDING + bool "PSA_WANT_ALG_CBC_NO_PADDING" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CBC_PKCS7 + bool "PSA_WANT_ALG_CBC_PKCS7" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CCM + bool "PSA_WANT_ALG_CCM" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CCM_STAR_NO_TAG + bool "PSA_WANT_ALG_CCM_STAR_NO_TAG" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CMAC + bool "PSA_WANT_ALG_CMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CFB + bool "PSA_WANT_ALG_CFB" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CHACHA20_POLY1305 + bool "PSA_WANT_ALG_CHACHA20_POLY1305" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CTR + bool "PSA_WANT_ALG_CTR" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_DETERMINISTIC_ECDSA + bool "PSA_WANT_ALG_DETERMINISTIC_ECDSA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_ECB_NO_PADDING + bool "PSA_WANT_ALG_ECB_NO_PADDING" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_ECDH + bool "PSA_WANT_ALG_ECDH" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_FFDH + bool "PSA_WANT_ALG_FFDH" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_ECDSA + bool "PSA_WANT_ALG_ECDSA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_JPAKE + bool "PSA_WANT_ALG_JPAKE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_GCM + bool "PSA_WANT_ALG_GCM" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HKDF + bool "PSA_WANT_ALG_HKDF" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HKDF_EXTRACT + bool "PSA_WANT_ALG_HKDF_EXTRACT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HKDF_EXPAND + bool "PSA_WANT_ALG_HKDF_EXPAND" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HMAC + bool "PSA_WANT_ALG_HMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_MD5 + bool "PSA_WANT_ALG_MD5" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_OFB + bool "PSA_WANT_ALG_OFB" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_PBKDF2_HMAC + bool "PSA_WANT_ALG_PBKDF2_HMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 + bool "PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RIPEMD160 + bool "PSA_WANT_ALG_RIPEMD160" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_OAEP + bool "PSA_WANT_ALG_RSA_OAEP" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_PKCS1V15_CRYPT + bool "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_PKCS1V15_SIGN + bool "PSA_WANT_ALG_RSA_PKCS1V15_SIGN" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_PSS + bool "PSA_WANT_ALG_RSA_PSS" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_1 + bool "PSA_WANT_ALG_SHA_1" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_224 + bool "PSA_WANT_ALG_SHA_224" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + config PSA_WANT_ALG_SHA_256 - bool "SHA-256 hash algorithm through PSA" + bool "PSA_WANT_ALG_SHA_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_384 + bool "PSA_WANT_ALG_SHA_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_512 + bool "PSA_WANT_ALG_SHA_512" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_224 + bool "PSA_WANT_ALG_SHA3_224" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_256 + bool "PSA_WANT_ALG_SHA3_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_384 + bool "PSA_WANT_ALG_SHA3_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_512 + bool "PSA_WANT_ALG_SHA3_512" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_STREAM_CIPHER + bool "PSA_WANT_ALG_STREAM_CIPHER" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_TLS12_PRF + bool "PSA_WANT_ALG_TLS12_PRF" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_TLS12_PSK_TO_MS + bool "PSA_WANT_ALG_TLS12_PSK_TO_MS" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + bool "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_BRAINPOOL_P_R1_256 + bool "PSA_WANT_ECC_BRAINPOOL_P_R1_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_BRAINPOOL_P_R1_384 + bool "PSA_WANT_ECC_BRAINPOOL_P_R1_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_BRAINPOOL_P_R1_512 + bool "PSA_WANT_ECC_BRAINPOOL_P_R1_512" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_MONTGOMERY_255 + bool "PSA_WANT_ECC_MONTGOMERY_255" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_MONTGOMERY_448 + bool "PSA_WANT_ECC_MONTGOMERY_448" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_K1_192 + bool "PSA_WANT_ECC_SECP_K1_192" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_K1_256 + bool "PSA_WANT_ECC_SECP_K1_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_192 + bool "PSA_WANT_ECC_SECP_R1_192" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_224 + bool "PSA_WANT_ECC_SECP_R1_224" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_256 + bool "PSA_WANT_ECC_SECP_R1_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_384 + bool "PSA_WANT_ECC_SECP_R1_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_521 + bool "PSA_WANT_ECC_SECP_R1_521" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_2048 + bool "PSA_WANT_DH_RFC7919_2048" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_3072 + bool "PSA_WANT_DH_RFC7919_3072" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_4096 + bool "PSA_WANT_DH_RFC7919_4096" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_6144 + bool "PSA_WANT_DH_RFC7919_6144" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_8192 + bool "PSA_WANT_DH_RFC7919_8192" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DERIVE + bool "PSA_WANT_KEY_TYPE_DERIVE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_PASSWORD + bool "PSA_WANT_KEY_TYPE_PASSWORD" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_PASSWORD_HASH + bool "PSA_WANT_KEY_TYPE_PASSWORD_HASH" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_HMAC + bool "PSA_WANT_KEY_TYPE_HMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_AES + bool "PSA_WANT_KEY_TYPE_AES" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ARIA + bool "PSA_WANT_KEY_TYPE_ARIA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_CAMELLIA + bool "PSA_WANT_KEY_TYPE_CAMELLIA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_CHACHA20 + bool "PSA_WANT_KEY_TYPE_CHACHA20" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DES + bool "PSA_WANT_KEY_TYPE_DES" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY + bool "PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY + bool "PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RAW_DATA + bool "PSA_WANT_KEY_TYPE_RAW_DATA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + bool "PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL endif # MBEDTLS_PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/configs/config-psa.h b/modules/mbedtls/configs/config-psa.h new file mode 100644 index 00000000000000..e0278f761b889e --- /dev/null +++ b/modules/mbedtls/configs/config-psa.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file was automatically generated by create_psa_files.py + * from: ../../../modules/crypto/mbedtls/include/psa/crypto_config.h + * Do not edit it manually. + */ + +#ifndef CONFIG_PSA_H +#define CONFIG_PSA_H + +#if defined(CONFIG_PSA_WANT_ALG_CBC_NO_PADDING) +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CBC_PKCS7) +#define PSA_WANT_ALG_CBC_PKCS7 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CCM) +#define PSA_WANT_ALG_CCM 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CCM_STAR_NO_TAG) +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CMAC) +#define PSA_WANT_ALG_CMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CFB) +#define PSA_WANT_ALG_CFB 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CHACHA20_POLY1305) +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CTR) +#define PSA_WANT_ALG_CTR 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_DETERMINISTIC_ECDSA) +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_ECB_NO_PADDING) +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_ECDH) +#define PSA_WANT_ALG_ECDH 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_FFDH) +#define PSA_WANT_ALG_FFDH 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_JPAKE) +#define PSA_WANT_ALG_JPAKE 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_GCM) +#define PSA_WANT_ALG_GCM 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HKDF) +#define PSA_WANT_ALG_HKDF 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HKDF_EXTRACT) +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HKDF_EXPAND) +#define PSA_WANT_ALG_HKDF_EXPAND 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HMAC) +#define PSA_WANT_ALG_HMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_MD5) +#define PSA_WANT_ALG_MD5 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_OFB) +#define PSA_WANT_ALG_OFB 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_PBKDF2_HMAC) +#define PSA_WANT_ALG_PBKDF2_HMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) +#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RIPEMD160) +#define PSA_WANT_ALG_RIPEMD160 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_OAEP) +#define PSA_WANT_ALG_RSA_OAEP 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_1) +#define PSA_WANT_ALG_SHA_1 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_224) +#define PSA_WANT_ALG_SHA_224 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_256) +#define PSA_WANT_ALG_SHA_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_384) +#define PSA_WANT_ALG_SHA_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_512) +#define PSA_WANT_ALG_SHA_512 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_224) +#define PSA_WANT_ALG_SHA3_224 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_256) +#define PSA_WANT_ALG_SHA3_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_384) +#define PSA_WANT_ALG_SHA3_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_512) +#define PSA_WANT_ALG_SHA3_512 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_STREAM_CIPHER) +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_TLS12_PRF) +#define PSA_WANT_ALG_TLS12_PRF 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_TLS12_PSK_TO_MS) +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_MONTGOMERY_255) +#define PSA_WANT_ECC_MONTGOMERY_255 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_MONTGOMERY_448) +#define PSA_WANT_ECC_MONTGOMERY_448 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_K1_192) +#define PSA_WANT_ECC_SECP_K1_192 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_K1_256) +#define PSA_WANT_ECC_SECP_K1_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_192) +#define PSA_WANT_ECC_SECP_R1_192 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_224) +#define PSA_WANT_ECC_SECP_R1_224 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_256) +#define PSA_WANT_ECC_SECP_R1_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_384) +#define PSA_WANT_ECC_SECP_R1_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_521) +#define PSA_WANT_ECC_SECP_R1_521 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_2048) +#define PSA_WANT_DH_RFC7919_2048 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_3072) +#define PSA_WANT_DH_RFC7919_3072 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_4096) +#define PSA_WANT_DH_RFC7919_4096 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_6144) +#define PSA_WANT_DH_RFC7919_6144 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_8192) +#define PSA_WANT_DH_RFC7919_8192 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DERIVE) +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_PASSWORD) +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_PASSWORD_HASH) +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_HMAC) +#define PSA_WANT_KEY_TYPE_HMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_AES) +#define PSA_WANT_KEY_TYPE_AES 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ARIA) +#define PSA_WANT_KEY_TYPE_ARIA 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_CAMELLIA) +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_CHACHA20) +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DES) +#define PSA_WANT_KEY_TYPE_DES 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) +#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RAW_DATA) +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 +#endif + +#endif /* CONFIG_PSA_H */ diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 6a731d4f61ac7b..2750bab09bc15d 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -489,6 +489,9 @@ #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) #define MBEDTLS_PSA_CRYPTO_CLIENT +#define MBEDTLS_PSA_CRYPTO_CONFIG +#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "config-psa.h" + #endif #if defined(CONFIG_MBEDTLS_TLS_VERSION_1_2) && defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) @@ -507,8 +510,4 @@ #undef MBEDTLS_PSA_CRYPTO_C #endif -#if defined(CONFIG_PSA_WANT_ALG_SHA_256) -#define PSA_WANT_ALG_SHA_256 1 -#endif - #endif /* MBEDTLS_CONFIG_H */ diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index e82e7f95ac14bf..090559e2049238 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -910,6 +910,7 @@ def check_no_undef_outside_kconfig(self, kconf): "OPT", "OPT_0", "PEDO_THS_MIN", + "PSA_H", # This is used in config-psa.h as guard for the header file "REG1", "REG2", "RIMAGE_SIGNING_SCHEMA", # Optional module From d56d855c405ea0c95b92bb477522c235f9a42e27 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1277/1389] mbedtls: add the python script used to generate PSA Kconfigs Since PSA has several different symbols defined and since it's better to keep them aligned with the current MbedTLS release, a python script is used to generate both: - Kconfig.psa - config-psa-generic.h Signed-off-by: Valerio Setti --- modules/mbedtls/create_psa_files.py | 128 ++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100755 modules/mbedtls/create_psa_files.py diff --git a/modules/mbedtls/create_psa_files.py b/modules/mbedtls/create_psa_files.py new file mode 100755 index 00000000000000..fd5d21c9ad9451 --- /dev/null +++ b/modules/mbedtls/create_psa_files.py @@ -0,0 +1,128 @@ +#!/bin/python3 + +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +import re +import os +import sys +import argparse +from typing import List + +SCRIPT_PATH = os.path.dirname(__file__) +INPUT_REL_PATH = os.path.join("..", "..", "..", "modules", "crypto", "mbedtls", + "include", "psa", "crypto_config.h") +INPUT_FILE = os.path.normpath(os.path.join(SCRIPT_PATH, INPUT_REL_PATH)) + +KCONFIG_PATH=os.path.join(SCRIPT_PATH, "Kconfig.psa") +HEADER_PATH=os.path.join(SCRIPT_PATH, "configs", "config-psa.h") + +KCONFIG_HEADER="""\ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# This file was automatically generated by {} +# from: {}. +# Do not edit it manually. + +config MBEDTLS_PSA_CRYPTO_CLIENT + bool + default y + depends on BUILD_WITH_TFM || MBEDTLS_PSA_CRYPTO_C + +if MBEDTLS_PSA_CRYPTO_CLIENT + +config PSA_CRYPTO_ENABLE_ALL + bool "All PSA crypto features" +""".format(os.path.basename(__file__), INPUT_REL_PATH) + +KCONFIG_FOOTER="\nendif # MBEDTLS_PSA_CRYPTO_CLIENT\n" + +H_HEADER="""\ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file was automatically generated by {} + * from: {} + * Do not edit it manually. + */ + +#ifndef CONFIG_PSA_H +#define CONFIG_PSA_H +""".format(os.path.basename(__file__), INPUT_REL_PATH) + +H_FOOTER="\n#endif /* CONFIG_PSA_H */\n" + +def parse_psa_symbols(input_file: str): + symbols = [] + with open(input_file) as file: + content = file.readlines() + for line in content: + res = re.findall(r"^#define *(PSA_WANT_\w+)", line) + if len(res) > 0: + symbols.append(res[0]) + return symbols + +def generate_kconfig_content(symbols: List[str]) -> str: + output = [] + for sym in symbols: + output.append(""" +config {0} +\tbool "{0}" if !MBEDTLS_PROMPTLESS +\tdefault y if PSA_CRYPTO_ENABLE_ALL +""".format(sym)) + + return KCONFIG_HEADER + "".join(output) + KCONFIG_FOOTER + +def generate_header_content(symbols: List[str]) -> str: + output = [] + for sym in symbols: + output.append(""" +#if defined(CONFIG_{0}) +#define {0} 1 +#endif +""".format(sym)) + + return H_HEADER + "".join(output) + H_FOOTER + +def generate_output_file(content: str, file_name: str): + with open(file_name, "wt") as output_file: + output_file.write(content) + +def check_file(content: str, file_name: str): + file_content = "" + with open(file_name) as input_file: + file_content = input_file.read() + if file_content != content: + print() + return False + return True + +def main(): + arg_parser = argparse.ArgumentParser(allow_abbrev = False) + arg_parser.add_argument("--check", action = "store_true", default = False) + args = arg_parser.parse_args() + + check_files = args.check + + psa_symbols = parse_psa_symbols(INPUT_FILE) + kconfig_content = generate_kconfig_content(psa_symbols) + header_content = generate_header_content(psa_symbols) + + if check_files: + if ((not check_file(kconfig_content, KCONFIG_PATH)) or + (not check_file(header_content, HEADER_PATH))): + print("Error: PSA Kconfig and header files do not match with the current" + "version of MbedTLS. Please update them.") + sys.exit(1) + else: + generate_output_file(kconfig_content, KCONFIG_PATH) + generate_output_file(header_content, HEADER_PATH) + + sys.exit(0) + +if __name__ == "__main__": + main() From 8ede83adede053b1dbb9a42767de1085ec15968c Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1278/1389] mbedtls: default enable USE_PSA_CRYPTO when CRYPTO_C Now that support for all PSA_WANT symbols is in place, we can enable MBEDTLS_USE_PSA_CRYPTO when MBEDTLS_PSA_CRYPTO_C is enabled as well. Note: this commit also moves USE_PSA_CRYPTO out of CRYPTO_C dependency in config-tls-generic.h because TLS/DTLS/X509 modules of MbedTLS can rely on *any* implementation of PSA crypto APIs not only the MbedTLS one. TFM is for example an alternative to this. Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.tls-generic | 1 + modules/mbedtls/configs/config-tls-generic.h | 8 ++++---- samples/tfm_integration/psa_crypto/prj.conf | 1 - subsys/bluetooth/mesh/Kconfig | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index eec38e05089fbd..6117424f8a4c99 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -488,6 +488,7 @@ config MBEDTLS_PSA_CRYPTO_C config MBEDTLS_USE_PSA_CRYPTO bool "Use PSA APIs instead of legacy MbedTLS when possible" + default y if MBEDTLS_PSA_CRYPTO_CLIENT help Use PSA APIs instead of legacy MbedTLS functions in TLS/DTLS and other "intermediate" modules such as PK, MD and Cipher. diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 2750bab09bc15d..dc94e3d75f3d72 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -474,10 +474,6 @@ #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_C -#if defined(CONFIG_MBEDTLS_USE_PSA_CRYPTO) -#define MBEDTLS_USE_PSA_CRYPTO -#endif - #if defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_PICOLIBC) #define MBEDTLS_PSA_KEY_SLOT_COUNT 64 #define MBEDTLS_PSA_CRYPTO_STORAGE_C @@ -487,6 +483,10 @@ #endif /* CONFIG_MBEDTLS_PSA_CRYPTO_C */ +#if defined(CONFIG_MBEDTLS_USE_PSA_CRYPTO) +#define MBEDTLS_USE_PSA_CRYPTO +#endif + #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) #define MBEDTLS_PSA_CRYPTO_CLIENT #define MBEDTLS_PSA_CRYPTO_CONFIG diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index f308a5aefaf5b7..a7ac8db8f2e149 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -29,7 +29,6 @@ CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" CONFIG_MBEDTLS_PSA_CRYPTO_C=y -CONFIG_MBEDTLS_USE_PSA_CRYPTO=y CONFIG_MBEDTLS_ENTROPY_ENABLED=y CONFIG_MBEDTLS_ECP_C=y CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 74e377569b3386..88fccf0961cf55 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1349,7 +1349,6 @@ config BT_MESH_USES_MBEDTLS_PSA select MBEDTLS select MBEDTLS_ZEPHYR_ENTROPY select MBEDTLS_PSA_CRYPTO_C - select MBEDTLS_USE_PSA_CRYPTO select MBEDTLS_MAC_CMAC_ENABLED select MBEDTLS_CIPHER_AES_ENABLED select MBEDTLS_AES_ROM_TABLES From 1b578b30c51229bafe263df3eff8e811d1bab6c4 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1279/1389] mbedtls: add new PSA_CRYPTO_CLIENT config Using MBEDTLS_PSA_CRYPTO_CLIENT to guard all PSA_WANT symbols is not completely correct because: 1. the prefix MBEDTLS suggests that it's something related to MbedTLS, while actually PSA APIs can be provided also by other implementations (ex: TFM) 2. there might applications which are willing to use PSA APIs without using MbedTLS at all. For example computing an hash can be as simple as writing psa_hash_compute() and, if the PSA function is provided thorugh TFM, then MbedTLS is not required at all Therefore this commit: - moves MBEDTLS_PSA_CRYPTO_CLIENT to Kconfig.tls-generic since that symbol belongs to MbedTLS - adds a new symbol named PSA_CRYPTO_CLIENT as a generic way to state that there is "some" PSA crypto API provider - let MBEDTLS_PSA_CRYPTO_CLIENT automatically select PSA_CRYPTO_CLIENT, since the former is an implementation of the latter. Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.psa | 11 ++++++----- modules/mbedtls/Kconfig.tls-generic | 6 ++++++ modules/mbedtls/create_psa_files.py | 11 ++++++----- modules/trusted-firmware-m/Kconfig.tfm | 1 + 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa index e6121ed9173b1a..7562032bf3d4ed 100644 --- a/modules/mbedtls/Kconfig.psa +++ b/modules/mbedtls/Kconfig.psa @@ -5,12 +5,13 @@ # from: ../../../modules/crypto/mbedtls/include/psa/crypto_config.h. # Do not edit it manually. -config MBEDTLS_PSA_CRYPTO_CLIENT +config PSA_CRYPTO_CLIENT bool - default y - depends on BUILD_WITH_TFM || MBEDTLS_PSA_CRYPTO_C + help + Promptless symbol to state that there is a PSA crypto API provider + enabled in the system. This allows to select desired PSA_WANT features. -if MBEDTLS_PSA_CRYPTO_CLIENT +if PSA_CRYPTO_CLIENT config PSA_CRYPTO_ENABLE_ALL bool "All PSA crypto features" @@ -351,4 +352,4 @@ config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -endif # MBEDTLS_PSA_CRYPTO_CLIENT +endif # PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 6117424f8a4c99..b3e620d94b9332 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -493,6 +493,12 @@ config MBEDTLS_USE_PSA_CRYPTO Use PSA APIs instead of legacy MbedTLS functions in TLS/DTLS and other "intermediate" modules such as PK, MD and Cipher. +config MBEDTLS_PSA_CRYPTO_CLIENT + bool + default y + depends on BUILD_WITH_TFM || MBEDTLS_PSA_CRYPTO_C + select PSA_CRYPTO_CLIENT + config MBEDTLS_LMS bool "Support LMS signature schemes" depends on MBEDTLS_PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/create_psa_files.py b/modules/mbedtls/create_psa_files.py index fd5d21c9ad9451..fe6d0b79b46555 100755 --- a/modules/mbedtls/create_psa_files.py +++ b/modules/mbedtls/create_psa_files.py @@ -25,18 +25,19 @@ # from: {}. # Do not edit it manually. -config MBEDTLS_PSA_CRYPTO_CLIENT +config PSA_CRYPTO_CLIENT bool - default y - depends on BUILD_WITH_TFM || MBEDTLS_PSA_CRYPTO_C + help + Promptless symbol to state that there is a PSA crypto API provider + enabled in the system. This allows to select desired PSA_WANT features. -if MBEDTLS_PSA_CRYPTO_CLIENT +if PSA_CRYPTO_CLIENT config PSA_CRYPTO_ENABLE_ALL bool "All PSA crypto features" """.format(os.path.basename(__file__), INPUT_REL_PATH) -KCONFIG_FOOTER="\nendif # MBEDTLS_PSA_CRYPTO_CLIENT\n" +KCONFIG_FOOTER="\nendif # PSA_CRYPTO_CLIENT\n" H_HEADER="""\ /* diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 1c11a997cf7ff9..e8f860fa2f6464 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -33,6 +33,7 @@ menuconfig BUILD_WITH_TFM imply INIT_ARCH_HW_AT_BOOT imply ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS imply MBEDTLS + imply PSA_CRYPTO_ENABLE_ALL help When enabled, this option instructs the Zephyr build process to additionally generate a TF-M image for the Secure Execution From ce415568d95cd73c6cac953278a3e35a82a5c1ae Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1280/1389] mbedtls: add new source file from MbedTLS 3.6 release Add "sha3.c" source file that was previously missing from CMakeLists.txt and that has been added in MbedTLS 3.6 release. Signed-off-by: Valerio Setti --- modules/mbedtls/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 30ddce44eb176e..b5eececbc9e36e 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -88,6 +88,7 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha1.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha256.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha512.c + ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha3.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/threading.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/timing.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/version_features.c From e0ce9b5175f8d696e9ca3b550648b7ec848a2ded Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1281/1389] bluetooth: mesh: update BT_MESH_USES_MBEDTLS_PSA selected symbols Instead of selecting legacy MBEDTLS symbols, use corresponding PSA_WANT ones when possible (note: some legacy symbols do not have a PSA correspondance). Signed-off-by: Valerio Setti --- modules/mbedtls/Kconfig.tls-generic | 2 +- subsys/bluetooth/mesh/Kconfig | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index b3e620d94b9332..b692c18e323594 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -105,7 +105,7 @@ config MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED config MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED bool "ECDH-ECDSA based ciphersuite modes" - depends on MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C + depends on (MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C) || (PSA_WANT_ALG_ECDH && PSA_WANT_ALG_ECDSA) config MBEDTLS_ECDSA_DETERMINISTIC bool "Deterministic ECDSA (RFC 6979)" diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 88fccf0961cf55..796982280a882b 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1349,15 +1349,24 @@ config BT_MESH_USES_MBEDTLS_PSA select MBEDTLS select MBEDTLS_ZEPHYR_ENTROPY select MBEDTLS_PSA_CRYPTO_C - select MBEDTLS_MAC_CMAC_ENABLED - select MBEDTLS_CIPHER_AES_ENABLED + select MBEDTLS_USE_PSA_CRYPTO + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE + # Required, otherwise there are missing symbols for PK helpers at link time. + select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + select PSA_WANT_KEY_TYPE_AES select MBEDTLS_AES_ROM_TABLES - select MBEDTLS_CIPHER_CCM_ENABLED - select MBEDTLS_ECP_C - select MBEDTLS_ECDH_C - select MBEDTLS_ECDSA_C + select PSA_WANT_ALG_CCM + select PSA_WANT_KEY_TYPE_HMAC + select PSA_WANT_ALG_HMAC + select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_ECDH + select PSA_WANT_ALG_ECDSA select MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - select MBEDTLS_ECP_DP_SECP256R1_ENABLED + select PSA_WANT_ECC_SECP_R1_256 select MBEDTLS_PK_WRITE_C help Use mbed TLS library to perform crypto operations. Support of From 177a4a821f3280b7b8835b5730f88b7018f7eca6 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1282/1389] test: mbedtls: add custom target to check MbedTLS auto-generated files This commit adds a custom target to tests/crypto/mbedtls in order to verify that MbedTLS auto-generated files are up to date. Signed-off-by: Valerio Setti --- tests/crypto/mbedtls/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/crypto/mbedtls/CMakeLists.txt b/tests/crypto/mbedtls/CMakeLists.txt index 1bbd6b6ddd7d88..7ebdc9d76a9ae9 100644 --- a/tests/crypto/mbedtls/CMakeLists.txt +++ b/tests/crypto/mbedtls/CMakeLists.txt @@ -4,5 +4,17 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(mbedtls) +set(output_file ${PROJECT_BINARY_DIR}/mbedtls-check.timestamp) + +add_custom_command( + COMMENT "Check Mbed TLS auto-generated files" + COMMAND + ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/modules/mbedtls/create_psa_files.py --check + OUTPUT + ${output_file} +) + +add_custom_target(check_mbedtls_auto_generated_files ALL DEPENDS ${output_file}) + FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) From e02e7901fa26c80f85ddc9f4f0cb70c14edb3e41 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1283/1389] Bluetooth: controller: Allow any valid ISO sync receiver BIG handle The BIG handle for an ISO sync receiver is provided by the host. The valid range is [0x00..0xEF], and this requires the controller to allow non-consecutive handle numbering. This means that even if only one sync set is supported, a BIG handle of ex. value 2 must be supported. As the code uses indexing and range checking directly by handle, this needs to be changed. Introducing the handle index, which sequnces the handles such that index = 0 is always the "first handle", regardless of value. Signed-off-by: Morten Priess --- .../bluetooth/controller/ll_sw/lll_sync_iso.h | 2 +- .../ll_sw/nordic/lll/lll_sync_iso.c | 2 +- .../bluetooth/controller/ll_sw/ull_sync_iso.c | 69 +++++++++++++------ .../controller/ll_sw/ull_sync_types.h | 1 + 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h index 4038a04486ec61..8db6c3a31a482c 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync_iso.h @@ -90,7 +90,7 @@ int lll_sync_iso_reset(void); void lll_sync_iso_create_prepare(void *param); void lll_sync_iso_prepare(void *param); -extern uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll); +extern uint8_t ull_sync_iso_lll_index_get(struct lll_sync_iso *lll); extern struct lll_sync_iso_stream *ull_sync_iso_lll_stream_get(uint16_t handle); extern void ll_iso_rx_put(memq_link_t *link, void *rx); extern void ll_rx_sched(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c index fcc37fc52d873f..96b932403aa14a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c @@ -375,7 +375,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) uint32_t overhead; overhead = lll_preempt_calc(ull, (TICKER_ID_SCAN_SYNC_ISO_BASE + - ull_sync_iso_lll_handle_get(lll)), ticks_at_event); + ull_sync_iso_lll_index_get(lll)), ticks_at_event); /* check if preempt to start has changed */ if (overhead) { LL_ASSERT_OVERHEAD(overhead); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index f6c68436b5eb09..41a6d0a3037042 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -52,7 +52,9 @@ static int init_reset(void); static struct ll_sync_iso_set *sync_iso_get(uint8_t handle); +static struct ll_sync_iso_set *sync_iso_alloc(uint8_t handle); static uint8_t sync_iso_handle_get(struct ll_sync_iso_set *sync); +static uint8_t sync_iso_handle_to_index(uint8_t handle); static struct stream *sync_iso_stream_acquire(void); static uint16_t sync_iso_stream_handle_get(struct lll_sync_iso_stream *stream); static void timeout_cleanup(struct ll_sync_iso_set *sync_iso); @@ -89,23 +91,23 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle, int8_t last_index; sync = ull_sync_is_enabled_get(sync_handle); - if (!sync || sync->iso.sync_iso) { + if (!sync) { + return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER; + } + + if (sync->iso.sync_iso) { return BT_HCI_ERR_CMD_DISALLOWED; } sync_iso = sync_iso_get(big_handle); - if (!sync_iso) { - /* Host requested more than supported number of ISO Synchronized - * Receivers. - * Or probably HCI handles where not translated to zero-indexed - * controller handles? - */ - return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; + if (sync_iso) { + /* BIG handle already in use */ + return BT_HCI_ERR_CMD_DISALLOWED; } - /* Check if this ISO already is associated with a Periodic Sync */ - if (sync_iso->sync) { - return BT_HCI_ERR_CMD_DISALLOWED; + sync_iso = sync_iso_alloc(big_handle); + if (!sync_iso) { + return BT_HCI_ERR_INSUFFICIENT_RESOURCES; } /* TODO: Check remaining parameters */ @@ -269,7 +271,8 @@ uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx) } err = ull_ticker_stop_with_mark((TICKER_ID_SCAN_SYNC_ISO_BASE + - big_handle), sync_iso, &sync_iso->lll); + sync_iso_handle_to_index(big_handle)), + sync_iso, &sync_iso->lll); LL_ASSERT_INFO2(err == 0 || err == -EALREADY, big_handle, err); if (err) { return BT_HCI_ERR_CMD_DISALLOWED; @@ -307,9 +310,9 @@ int ull_sync_iso_reset(void) return 0; } -uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll) +uint8_t ull_sync_iso_lll_index_get(struct lll_sync_iso *lll) { - return sync_iso_handle_get(HDR_LLL2ULL(lll)); + return ARRAY_INDEX(ll_sync_iso, HDR_LLL2ULL(lll)); } struct ll_sync_iso_set *ull_sync_iso_by_stream_get(uint16_t handle) @@ -630,7 +633,8 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, handle = sync_iso_handle_get(sync_iso); ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, - (TICKER_ID_SCAN_SYNC_ISO_BASE + handle), + (TICKER_ID_SCAN_SYNC_ISO_BASE + + sync_iso_handle_to_index(handle)), ftr->ticks_anchor - ticks_slot_offset, HAL_TICKER_US_TO_TICKS(sync_iso_offset_us), HAL_TICKER_US_TO_TICKS(interval_us), @@ -762,7 +766,7 @@ void ull_sync_iso_done(struct node_rx_event_done *done) ticker_status = ticker_update(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, (TICKER_ID_SCAN_SYNC_ISO_BASE + - handle), + sync_iso_handle_to_index(handle)), ticks_drift_plus, ticks_drift_minus, 0U, 0U, lazy, force, @@ -796,7 +800,8 @@ void ull_sync_iso_done_terminate(struct node_rx_event_done *done) /* Stop Sync ISO Ticker */ handle = sync_iso_handle_get(sync_iso); ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, - (TICKER_ID_SCAN_SYNC_ISO_BASE + handle), + (TICKER_ID_SCAN_SYNC_ISO_BASE + + sync_iso_handle_to_index(handle)), ticker_stop_op_cb, (void *)sync_iso); LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); @@ -846,16 +851,35 @@ static int init_reset(void) static struct ll_sync_iso_set *sync_iso_get(uint8_t handle) { - if (handle >= CONFIG_BT_CTLR_SCAN_SYNC_ISO_SET) { - return NULL; + for (uint8_t idx = 0; idx < CONFIG_BT_CTLR_SCAN_SYNC_ISO_SET; idx++) { + if (ll_sync_iso[idx].sync && ll_sync_iso[idx].big_handle == handle) { + return &ll_sync_iso[idx]; + } + } + + return NULL; +} + +static struct ll_sync_iso_set *sync_iso_alloc(uint8_t handle) +{ + for (uint8_t idx = 0; idx < CONFIG_BT_CTLR_SCAN_SYNC_ISO_SET; idx++) { + if (!ll_sync_iso[idx].sync) { + ll_sync_iso[idx].big_handle = handle; + return &ll_sync_iso[idx]; + } } - return &ll_sync_iso[handle]; + return NULL; } static uint8_t sync_iso_handle_get(struct ll_sync_iso_set *sync) { - return mem_index_get(sync, ll_sync_iso, sizeof(*sync)); + return sync->big_handle; +} + +static uint8_t sync_iso_handle_to_index(uint8_t handle) +{ + return ARRAY_INDEX(ll_sync_iso, sync_iso_get(handle)); } static struct stream *sync_iso_stream_acquire(void) @@ -890,7 +914,8 @@ static void timeout_cleanup(struct ll_sync_iso_set *sync_iso) /* Stop Sync ISO Ticker */ handle = sync_iso_handle_get(sync_iso); ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, - (TICKER_ID_SCAN_SYNC_ISO_BASE + handle), + (TICKER_ID_SCAN_SYNC_ISO_BASE + + sync_iso_handle_to_index(handle)), ticker_stop_op_cb, (void *)sync_iso); LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || (ret == TICKER_STATUS_BUSY)); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h index 38a92f40c9ec2e..b4ecfd52ca27b9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_types.h @@ -115,6 +115,7 @@ struct ll_sync_iso_set { uint16_t timeout; uint16_t volatile timeout_reload; /* Non-zero when sync established */ uint16_t timeout_expire; /* timeout countdown */ + uint8_t big_handle; /* Encryption */ uint8_t gltk[16]; From ff628df214cd2836775b65ee07029c2c83f491ce Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1284/1389] spi_nor: remove unneeded enter_dpd() at end of spi_nor_configure() This block of code was in the original commit that added CONFIG_SPI_NOR_IDLE_IN_DPD but later modifications added acquire_device() and release_device() calls earlier in spi_nor_configure() and the release_device() function will have already done the enter_dpd(). Signed-off-by: Mike J. Chen --- drivers/flash/spi_nor.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index ccf492f0255c36..f0b4df33590f47 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -1414,11 +1414,6 @@ static int spi_nor_configure(const struct device *dev) } #endif /* ANY_INST_HAS_MXICY_MX25R_POWER_MODE */ - if (IS_ENABLED(CONFIG_SPI_NOR_IDLE_IN_DPD) - && (enter_dpd(dev) != 0)) { - return -ENODEV; - } - return 0; } From 03d6c92d4a0e397ae6601330a062fe286618cdaa Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1285/1389] codeowners: add sensor veaa-x-3 Add @jeppenodgaard and @MaureenHelm as veaa-x-3 codeowners. Signed-off-by: Jeppe Odgaard --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 60ce1a2533a623..d1940b8d606cac 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -333,6 +333,7 @@ /drivers/sensor/qdec_stm32/ @valeriosetti /drivers/sensor/rpi_pico_temp/ @soburi /drivers/sensor/st*/ @avisconti +/drivers/sensor/veaa_x_3/ @jeppenodgaard @MaureenHelm /drivers/sensor/ene_tack_kb1200/ @ene-steven /drivers/serial/*b91* @andy-liu-telink /drivers/serial/uart_altera_jtag.c @nashif @gohshunjing From aedbae2077b66b338d67bd834202159f54453bda Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1286/1389] mbedtls: reduce heap usage when building PSA crypto By default PSA crypto library copies all the buffers that are passed in into the heap before further processing them. This is required when the PSA crypto library is on the secure side and it accepts buffers from a non-secure code. However this case in Zephyr is already handled by TF-M, so when the PSA crypto library is built (CONFIG_MBEDTLS_PSA_CRYPTO_C) then it will be on the non-secure side. Therefore this malloc copy is useless and it consumes heap memory. Setting MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS at Mbed TLS build time helps in removing this mechanism and it saves heap memory. Signed-off-by: Valerio Setti --- modules/mbedtls/configs/config-tls-generic.h | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index dc94e3d75f3d72..45bc81f35f20c8 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -473,6 +473,7 @@ #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_C +#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS #if defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_PICOLIBC) #define MBEDTLS_PSA_KEY_SLOT_COUNT 64 From 6f8d9fd5c3a85cde9cb8cc25f19a96784563ca3e Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1287/1389] doc: requirements: Add pyserial Since 7eaca455faf6ff8d9a92c4392da281dab08d0c2b, pyserial is required for building docs because `DeviceAdapter` from the `pytest-twister-harness` plugin, which is imported by autodoc, now depends on it. Signed-off-by: Stephanos Ioannidis --- doc/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index bb12e241930e5a..55cf8de6297594 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -15,8 +15,9 @@ sphinx-sitemap PyYAML>=6.0 pykwalify -# Used by pytest-twister-harness plugin +# Used by pytest-twister-harness plugin (imported by autodoc) pytest +pyserial # Doxygen doxmlparser doxmlparser From 3e8f2785e71a796c05bff324ed44889df673a71c Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1288/1389] tests: uoscore: Set necessary PSA options Set necessary psa options to the test execution. Signed-off-by: Flavio Ceolin --- tests/modules/uoscore/prj.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/modules/uoscore/prj.conf b/tests/modules/uoscore/prj.conf index 0282e87b3bb7fd..af103ceb24f75b 100644 --- a/tests/modules/uoscore/prj.conf +++ b/tests/modules/uoscore/prj.conf @@ -12,3 +12,13 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=2048 CONFIG_MBEDTLS_ZEPHYR_ENTROPY=y + +# PSA Crypto options + +CONFIG_PSA_WANT_ALG_CCM=y +CONFIG_PSA_WANT_ALG_HMAC=y + +CONFIG_PSA_WANT_KEY_TYPE_HMAC=y +CONFIG_PSA_WANT_KEY_TYPE_AES=y +CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY=y +CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y From 50f622e42b8678188249b90b0cfb78a0a5e67dbb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1289/1389] tests: Bluetooth: tester: Fix assert in OTS MCS OTS support doesn't implement OTS checksum and if this is globally enabled assert is triggered. [00:00:03.409,484] bttester_gap: set_io_cap: io_cap: 0 ASSERTION FAIL [ots_init->cb->obj_cal_checksum] @ WEST_TOPDIR/zephyr/subsys/bluetooth/services/ots/ots.c:476 Callback for object calculate checksum is not set This should be reverted when Zephyr issue #72471 is fixed. Signed-off-by: Szymon Janc --- tests/bluetooth/tester/overlay-le-audio.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/bluetooth/tester/overlay-le-audio.conf b/tests/bluetooth/tester/overlay-le-audio.conf index 6b0186e55d8595..4954b75fd9b07e 100644 --- a/tests/bluetooth/tester/overlay-le-audio.conf +++ b/tests/bluetooth/tester/overlay-le-audio.conf @@ -134,6 +134,8 @@ CONFIG_BT_MPL_OBJECTS=y CONFIG_BT_OTS=y CONFIG_BT_OTS_SECONDARY_SVC=y CONFIG_BT_OTS_MAX_OBJ_CNT=0x30 +#disable OTS checksum support until 72471 is fixed +CONFIG_BT_OTS_OACP_CHECKSUM_SUPPORT=n CONFIG_BT_MCS=y CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL=y CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS=y From 3415941579400144c8417fc74503f1dd2866eea3 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:39:36 +0200 Subject: [PATCH 1290/1389] i2c: nrfx_twi_rtio: Establish proper namespacing in driver To clearly distinguish between common code and RTIO-only code on nrfx_twi and nrfx_twi_rtio. Signed-off-by: Luis Ubieda --- drivers/i2c/i2c_nrfx_twi_rtio.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/i2c_nrfx_twi_rtio.c b/drivers/i2c/i2c_nrfx_twi_rtio.c index cf2e4c06312d97..96977c134b7004 100644 --- a/drivers/i2c/i2c_nrfx_twi_rtio.c +++ b/drivers/i2c/i2c_nrfx_twi_rtio.c @@ -32,9 +32,9 @@ BUILD_ASSERT( offsetof(struct i2c_nrfx_twi_common_data, dev_config) ); -static void i2c_nrfx_twi_complete(const struct device *dev, int status); +static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status); -static bool i2c_nrfx_twi_msg_start(const struct device *dev, uint8_t flags, +static bool i2c_nrfx_twi_rtio_msg_start(const struct device *dev, uint8_t flags, uint8_t *buf, size_t buf_len, uint16_t i2c_addr) { const struct i2c_nrfx_twi_config *config = dev->config; @@ -59,7 +59,7 @@ static bool i2c_nrfx_twi_msg_start(const struct device *dev, uint8_t flags, return false; } -static bool i2c_nrfx_twi_start(const struct device *dev) +static bool i2c_nrfx_twi_rtio_start(const struct device *dev) { struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data; struct i2c_rtio *ctx = dev_data->ctx; @@ -68,13 +68,13 @@ static bool i2c_nrfx_twi_start(const struct device *dev) switch (sqe->op) { case RTIO_OP_RX: - return i2c_nrfx_twi_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags, + return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags, sqe->buf, sqe->buf_len, dt_spec->addr); case RTIO_OP_TINY_TX: - return i2c_nrfx_twi_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, + return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, sqe->tiny_buf, sqe->tiny_buf_len, dt_spec->addr); case RTIO_OP_TX: - return i2c_nrfx_twi_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, + return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, sqe->buf, sqe->buf_len, dt_spec->addr); case RTIO_OP_I2C_CONFIGURE: (void)i2c_nrfx_twi_configure(dev, sqe->i2c_config); @@ -88,7 +88,7 @@ static bool i2c_nrfx_twi_start(const struct device *dev) } } -static void i2c_nrfx_twi_complete(const struct device *dev, int status) +static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status) { /** Finalize if there are no more pending xfers */ const struct i2c_nrfx_twi_config *config = dev->config; @@ -96,14 +96,14 @@ static void i2c_nrfx_twi_complete(const struct device *dev, int status) struct i2c_rtio *const ctx = data->ctx; if (i2c_rtio_complete(ctx, status)) { - (void)i2c_nrfx_twi_start(dev); + (void)i2c_nrfx_twi_rtio_start(dev); } else { nrfx_twi_disable(&config->twi); data->twi_enabled = false; } } -static int i2c_nrfx_twi_transfer(const struct device *dev, +static int i2c_nrfx_twi_rtio_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { @@ -122,24 +122,24 @@ static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) status = -EIO; } - i2c_nrfx_twi_complete(dev, status); + i2c_nrfx_twi_rtio_complete(dev, status); } -static void i2c_nrfx_twi_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_seq) +static void i2c_nrfx_twi_rtio_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_seq) { struct i2c_nrfx_twi_rtio_data *data = dev->data; struct i2c_rtio *const ctx = data->ctx; if (i2c_rtio_submit(ctx, iodev_seq)) { - (void)i2c_nrfx_twi_start(dev); + (void)i2c_nrfx_twi_rtio_start(dev); } } -static const struct i2c_driver_api i2c_nrfx_twi_driver_api = { +static const struct i2c_driver_api i2c_nrfx_twi_rtio_driver_api = { .configure = i2c_nrfx_twi_configure, - .transfer = i2c_nrfx_twi_transfer, + .transfer = i2c_nrfx_twi_rtio_transfer, .recover_bus = i2c_nrfx_twi_recover_bus, - .iodev_submit = i2c_nrfx_twi_submit, + .iodev_submit = i2c_nrfx_twi_rtio_submit, }; #define I2C_NRFX_TWI_RTIO_DEVICE(idx) \ @@ -186,7 +186,7 @@ static const struct i2c_driver_api i2c_nrfx_twi_driver_api = { &twi_##idx##z_config, \ POST_KERNEL, \ CONFIG_I2C_INIT_PRIORITY, \ - &i2c_nrfx_twi_driver_api) + &i2c_nrfx_twi_rtio_driver_api) #ifdef CONFIG_HAS_HW_NRF_TWI0 I2C_NRFX_TWI_RTIO_DEVICE(0); From fe4b6799e1af4faa40d20535fb26b208fba763bb Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1291/1389] drivers: i2c: nrfx_twi_rtio: Minor indentation fixes Not necessarily related to the namespacing changes, but just establishing proper indentation formatting throughout the whole file. Signed-off-by: Luis Ubieda --- drivers/i2c/i2c_nrfx_twi_rtio.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/i2c_nrfx_twi_rtio.c b/drivers/i2c/i2c_nrfx_twi_rtio.c index 96977c134b7004..7f5d5becf04720 100644 --- a/drivers/i2c/i2c_nrfx_twi_rtio.c +++ b/drivers/i2c/i2c_nrfx_twi_rtio.c @@ -35,7 +35,7 @@ BUILD_ASSERT( static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status); static bool i2c_nrfx_twi_rtio_msg_start(const struct device *dev, uint8_t flags, - uint8_t *buf, size_t buf_len, uint16_t i2c_addr) + uint8_t *buf, size_t buf_len, uint16_t i2c_addr) { const struct i2c_nrfx_twi_config *config = dev->config; struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data; @@ -69,13 +69,13 @@ static bool i2c_nrfx_twi_rtio_start(const struct device *dev) switch (sqe->op) { case RTIO_OP_RX: return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags, - sqe->buf, sqe->buf_len, dt_spec->addr); + sqe->buf, sqe->buf_len, dt_spec->addr); case RTIO_OP_TINY_TX: return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, - sqe->tiny_buf, sqe->tiny_buf_len, dt_spec->addr); + sqe->tiny_buf, sqe->tiny_buf_len, dt_spec->addr); case RTIO_OP_TX: return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, - sqe->buf, sqe->buf_len, dt_spec->addr); + sqe->buf, sqe->buf_len, dt_spec->addr); case RTIO_OP_I2C_CONFIGURE: (void)i2c_nrfx_twi_configure(dev, sqe->i2c_config); return false; @@ -103,9 +103,8 @@ static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status) } } -static int i2c_nrfx_twi_rtio_transfer(const struct device *dev, - struct i2c_msg *msgs, - uint8_t num_msgs, uint16_t addr) +static int i2c_nrfx_twi_rtio_transfer(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs, uint16_t addr) { struct i2c_rtio *const ctx = ((struct i2c_nrfx_twi_rtio_data *) dev->data)->ctx; From d5fd1d65a9fc374776dcb0320ee5098ac424c4fd Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1292/1389] samples: Bluetooth: Fix incorrect comments about adv sets Several places we simply had /* Create a non-connectable non-scannable advertising set */ regardless of the type of advertising it was. Modified the comment to omit the scannable part and corrected the connectable part. Signed-off-by: Emil Gydesen --- samples/bluetooth/broadcast_audio_sink/src/main.c | 2 +- samples/bluetooth/broadcast_audio_source/src/main.c | 2 +- .../bluetooth/broadcaster_multiple/src/broadcaster_multiple.c | 2 +- samples/bluetooth/extended_adv/advertiser/src/main.c | 2 +- samples/bluetooth/hap_ha/src/main.c | 2 +- samples/bluetooth/iso_broadcast/src/main.c | 2 +- samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c | 2 +- samples/bluetooth/periodic_adv/src/main.c | 2 +- samples/bluetooth/periodic_adv_conn/src/main.c | 2 +- samples/bluetooth/periodic_adv_rsp/src/main.c | 2 +- samples/bluetooth/public_broadcast_source/src/main.c | 2 +- samples/bluetooth/tmap_bms/src/cap_initiator.c | 2 +- samples/bluetooth/unicast_audio_server/src/main.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c index 860434d428af42..38f9f546078377 100644 --- a/samples/bluetooth/broadcast_audio_sink/src/main.c +++ b/samples/bluetooth/broadcast_audio_sink/src/main.c @@ -1393,7 +1393,7 @@ static int start_adv(void) }; int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &ext_adv); if (err != 0) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/broadcast_audio_source/src/main.c b/samples/bluetooth/broadcast_audio_source/src/main.c index e6f2c85b8b4968..dbaffb0c2ffec9 100644 --- a/samples/bluetooth/broadcast_audio_source/src/main.c +++ b/samples/bluetooth/broadcast_audio_source/src/main.c @@ -493,7 +493,7 @@ int main(void) struct bt_data per_ad; uint32_t broadcast_id; - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CUSTOM, NULL, &adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", diff --git a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c index 8da6984ee55d6b..f2e7127b406bd6 100644 --- a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c +++ b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c @@ -88,7 +88,7 @@ int broadcaster_multiple(void) /* Use advertising set instance index as SID */ adv_param.sid = index; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(&adv_param, NULL, &adv[index]); if (err) { printk("Failed to create advertising set %d (err %d)\n", diff --git a/samples/bluetooth/extended_adv/advertiser/src/main.c b/samples/bluetooth/extended_adv/advertiser/src/main.c index be51694fd1ad25..efb8dbc3e1fdee 100644 --- a/samples/bluetooth/extended_adv/advertiser/src/main.c +++ b/samples/bluetooth/extended_adv/advertiser/src/main.c @@ -102,7 +102,7 @@ int main(void) return err; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/hap_ha/src/main.c b/samples/bluetooth/hap_ha/src/main.c index 205feceb0b8496..586ed60046919a 100644 --- a/samples/bluetooth/hap_ha/src/main.c +++ b/samples/bluetooth/hap_ha/src/main.c @@ -100,7 +100,7 @@ static void adv_work_handler(struct k_work *work) int err; if (ext_adv == NULL) { - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, &adv_cb, &ext_adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/iso_broadcast/src/main.c b/samples/bluetooth/iso_broadcast/src/main.c index e0ff7dd306e089..85460d10fdd5ce 100644 --- a/samples/bluetooth/iso_broadcast/src/main.c +++ b/samples/bluetooth/iso_broadcast/src/main.c @@ -105,7 +105,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c index 1040f0cd214831..94f334ff54d84e 100644 --- a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c +++ b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c @@ -617,7 +617,7 @@ static int create_big(struct bt_le_ext_adv **adv, struct bt_iso_big **big) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ LOG_INF("Creating Extended Advertising set"); err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); if (err != 0) { diff --git a/samples/bluetooth/periodic_adv/src/main.c b/samples/bluetooth/periodic_adv/src/main.c index 9b584966ce77f9..a927c82e16c2b9 100644 --- a/samples/bluetooth/periodic_adv/src/main.c +++ b/samples/bluetooth/periodic_adv/src/main.c @@ -30,7 +30,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/periodic_adv_conn/src/main.c b/samples/bluetooth/periodic_adv_conn/src/main.c index 63818ddbeea5bb..1bfcc55977af06 100644 --- a/samples/bluetooth/periodic_adv_conn/src/main.c +++ b/samples/bluetooth/periodic_adv_conn/src/main.c @@ -181,7 +181,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, &adv_cb, &pawr_adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/periodic_adv_rsp/src/main.c b/samples/bluetooth/periodic_adv_rsp/src/main.c index 6764b023a5ad20..b88c724a2225a1 100644 --- a/samples/bluetooth/periodic_adv_rsp/src/main.c +++ b/samples/bluetooth/periodic_adv_rsp/src/main.c @@ -266,7 +266,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, &adv_cb, &pawr_adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/public_broadcast_source/src/main.c b/samples/bluetooth/public_broadcast_source/src/main.c index 5ffb94d785f0d1..f4dab65bbb2913 100644 --- a/samples/bluetooth/public_broadcast_source/src/main.c +++ b/samples/bluetooth/public_broadcast_source/src/main.c @@ -127,7 +127,7 @@ static int setup_extended_adv(struct bt_le_ext_adv **adv) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); diff --git a/samples/bluetooth/tmap_bms/src/cap_initiator.c b/samples/bluetooth/tmap_bms/src/cap_initiator.c index 2c0019e234c215..3cce613dd9863e 100644 --- a/samples/bluetooth/tmap_bms/src/cap_initiator.c +++ b/samples/bluetooth/tmap_bms/src/cap_initiator.c @@ -115,7 +115,7 @@ static int setup_extended_adv(struct bt_le_ext_adv **adv) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); diff --git a/samples/bluetooth/unicast_audio_server/src/main.c b/samples/bluetooth/unicast_audio_server/src/main.c index db2a76fbab60fa..6a39afb6879a72 100644 --- a/samples/bluetooth/unicast_audio_server/src/main.c +++ b/samples/bluetooth/unicast_audio_server/src/main.c @@ -750,7 +750,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); From d2589ffccfc2628bcf64d07af68132f612b4ba52 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1293/1389] tests: Bluetooth: Fix incorrect comments about adv sets Several places we simply had /* Create a non-connectable non-scannable advertising set */ regardless of the type of advertising it was. Modified the comment to omit the scannable part and corrected the connectable part. Signed-off-by: Emil Gydesen --- tests/bsim/bluetooth/audio/src/bap_bass_broadcaster_test.c | 2 +- tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c | 2 +- tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c | 2 +- tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c | 2 +- tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c | 2 +- tests/bsim/bluetooth/audio/src/gmap_ugg_test.c | 2 +- .../bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c | 2 +- tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/bsim/bluetooth/audio/src/bap_bass_broadcaster_test.c b/tests/bsim/bluetooth/audio/src/bap_bass_broadcaster_test.c index 782195e3bce2cb..468946f5a5b4fc 100644 --- a/tests/bsim/bluetooth/audio/src/bap_bass_broadcaster_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_bass_broadcaster_test.c @@ -31,7 +31,7 @@ static void test_main(void) printk("Bluetooth initialized\n"); - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, &adv); if (err) { FAIL("Failed to create advertising set (err %d)\n", err); diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c index 7919b4afcc954c..cabd365ab5d00b 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c @@ -898,7 +898,7 @@ static void test_start_adv(void) }; int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &ext_adv); if (err != 0) { FAIL("Failed to create advertising set (err %d)\n", err); diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c index cc0f0a5fc1bc91..6aa261cb3307c2 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c @@ -221,7 +221,7 @@ static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_ uint32_t broadcast_id; int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(&adv_param, NULL, adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c index 90e201b135263b..57dc3ac2dbc0a1 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_server_test.c @@ -490,7 +490,7 @@ static void init(void) &stream_ops); } - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &ext_adv); if (err != 0) { FAIL("Failed to create advertising set (err %d)\n", err); diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c index 34b172ad8ab93c..215c3a41a4c015 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c @@ -184,7 +184,7 @@ static void setup_extended_adv(struct bt_le_ext_adv **adv) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CUSTOM, NULL, adv); if (err != 0) { FAIL("Unable to create extended advertising set: %d\n", err); diff --git a/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c b/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c index 1d686a31016e5d..b2ca57556ce2ae 100644 --- a/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c +++ b/tests/bsim/bluetooth/audio/src/gmap_ugg_test.c @@ -1006,7 +1006,7 @@ static void setup_extended_adv(struct bt_le_ext_adv **adv) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CUSTOM, NULL, adv); if (err != 0) { FAIL("Unable to create extended advertising set: %d\n", err); diff --git a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c index fb5cf85e6b6bc4..b445d8d99faeea 100644 --- a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c +++ b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c @@ -216,7 +216,7 @@ static int setup_extended_adv(struct bt_le_ext_adv **adv) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); diff --git a/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c b/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c index 165b6add6838ce..e54412c55b0ca3 100644 --- a/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c +++ b/tests/bsim/bluetooth/host/iso/bis/src/bis_broadcaster.c @@ -155,7 +155,7 @@ static void create_ext_adv(struct bt_le_ext_adv **adv) LOG_INF("Creating extended advertising set with periodic advertising"); - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); TEST_ASSERT(err == 0, "Unable to create extended advertising set: %d", err); From e4a1555dea4b8b02c015b08b30876112337f0fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1294/1389] modules: hal_nordic: nrfx_glue: Remove NRFX_GPIOTE_CHANNELS_USED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This definition is no longer supported by the nrfx_gpiote driver (since nrfx 3.2.0, reserved channels need to be defined per GPIOTE instance), so remove it to not mislead users. Signed-off-by: Andrzej Głąbek --- modules/hal_nordic/nrfx/nrfx_glue.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 15a1f076063d2b..6b470c77733ce3 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -334,9 +334,6 @@ void nrfx_busy_wait(uint32_t usec_to_wait); NRFX_PPI_GROUPS_USED_BY_802154_DRV | \ NRFX_PPI_GROUPS_USED_BY_MPSL) -/** @brief Bitmask that defines GPIOTE channels that are reserved for use outside of the nrfx library. */ -#define NRFX_GPIOTE_CHANNELS_USED NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR - #if defined(CONFIG_BT_CTLR) /* * The enabled Bluetooth controller subsystem is responsible for providing @@ -348,11 +345,9 @@ void nrfx_busy_wait(uint32_t usec_to_wait); #include #define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS #define NRFX_PPI_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS -#define NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_GPIOTE_CHANNELS #else #define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR 0 #define NRFX_PPI_GROUPS_USED_BY_BT_CTLR 0 -#define NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR 0 #endif #if defined(CONFIG_NRF_802154_RADIO_DRIVER) From c87d63843445d2bbfe8b1a210d05c32c2c79c3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1295/1389] Bluetooth: Controller: nrf5: Allocate GPIOTE channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allocate the GPIOTE channels that the Bluetooth Controller needs to use with the dedicated function provided by the nrfx_gpiote driver instead of using hard-coded indexes of these channels, as now, when the driver supports multiple GPIOTE instances, it would be much more difficult to properly inform the driver which channels should be reserved. Signed-off-by: Andrzej Głąbek --- .../nrf5/nrfx_glue/bt_ctlr_used_resources.h | 19 ---- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 82 +++++++++++++++-- .../ll_sw/nordic/hal/nrf5/radio/radio.h | 2 + .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 91 ------------------- .../hal/nrf5/radio/radio_nrf5_dppi_gpiote.h | 75 +++++++++++++++ .../nordic/hal/nrf5/radio/radio_nrf5_fem.h | 4 +- .../nordic/hal/nrf5/radio/radio_nrf5_ppi.h | 47 ---------- .../hal/nrf5/radio/radio_nrf5_ppi_gpiote.h | 53 +++++++++++ .../controller/ll_sw/nordic/lll/lll.c | 13 +++ 9 files changed, 219 insertions(+), 167 deletions(-) create mode 100644 subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_gpiote.h create mode 100644 subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_gpiote.h diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/nrfx_glue/bt_ctlr_used_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/nrfx_glue/bt_ctlr_used_resources.h index b19abb3dfbb31d..b40e14f516f85d 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/nrfx_glue/bt_ctlr_used_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/nrfx_glue/bt_ctlr_used_resources.h @@ -18,25 +18,6 @@ #include "../radio/radio_nrf5_ppi_resources.h" #endif -#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || \ - defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) -#define HAL_PALNA_GPIOTE_CHAN 0 -#define HAL_PALNA_GPIOTE_MASK BIT(HAL_PALNA_GPIOTE_CHAN) -#else -#define HAL_PALNA_GPIOTE_MASK 0 -#endif - -#if defined(HAL_RADIO_FEM_IS_NRF21540) -#define HAL_PDN_GPIOTE_CHAN 1 -#define HAL_CSN_GPIOTE_CHAN 2 -#define HAL_PDN_CSN_GPIOTE_MASK (BIT(HAL_PDN_GPIOTE_CHAN) | BIT(HAL_CSN_GPIOTE_CHAN)) -#else -#define HAL_PDN_CSN_GPIOTE_MASK 0 -#endif - -/* Mask with all GPIOTE channels used by the bluetooth controller. */ -#define BT_CTLR_USED_GPIOTE_CHANNELS (HAL_PALNA_GPIOTE_MASK | HAL_PDN_CSN_GPIOTE_MASK) - /* Mask with all (D)PPI channels used by the bluetooth controller. */ #define BT_CTLR_USED_PPI_CHANNELS \ (BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI) | \ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 9d5357fba8b27b..4988276ffc91d5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "util/mem.h" @@ -67,6 +68,33 @@ BUILD_ASSERT(!HAL_RADIO_GPIO_LNA_OFFSET_MISSING, HAL_RADIO_GPIO_LNA_OFFSET_PROP_NAME); #endif /* FEM_NODE */ +#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) +static const nrfx_gpiote_t gpiote_palna = NRFX_GPIOTE_INSTANCE( + NRF_DT_GPIOTE_INST(FEM_NODE, HAL_RADIO_GPIO_PA_PROP)); +static uint8_t gpiote_ch_palna; + +BUILD_ASSERT(NRF_DT_GPIOTE_INST(FEM_NODE, HAL_RADIO_GPIO_PA_PROP) == + NRF_DT_GPIOTE_INST(FEM_NODE, HAL_RADIO_GPIO_LNA_PROP), + HAL_RADIO_GPIO_PA_PROP_NAME " and " HAL_RADIO_GPIO_LNA_PROP_NAME + " GPIOs must use the same GPIOTE instance."); +#endif + +#if defined(HAL_RADIO_FEM_IS_NRF21540) +static const nrfx_gpiote_t gpiote_pdn = NRFX_GPIOTE_INSTANCE( + NRF_DT_GPIOTE_INST(FEM_NODE, pdn_gpios)); +static uint8_t gpiote_ch_pdn; +static const nrfx_gpiote_t gpiote_csn = NRFX_GPIOTE_INSTANCE( + NRF_DT_GPIOTE_INST(DT_BUS(FEM_SPI_DEV_NODE), cs_gpios)); +static uint8_t gpiote_ch_csn; +#endif + +/* These headers require the above gpiote-related variables to be declared. */ +#if defined(PPI_PRESENT) +#include "radio_nrf5_ppi_gpiote.h" +#elif defined(DPPI_PRESENT) +#include "radio_nrf5_dppi_gpiote.h" +#endif + /* * "Manual" conversions of devicetree values to register bits. We * can't use the Zephyr GPIO API here, so we need this extra @@ -1548,10 +1576,48 @@ uint32_t radio_tmr_sample_get(void) #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || \ defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) +int radio_gpio_pa_lna_init(void) +{ +#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) + if (nrfx_gpiote_channel_alloc(&gpiote_palna, &gpiote_ch_palna) != NRFX_SUCCESS) { + return -ENOMEM; + } +#endif + +#if defined(NRF_GPIO_PDN_PIN) + if (nrfx_gpiote_channel_alloc(&gpiote_pdn, &gpiote_ch_pdn) != NRFX_SUCCESS) { + return -ENOMEM; + } +#endif + +#if defined(NRF_GPIO_CSN_PIN) + if (nrfx_gpiote_channel_alloc(&gpiote_csn, &gpiote_ch_csn) != NRFX_SUCCESS) { + return -ENOMEM; + } +#endif + + return 0; +} + +void radio_gpio_pa_lna_deinit(void) +{ +#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) + (void)nrfx_gpiote_channel_free(&gpiote_palna, gpiote_ch_palna); +#endif + +#if defined(NRF_GPIO_PDN_PIN) + (void)nrfx_gpiote_channel_free(&gpiote_pdn, gpiote_ch_pdn); +#endif + +#if defined(NRF_GPIO_CSN_PIN) + (void)nrfx_gpiote_channel_free(&gpiote_csn, gpiote_ch_csn); +#endif +} + #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) void radio_gpio_pa_setup(void) { - NRF_GPIOTE->CONFIG[HAL_PALNA_GPIOTE_CHAN] = + gpiote_palna.p_reg->CONFIG[gpiote_ch_palna] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | (NRF_GPIO_PA_PSEL << @@ -1572,7 +1638,7 @@ void radio_gpio_pa_setup(void) #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) void radio_gpio_lna_setup(void) { - NRF_GPIOTE->CONFIG[HAL_PALNA_GPIOTE_CHAN] = + gpiote_palna.p_reg->CONFIG[gpiote_ch_palna] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | (NRF_GPIO_LNA_PSEL << @@ -1593,7 +1659,7 @@ void radio_gpio_pdn_setup(void) { /* Note: the pdn-gpios property is optional. */ #if defined(NRF_GPIO_PDN) - NRF_GPIOTE->CONFIG[HAL_PDN_GPIOTE_CHAN] = + gpiote_pdn.p_reg->CONFIG[gpiote_ch_pdn] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | (NRF_GPIO_PDN_PSEL << @@ -1609,7 +1675,7 @@ void radio_gpio_csn_setup(void) { /* Note: the spi-if property is optional. */ #if defined(NRF_GPIO_CSN_PIN) - NRF_GPIOTE->CONFIG[HAL_CSN_GPIOTE_CHAN] = + gpiote_csn.p_reg->CONFIG[gpiote_ch_csn] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | (NRF_GPIO_CSN_PSEL << @@ -1662,13 +1728,13 @@ void radio_gpio_pa_lna_disable(void) BIT(HAL_DISABLE_PALNA_PPI) | BIT(HAL_ENABLE_FEM_PPI) | BIT(HAL_DISABLE_FEM_PPI)); - NRF_GPIOTE->CONFIG[HAL_PALNA_GPIOTE_CHAN] = 0; - NRF_GPIOTE->CONFIG[HAL_PDN_GPIOTE_CHAN] = 0; - NRF_GPIOTE->CONFIG[HAL_CSN_GPIOTE_CHAN] = 0; + gpiote_palna.p_reg->CONFIG[gpiote_ch_palna] = 0; + gpiote_pdn.p_reg->CONFIG[gpiote_ch_pdn] = 0; + gpiote_csn.p_reg->CONFIG[gpiote_ch_csn] = 0; #else hal_radio_nrf_ppi_channels_disable(BIT(HAL_ENABLE_PALNA_PPI) | BIT(HAL_DISABLE_PALNA_PPI)); - NRF_GPIOTE->CONFIG[HAL_PALNA_GPIOTE_CHAN] = 0; + gpiote_palna.p_reg->CONFIG[gpiote_ch_palna] = 0; #endif } #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN || HAL_RADIO_GPIO_HAVE_LNA_PIN */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h index fc355af1edca6e..fbc79906a2c404 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h @@ -156,6 +156,8 @@ uint32_t radio_tmr_tifs_base_get(void); void radio_tmr_sample(void); uint32_t radio_tmr_sample_get(void); +int radio_gpio_pa_lna_init(void); +void radio_gpio_pa_lna_deinit(void); void radio_gpio_pa_setup(void); void radio_gpio_lna_setup(void); void radio_gpio_pdn_setup(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index baf57d4665381f..a09056ae2d3d3d 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -182,97 +182,6 @@ static inline void hal_trigger_rateoverride_ppi_config(void) } #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ -/******************************************************************************/ -#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) -static inline void hal_palna_ppi_setup(void) -{ - nrf_timer_publish_set(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE2, - HAL_ENABLE_PALNA_PPI); - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, - HAL_DISABLE_PALNA_PPI); - -#if !defined(HAL_RADIO_FEM_IS_NRF21540) - nrf_gpiote_task_t task; - - task = nrf_gpiote_out_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_PALNA_PPI); -#endif -} -#endif /* defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) */ - -/******************************************************************************/ -#if defined(HAL_RADIO_FEM_IS_NRF21540) - -static inline void hal_pa_ppi_setup(void) -{ - nrf_gpiote_task_t task; - -#if defined(HAL_RADIO_GPIO_PA_POL_INV) - task = nrf_gpiote_clr_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_PALNA_PPI); - task = nrf_gpiote_set_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_PALNA_PPI); -#else /* !HAL_RADIO_GPIO_PA_POL_INV */ - task = nrf_gpiote_set_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_PALNA_PPI); - task = nrf_gpiote_clr_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_PALNA_PPI); -#endif /* !HAL_RADIO_GPIO_PA_POL_INV */ -} - -static inline void hal_lna_ppi_setup(void) -{ - nrf_gpiote_task_t task; - -#if defined(HAL_RADIO_GPIO_LNA_POL_INV) - task = nrf_gpiote_clr_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_PALNA_PPI); - task = nrf_gpiote_set_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_PALNA_PPI); -#else /* !HAL_RADIO_GPIO_LNA_POL_INV */ - task = nrf_gpiote_set_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_PALNA_PPI); - task = nrf_gpiote_clr_task_get(HAL_PALNA_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_PALNA_PPI); -#endif /* !HAL_RADIO_GPIO_LNA_POL_INV */ -} - -static inline void hal_fem_ppi_setup(void) -{ - nrf_gpiote_task_t task; - - nrf_timer_publish_set(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE3, - HAL_ENABLE_FEM_PPI); - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, - HAL_DISABLE_FEM_PPI); - -#if defined(HAL_RADIO_GPIO_NRF21540_PDN_POL_INV) - task = nrf_gpiote_clr_task_get(HAL_PDN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_FEM_PPI); - task = nrf_gpiote_set_task_get(HAL_PDN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_FEM_PPI); -#else /* !HAL_RADIO_GPIO_NRF21540_PDN_POL_INV */ - task = nrf_gpiote_set_task_get(HAL_PDN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_FEM_PPI); - task = nrf_gpiote_clr_task_get(HAL_PDN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_FEM_PPI); -#endif /* !HAL_RADIO_GPIO_NRF21540_PDN_POL_INV */ - -#if defined(HAL_RADIO_GPIO_NRF21540_CSN_POL_INV) - task = nrf_gpiote_clr_task_get(HAL_CSN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_FEM_PPI); - task = nrf_gpiote_set_task_get(HAL_CSN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_FEM_PPI); -#else /* !HAL_RADIO_GPIO_NRF21540_CSN_POL_INV */ - task = nrf_gpiote_set_task_get(HAL_CSN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_ENABLE_FEM_PPI); - task = nrf_gpiote_clr_task_get(HAL_CSN_GPIOTE_CHAN); - nrf_gpiote_subscribe_set(NRF_GPIOTE, task, HAL_DISABLE_FEM_PPI); -#endif /* !HAL_RADIO_GPIO_NRF21540_CSN_POL_INV */ -} - -#endif /* HAL_RADIO_FEM_IS_NRF21540 */ - /******************************************************************************/ #if !defined(CONFIG_BT_CTLR_TIFS_HW) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_gpiote.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_gpiote.h new file mode 100644 index 00000000000000..1403921ac22c50 --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_gpiote.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Extracted from radio_nrf_dppi.h functions that reference gpiote variables. */ + +#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) +static inline void hal_palna_ppi_setup(void) +{ + nrf_timer_publish_set(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE2, + HAL_ENABLE_PALNA_PPI); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, + HAL_DISABLE_PALNA_PPI); + +#if !defined(HAL_RADIO_FEM_IS_NRF21540) + nrf_gpiote_task_t task; + + task = nrf_gpiote_out_task_get(gpiote_ch_palna); + nrf_gpiote_subscribe_set(gpiote_palna.p_reg, task, HAL_DISABLE_PALNA_PPI); +#endif +} +#endif /* defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) */ + +/******************************************************************************/ +#if defined(HAL_RADIO_FEM_IS_NRF21540) +static inline void hal_gpiote_tasks_setup(NRF_GPIOTE_Type *gpiote, + uint8_t gpiote_ch, + bool inv, + uint8_t ppi_ch_enable, + uint8_t ppi_ch_disable) +{ + nrf_gpiote_task_t task; + + task = inv ? nrf_gpiote_clr_task_get(gpiote_ch) : + nrf_gpiote_set_task_get(gpiote_ch); + nrf_gpiote_subscribe_set(gpiote, task, ppi_ch_enable); + + task = inv ? nrf_gpiote_set_task_get(gpiote_ch) : + nrf_gpiote_clr_task_get(gpiote_ch); + nrf_gpiote_subscribe_set(gpiote, task, ppi_ch_disable); +} + +static inline void hal_pa_ppi_setup(void) +{ + hal_gpiote_tasks_setup(gpiote_palna.p_reg, gpiote_ch_palna, + IS_ENABLED(HAL_RADIO_GPIO_PA_POL_INV), + HAL_ENABLE_PALNA_PPI, HAL_DISABLE_PALNA_PPI); +} + +static inline void hal_lna_ppi_setup(void) +{ + hal_gpiote_tasks_setup(gpiote_palna.p_reg, gpiote_ch_palna, + IS_ENABLED(HAL_RADIO_GPIO_LNA_POL_INV), + HAL_ENABLE_PALNA_PPI, HAL_DISABLE_PALNA_PPI); +} + +static inline void hal_fem_ppi_setup(void) +{ + nrf_timer_publish_set(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE3, + HAL_ENABLE_FEM_PPI); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, + HAL_DISABLE_FEM_PPI); + + hal_gpiote_tasks_setup(gpiote_pdn.p_reg, gpiote_ch_pdn, + IS_ENABLED(HAL_RADIO_GPIO_NRF21540_PDN_POL_INV), + HAL_ENABLE_FEM_PPI, HAL_DISABLE_FEM_PPI); + + hal_gpiote_tasks_setup(gpiote_csn.p_reg, gpiote_ch_csn, + IS_ENABLED(HAL_RADIO_GPIO_NRF21540_CSN_POL_INV), + HAL_ENABLE_FEM_PPI, HAL_DISABLE_FEM_PPI); +} + +#endif /* HAL_RADIO_FEM_IS_NRF21540 */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_fem.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_fem.h index f38f88dc658dcd..b9ada56b5ab2f3 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_fem.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_fem.h @@ -49,12 +49,12 @@ #ifdef HAL_RADIO_GPIO_HAVE_PA_PIN #if DT_GPIO_FLAGS(FEM_NODE, HAL_RADIO_GPIO_PA_PROP) & GPIO_ACTIVE_LOW -#define HAL_RADIO_GPIO_PA_POL_INV +#define HAL_RADIO_GPIO_PA_POL_INV 1 #endif #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */ #ifdef HAL_RADIO_GPIO_HAVE_LNA_PIN #if DT_GPIO_FLAGS(FEM_NODE, HAL_RADIO_GPIO_LNA_PROP) & GPIO_ACTIVE_LOW -#define HAL_RADIO_GPIO_LNA_POL_INV +#define HAL_RADIO_GPIO_LNA_POL_INV 1 #endif #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h index a2ce85d5f9b2f9..1976df32233c72 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h @@ -268,53 +268,6 @@ static inline void hal_trigger_rateoverride_ppi_config(void) } #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ -/******************************************************************************/ -#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) -static inline void hal_palna_ppi_setup(void) -{ - nrf_ppi_channel_endpoint_setup( - NRF_PPI, - HAL_ENABLE_PALNA_PPI, - (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[2]), - (uint32_t)&(NRF_GPIOTE->TASKS_OUT[HAL_PALNA_GPIOTE_CHAN])); - nrf_ppi_channel_endpoint_setup( - NRF_PPI, - HAL_DISABLE_PALNA_PPI, - (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), - (uint32_t)&(NRF_GPIOTE->TASKS_OUT[HAL_PALNA_GPIOTE_CHAN])); -} -#endif /* defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) */ - -/******************************************************************************/ -#if defined(HAL_RADIO_FEM_IS_NRF21540) -static inline void hal_pa_ppi_setup(void) -{ - /* Nothing specific to PA with FEM to handle inside TRX chains */ -} - -static inline void hal_lna_ppi_setup(void) -{ - /* Nothing specific to LNA with FEM to handle inside TRX chains */ -} - -static inline void hal_fem_ppi_setup(void) -{ - nrf_ppi_channel_and_fork_endpoint_setup( - NRF_PPI, - HAL_ENABLE_FEM_PPI, - (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[3]), - (uint32_t)&(NRF_GPIOTE->TASKS_OUT[HAL_PDN_GPIOTE_CHAN]), - (uint32_t)&(NRF_GPIOTE->TASKS_OUT[HAL_CSN_GPIOTE_CHAN])); - nrf_ppi_channel_and_fork_endpoint_setup( - NRF_PPI, - HAL_DISABLE_FEM_PPI, - (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), - (uint32_t)&(NRF_GPIOTE->TASKS_OUT[HAL_PDN_GPIOTE_CHAN]), - (uint32_t)&(NRF_GPIOTE->TASKS_OUT[HAL_CSN_GPIOTE_CHAN])); -} - -#endif /* HAL_RADIO_FEM_IS_NRF21540 */ - /******************************************************************************/ #if !defined(CONFIG_BT_CTLR_TIFS_HW) /* PPI setup used for SW-based auto-switching during TIFS. */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_gpiote.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_gpiote.h new file mode 100644 index 00000000000000..ec3c11fea1b362 --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi_gpiote.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Extracted from radio_nrf_ppi.h functions that reference gpiote variables. */ + +#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) +static inline void hal_palna_ppi_setup(void) +{ + nrf_ppi_channel_endpoint_setup( + NRF_PPI, + HAL_ENABLE_PALNA_PPI, + (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[2]), + (uint32_t)&(gpiote_palna.p_reg->TASKS_OUT[gpiote_ch_palna])); + nrf_ppi_channel_endpoint_setup( + NRF_PPI, + HAL_DISABLE_PALNA_PPI, + (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), + (uint32_t)&(gpiote_palna.p_reg->TASKS_OUT[gpiote_ch_palna])); +} +#endif /* defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) */ + +/******************************************************************************/ +#if defined(HAL_RADIO_FEM_IS_NRF21540) +static inline void hal_pa_ppi_setup(void) +{ + /* Nothing specific to PA with FEM to handle inside TRX chains */ +} + +static inline void hal_lna_ppi_setup(void) +{ + /* Nothing specific to LNA with FEM to handle inside TRX chains */ +} + +static inline void hal_fem_ppi_setup(void) +{ + nrf_ppi_channel_and_fork_endpoint_setup( + NRF_PPI, + HAL_ENABLE_FEM_PPI, + (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[3]), + (uint32_t)&(gpiote_pdn.p_reg->TASKS_OUT[gpiote_ch_pdn]), + (uint32_t)&(gpiote_csn.p_reg->TASKS_OUT[gpiote_ch_csn])); + nrf_ppi_channel_and_fork_endpoint_setup( + NRF_PPI, + HAL_DISABLE_FEM_PPI, + (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), + (uint32_t)&(gpiote_pdn.p_reg->TASKS_OUT[gpiote_ch_pdn]), + (uint32_t)&(gpiote_csn.p_reg->TASKS_OUT[gpiote_ch_csn])); +} + +#endif /* HAL_RADIO_FEM_IS_NRF21540 */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 6aec56a0ab4a64..5ed02f4051ff07 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -192,6 +192,14 @@ int lll_init(void) return err; } + if (IS_ENABLED(HAL_RADIO_GPIO_HAVE_PA_PIN) || + IS_ENABLED(HAL_RADIO_GPIO_HAVE_LNA_PIN)) { + err = radio_gpio_pa_lna_init(); + if (err) { + return err; + } + } + /* Initialize SW IRQ structure */ hal_swi_init(); @@ -259,6 +267,11 @@ int lll_deinit(void) return err; } + if (IS_ENABLED(HAL_RADIO_GPIO_HAVE_PA_PIN) || + IS_ENABLED(HAL_RADIO_GPIO_HAVE_LNA_PIN)) { + radio_gpio_pa_lna_deinit(); + } + /* Disable IRQs */ irq_disable(RADIO_IRQn); irq_disable(RTC0_IRQn); From ef5339e4c737b92d411914cb2081db682eea3e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1296/1389] drivers: timer: nrf_grtc_timer: Fix for random system hangs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit d599e2b6705eb removed early return from sys_clock_timeout_handler if current counter value is less than cc_val. It seems that this return is needed as after the removal some stress tests which were using system timers heavily started to hang. Signed-off-by: Krzysztof Chruściński --- drivers/timer/nrf_grtc_timer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index a5c41a63ab97c7..a12bf607555d45 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -184,6 +184,11 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte ARG_UNUSED(id); ARG_UNUSED(p_context); uint64_t dticks; + uint64_t now = counter(); + + if (unlikely(now < cc_val)) { + return; + } dticks = counter_sub(cc_val, last_count) / CYC_PER_TICK; From 1756fa66bb29689bf43830f72a21d4039b95df03 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1297/1389] kernel: demand_paging: fix arch_page_location_get() documentation Symbols from enum arch_page_location are defined as ARCH_PAGE_LOCATION_* and not ARCH_PAGE_FAULT_*. Signed-off-by: Nicolas Pitre --- kernel/include/kernel_arch_interface.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 18944dc78a06c7..9860070542edf2 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -435,12 +435,12 @@ enum arch_page_location { * in that. * * @param addr Virtual data page address that took the page fault - * @param [out] location In the case of ARCH_PAGE_FAULT_PAGED_OUT, the backing + * @param [out] location In the case of ARCH_PAGE_LOCATION_PAGED_OUT, the backing * store location value used to retrieve the data page. In the case of - * ARCH_PAGE_FAULT_PAGED_IN, the physical address the page is mapped to. - * @retval ARCH_PAGE_FAULT_PAGED_OUT The page was evicted to the backing store. - * @retval ARCH_PAGE_FAULT_PAGED_IN The data page is resident in memory. - * @retval ARCH_PAGE_FAULT_BAD The page is un-mapped or otherwise has had + * ARCH_PAGE_LOCATION_PAGED_IN, the physical address the page is mapped to. + * @retval ARCH_PAGE_LOCATION_PAGED_OUT The page was evicted to the backing store. + * @retval ARCH_PAGE_LOCATION_PAGED_IN The data page is resident in memory. + * @retval ARCH_PAGE_LOCATION_BAD The page is un-mapped or otherwise has had * invalid access */ enum arch_page_location arch_page_location_get(void *addr, uintptr_t *location); From 8426e01e86251ac03a20dd100b01f47788d059c0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1298/1389] usb: dfu: fix detach happening too fast In some relatively rare conditions, the DFU detach/attach happens to fast, which cause the host to not notice it. It seems to to be the case for instance on STM32 when no endpoint are being used. Adding a 1 ms delay (i.e. one SOF period) between the detach and the attach fixes the issue. Signed-off-by: Aurelien Jarno --- subsys/usb/device/class/dfu/usb_dfu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/usb/device/class/dfu/usb_dfu.c b/subsys/usb/device/class/dfu/usb_dfu.c index db1706de1d68bd..0847e9b2454b1b 100644 --- a/subsys/usb/device/class/dfu/usb_dfu.c +++ b/subsys/usb/device/class/dfu/usb_dfu.c @@ -427,6 +427,10 @@ static void dfu_timer_work_handler(struct k_work *item) LOG_ERR("usb_dc_detach failed"); } dfu_enter_idle(); + + /* Wait 1 SOF period to ensure the host notices the deconnection. */ + k_sleep(K_MSEC(1)); + if (usb_dc_attach()) { LOG_ERR("usb_dc_attach failed"); } From 56ce756ed50853f8a4fd58f3f6aa0d922090b45b Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1299/1389] net: dns: don't request address in recvfrom() Source address is not used anywhere, so don't request it with recvfrom() API. Signed-off-by: Marcin Niestroj --- subsys/net/lib/dns/resolve.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 3e7a22923bc3c5..85bbf9a6feba0c 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -780,11 +780,8 @@ static int dns_read(struct dns_resolve_context *ctx, static int recv_data(struct net_socket_service_event *pev) { - COND_CODE_1(IS_ENABLED(CONFIG_NET_IPV6), - (struct sockaddr_in6), (struct sockaddr_in)) addr; struct dns_resolve_context *ctx = pev->user_data; socklen_t optlen = sizeof(int); - size_t addrlen = sizeof(addr); struct net_buf *dns_cname = NULL; struct net_buf *dns_data = NULL; uint16_t query_hash = 0U; @@ -824,7 +821,7 @@ static int recv_data(struct net_socket_service_event *pev) ret = zsock_recvfrom(pev->event.fd, dns_data->data, net_buf_max_len(dns_data), 0, - (struct sockaddr *)&addr, &addrlen); + NULL, NULL); if (ret < 0) { ret = -errno; NET_ERR("recv failed on IPv%d socket (%d)", From 1be954321f0702755c5bad537840a091ce57d7e2 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1300/1389] dt-bindings: pinctrl: nrf: allow for more ports New nRF54H20 SoC series expose more ports, e.g. P9, so reserve more bits for the Port+Pin field. Signed-off-by: Gerard Marull-Paretas --- .../zephyr/dt-bindings/pinctrl/nrf-pinctrl.h | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h index a50233ab38c7fc..cbd92c734604b4 100644 --- a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h @@ -10,13 +10,12 @@ * The whole nRF pin configuration information is encoded in a 32-bit bitfield * organized as follows: * - * - 31..16: Pin function. - * - 15: Reserved. - * - 14: Pin inversion mode. - * - 13: Pin low power mode. - * - 12..9: Pin output drive configuration. - * - 8..7: Pin pull configuration. - * - 6..0: Pin number (combination of port and pin). + * - 31..17: Pin function. + * - 16: Pin inversion mode. + * - 15: Pin low power mode. + * - 14..11: Pin output drive configuration. + * - 10..9: Pin pull configuration. + * - 8..0: Pin number (combination of port and pin). */ /** @@ -25,29 +24,29 @@ */ /** Position of the function field. */ -#define NRF_FUN_POS 16U +#define NRF_FUN_POS 17U /** Mask for the function field. */ -#define NRF_FUN_MSK 0xFFFFU +#define NRF_FUN_MSK 0x7FFFU /** Position of the invert field. */ -#define NRF_INVERT_POS 14U +#define NRF_INVERT_POS 16U /** Mask for the invert field. */ #define NRF_INVERT_MSK 0x1U /** Position of the low power field. */ -#define NRF_LP_POS 13U +#define NRF_LP_POS 15U /** Mask for the low power field. */ #define NRF_LP_MSK 0x1U /** Position of the drive configuration field. */ -#define NRF_DRIVE_POS 9U +#define NRF_DRIVE_POS 11U /** Mask for the drive configuration field. */ #define NRF_DRIVE_MSK 0xFU /** Position of the pull configuration field. */ -#define NRF_PULL_POS 7U +#define NRF_PULL_POS 9U /** Mask for the pull configuration field. */ #define NRF_PULL_MSK 0x3U /** Position of the pin field. */ #define NRF_PIN_POS 0U /** Mask for the pin field. */ -#define NRF_PIN_MSK 0x7FU +#define NRF_PIN_MSK 0x1FFU /** @} */ @@ -218,7 +217,7 @@ * @brief Utility macro to build nRF psels property entry. * * @param fun Pin function configuration (see NRF_FUNC_{name} macros). - * @param port Port (0 or 1). + * @param port Port (0 or 15). * @param pin Pin (0..31). */ #define NRF_PSEL(fun, port, pin) \ From 7b8c974c0c3df29a0586787d53b2f77765ba883b Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1301/1389] drivers: mipi_dbi: smartbond: Optimize driver PM This commit should optimize the way the device is allowed to enter the suspended state. Instead of returning a PM error code to abort the PM process, the standby power state is constrained as long as the device is not allowed to enter suspension. With that approach, acquiring PD_SYS is not needed when in PM device runtime mode. Signed-off-by: Ioannis Karachalios --- drivers/mipi_dbi/mipi_dbi_smartbond.c | 64 +++++++++------------------ 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/mipi_dbi/mipi_dbi_smartbond.c b/drivers/mipi_dbi/mipi_dbi_smartbond.c index 480ee2158b2062..da0e5e154cec11 100644 --- a/drivers/mipi_dbi/mipi_dbi_smartbond.c +++ b/drivers/mipi_dbi/mipi_dbi_smartbond.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -62,10 +63,6 @@ struct mipi_dbi_smartbond_data { struct k_sem sync_sem; /* Flag indicating whether or not an underflow took place */ volatile bool underflow_flag; -#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) - /* Flag to designate whether or not a frame update is in progress */ - bool is_active; -#endif /* Layer settings */ lcdc_smartbond_layer_cfg layer; }; @@ -82,23 +79,20 @@ struct mipi_dbi_smartbond_config { }; /* Mark the device is is progress and so it's not allowed to enter the sleep state. */ -static void mipi_dbi_pm_get(const struct device *dev) +static inline void mipi_dbi_smartbond_pm_policy_state_lock_get(void) { -#ifdef CONFIG_PM_DEVICE - struct mipi_dbi_smartbond_data *data = dev->data; - - data->is_active = true; -#endif + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following LCDC events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); } /* Mark that device is inactive and so it's allowed to enter the sleep state */ -static void mipi_dbi_pm_put(const struct device *dev) +static inline void mipi_dbi_smartbond_pm_policy_state_lock_put(void) { -#ifdef CONFIG_PM_DEVICE - struct mipi_dbi_smartbond_data *data = dev->data; - - data->is_active = false; -#endif + /* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); } /* Helper function to trigger the LCDC fetching data from frame buffer to the connected display */ @@ -217,6 +211,8 @@ static int mipi_dbi_smartbond_command_read(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); + mipi_dbi_smartbond_pm_policy_state_lock_get(); + /* * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data * engine should not be affected. @@ -283,6 +279,8 @@ static int mipi_dbi_smartbond_command_read(const struct device *dev, LOG_ERR("Could not apply MIPI DBI pins' default state (%d)", ret); } + mipi_dbi_smartbond_pm_policy_state_lock_put(); + k_sem_give(&data->device_sem); return ret; @@ -300,7 +298,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); - mipi_dbi_pm_get(dev); + mipi_dbi_smartbond_pm_policy_state_lock_get(); /* * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data @@ -321,7 +319,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev, da1469x_lcdc_send_cmd_data(false, data_buf, len); } - mipi_dbi_pm_put(dev); + mipi_dbi_smartbond_pm_policy_state_lock_put(); k_sem_give(&data->device_sem); @@ -349,7 +347,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); - mipi_dbi_pm_get(dev); + mipi_dbi_smartbond_pm_policy_state_lock_get(); /* * Mainly check if the frame generator is busy with a pending frame update (might happen @@ -388,7 +386,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev, _mipi_dbi_write_exit: - mipi_dbi_pm_put(dev); + mipi_dbi_smartbond_pm_policy_state_lock_put(); k_sem_give(&data->device_sem); @@ -488,33 +486,14 @@ static int mipi_dbi_smartbond_suspend(const struct device *dev) static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { - /* Initialize with an error code that should abort sleeping */ - int ret = -EBUSY; - struct mipi_dbi_smartbond_data *data = dev->data; + int ret = 0; switch (action) { case PM_DEVICE_ACTION_SUSPEND: - /* Sleep is only allowed when there are no active LCDC operations */ - if (!data->is_active) { - (void)mipi_dbi_smartbond_suspend(dev); - /* - * Once the display block is turned off, its power domain - * can be released as well. - */ - da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); - ret = 0; - } + /* A non-zero value should not affect sleep */ + (void)mipi_dbi_smartbond_suspend(dev); break; case PM_DEVICE_ACTION_RESUME: - __ASSERT_NO_MSG(!data->is_active); - - /* - * Although PD_SYS should already be turned on, make sure LCD controller's - * power domain is up and running before accessing the display block. - * Acquiring PD_SYS is mandatory when in PM runtime mode. - */ - da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); - /* * The resume error code should not be taken into consideration * by the PM subsystem. @@ -559,7 +538,6 @@ static int mipi_dbi_smartbond_init(const struct device *dev) ret = pm_device_runtime_enable(dev); #else - da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); /* Resme if either PM is not used at all or if PM without runtime is used. */ ret = mipi_dbi_smartbond_resume(dev); #endif From 15579324bd1ede6a5fe8529fcab24a8bf10d4a77 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1302/1389] drivers: display: smartbond: Optimize driver PM This commit should optimize the way the device is allowed to enter the suspended state. Instead of returning a PM error code to abort the PM process, the standby power state is constrained as long as the device is not allowed to enter suspension. With that approach, acquiring PD_SYS is not needed when in PM device runtime mode. Signed-off-by: Ioannis Karachalios --- drivers/display/display_renesas_lcdc.c | 52 +++++++++++++++----------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/display/display_renesas_lcdc.c b/drivers/display/display_renesas_lcdc.c index ab12cc23a0083a..24678108617358 100644 --- a/drivers/display/display_renesas_lcdc.c +++ b/drivers/display/display_renesas_lcdc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(smartbond_display, CONFIG_DISPLAY_LOG_LEVEL); @@ -75,8 +76,7 @@ struct display_smartbond_data { /* Granted DMA channel used for memory transfers */ int dma_channel; #if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) - /* Flag to determine if device suspension is allowed */ - bool is_sleep_allowed; + ATOMIC_DEFINE(pm_policy_state_flag, 1); #endif }; @@ -99,6 +99,29 @@ struct display_smartbond_config { enum display_pixel_format pixel_format; }; +static inline void lcdc_smartbond_pm_policy_state_lock_get(struct display_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following LCDC events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void lcdc_smartbond_pm_policy_state_lock_put(struct display_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + /* Display pixel to layer color format translation */ static uint8_t lcdc_smartbond_pixel_to_lcm(enum display_pixel_format pixel_format) { @@ -319,11 +342,6 @@ static int display_smartbond_init(const struct device *dev) pm_device_init_suspended(dev); ret = pm_device_runtime_enable(dev); - - /* Sleep is allowed until the device is explicitly resumed on application level. */ - if (ret == 0) { - data->is_sleep_allowed = true; - } #else /* Resume if either PM is not used at all or if PM without runtime is used. */ ret = display_smartbond_resume(dev); @@ -355,13 +373,11 @@ static int display_smartbond_blanking_on(const struct device *dev) } } -#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) /* * At this moment the display panel should be turned off and so the device * can enter the suspend state. */ - data->is_sleep_allowed = true; -#endif + lcdc_smartbond_pm_policy_state_lock_put(data); k_sem_give(&data->device_sem); @@ -391,13 +407,11 @@ static int display_smartbond_blanking_off(const struct device *dev) */ LCDC->LCDC_MODE_REG &= ~LCDC_LCDC_MODE_REG_LCDC_FORCE_BLANK_Msk; -#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) /* * At this moment the display should be turned on and so the device * cannot enter the suspend state. */ - data->is_sleep_allowed = false; -#endif + lcdc_smartbond_pm_policy_state_lock_get(data); k_sem_give(&data->device_sem); @@ -566,20 +580,14 @@ static int display_smartbond_write(const struct device *dev, #if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) static int display_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { - /* Initialize with an error code that should abort sleeping */ - int ret = -EBUSY; - struct display_smartbond_data *data = dev->data; + int ret = 0; switch (action) { case PM_DEVICE_ACTION_SUSPEND: - /* Sleep is only allowed whne display blanking is activated */ - if (data->is_sleep_allowed) { - (void)display_smartbond_suspend(dev); - ret = 0; - } + /* A non-zero value should not affect sleep */ + (void)display_smartbond_suspend(dev); break; case PM_DEVICE_ACTION_RESUME: - __ASSERT_NO_MSG(data->is_sleep_allowed); /* * The resume error code should not be taken into consideration * by the PM subsystem From da7d1857c4b077a09af15a4a8858c88d81b88171 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1303/1389] drivers: entropy: smartbond: Optimize driver PM This commit should optimize the way the device is allowed to enter the suspended state. Instead of returning a PM error code to abort the PM process, the standby power state is constrained as long as the device is not allowed to enter suspension. With that approach, acquiring PD_SYS is not needed when in PM device runtime mode. Signed-off-by: Ioannis Karachalios --- drivers/entropy/entropy_smartbond.c | 62 +++++++++++++++++++---------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/entropy/entropy_smartbond.c b/drivers/entropy/entropy_smartbond.c index 80f9ef1510c5d3..fecb7b07491e22 100644 --- a/drivers/entropy/entropy_smartbond.c +++ b/drivers/entropy/entropy_smartbond.c @@ -12,6 +12,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(smartbond_entropy, CONFIG_ENTROPY_LOG_LEVEL); @@ -46,6 +47,10 @@ struct entropy_smartbond_dev_data { RNG_POOL_DEFINE(isr, CONFIG_ENTROPY_SMARTBOND_ISR_POOL_SIZE); RNG_POOL_DEFINE(thr, CONFIG_ENTROPY_SMARTBOND_THR_POOL_SIZE); + +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; static struct entropy_smartbond_dev_data entropy_smartbond_data; @@ -57,6 +62,33 @@ static struct entropy_smartbond_dev_data entropy_smartbond_data; #define FIFO_COUNT_MASK \ (TRNG_TRNG_FIFOLVL_REG_TRNG_FIFOFULL_Msk | TRNG_TRNG_FIFOLVL_REG_TRNG_FIFOLVL_Msk) +static inline void entropy_smartbond_pm_policy_state_lock_get(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct entropy_smartbond_dev_data *data = dev->data; + + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following TRNG events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void entropy_smartbond_pm_policy_state_lock_put(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct entropy_smartbond_dev_data *data = dev->data; + + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* Allow the SoC to enter the nornmal sleep state once TRNG is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + static void trng_enable(bool enable) { unsigned int key; @@ -65,9 +97,17 @@ static void trng_enable(bool enable) if (enable) { CRG_TOP->CLK_AMBA_REG |= CRG_TOP_CLK_AMBA_REG_TRNG_CLK_ENABLE_Msk; TRNG->TRNG_CTRL_REG = TRNG_TRNG_CTRL_REG_TRNG_ENABLE_Msk; + + /* + * Sleep is not allowed as long as the ISR and thread SW FIFOs + * are being filled with random numbers. + */ + entropy_smartbond_pm_policy_state_lock_get(DEVICE_DT_INST_GET(0)); } else { CRG_TOP->CLK_AMBA_REG &= ~CRG_TOP_CLK_AMBA_REG_TRNG_CLK_ENABLE_Msk; TRNG->TRNG_CTRL_REG = 0; + + entropy_smartbond_pm_policy_state_lock_put(DEVICE_DT_INST_GET(0)); } irq_unlock(key); } @@ -340,25 +380,12 @@ static int entropy_smartbond_get_entropy_isr(const struct device *dev, uint8_t * } #if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) -/* - * TRNG is powered by PD_SYS which is the same power domain used to power the SoC. - * Entering the sleep state should not be allowed for as long as the ISR and thread - * SW FIFOs are being filled with random numbers. - */ -static inline bool entropy_is_sleep_allowed(void) -{ - return !(TRNG->TRNG_CTRL_REG & TRNG_TRNG_CTRL_REG_TRNG_ENABLE_Msk); -} - static int entropy_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { - /* Initialize with an error code that should abort sleeping */ - int ret = -EBUSY; + int ret = 0; switch (action) { case PM_DEVICE_ACTION_RESUME: - __ASSERT_NO_MSG(entropy_is_sleep_allowed()); - /* * No need to turn on TRNG. It should be done when we the space in the FIFOs * are below the defined ISR and thread FIFO's thresholds. @@ -367,14 +394,9 @@ static int entropy_smartbond_pm_action(const struct device *dev, enum pm_device_ * \sa CONFIG_ENTROPY_SMARTBOND_ISR_THRESHOLD * */ - ret = 0; break; case PM_DEVICE_ACTION_SUSPEND: - /* Sleep is only allowed when there is no TRNG activity */ - if (entropy_is_sleep_allowed()) { - /* At this point TRNG should be disabled; no need to turn it off. */ - ret = 0; - } + /* At this point TRNG should be disabled; no need to turn it off. */ break; default: ret = -ENOTSUP; From 46743dfea77fcff3213205152b2fac1ac9211c79 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1304/1389] Bluetooth: audio: tests: Switch to one-time adv This patch removes all uses of the adv auto-resume feature in the audio bsim tests, and instead makes all adv starts explicit. The auto-resume feature is planned for deprecation. And, explicit starting of adv makes what happens in the test more explicit as well. Signed-off-by: Aleksander Wasaznik --- .../audio/src/bap_scan_delegator_test.c | 2 +- .../bluetooth/audio/src/cap_acceptor_test.c | 2 +- .../audio/src/csip_notify_server_test.c | 4 ++-- .../audio/src/csip_set_member_test.c | 2 +- .../bsim/bluetooth/audio/src/gmap_ugt_test.c | 4 ++-- tests/bsim/bluetooth/audio/src/has_test.c | 22 ++++++++++++------ tests/bsim/bluetooth/audio/src/ias_test.c | 2 +- tests/bsim/bluetooth/audio/src/mcs_test.c | 23 +++++++++---------- .../audio/src/media_controller_test.c | 2 +- .../bluetooth/audio/src/micp_mic_dev_test.c | 2 +- .../audio/src/pacs_notify_server_test.c | 8 +++---- .../bluetooth/audio/src/tbs_client_test.c | 2 +- .../bluetooth/audio/src/vcp_vol_rend_test.c | 2 +- 13 files changed, 42 insertions(+), 35 deletions(-) diff --git a/tests/bsim/bluetooth/audio/src/bap_scan_delegator_test.c b/tests/bsim/bluetooth/audio/src/bap_scan_delegator_test.c index 776fe9ff4b38cc..13123a2306ca42 100644 --- a/tests/bsim/bluetooth/audio/src/bap_scan_delegator_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_scan_delegator_test.c @@ -680,7 +680,7 @@ static int common_init(void) bt_bap_scan_delegator_register_cb(&scan_delegator_cb); bt_le_per_adv_sync_cb_register(&pa_sync_cb); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); return err; diff --git a/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c b/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c index 9a11cee54ff3b6..38a8bde83f599c 100644 --- a/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c @@ -616,7 +616,7 @@ static void init(void) bt_cap_stream_ops_register(&unicast_streams[i], &unicast_stream_ops); } - err = bt_le_adv_start(BT_LE_ADV_CONN, cap_acceptor_ad, + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, cap_acceptor_ad, ARRAY_SIZE(cap_acceptor_ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); diff --git a/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c b/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c index 0faa6713d59b0b..1223a6797e0baf 100644 --- a/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c +++ b/tests/bsim/bluetooth/audio/src/csip_notify_server_test.c @@ -66,7 +66,7 @@ static void test_main(void) } printk("Start Advertising\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; @@ -107,7 +107,7 @@ static void test_main(void) } printk("Start Advertising\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/csip_set_member_test.c b/tests/bsim/bluetooth/audio/src/csip_set_member_test.c index 0833c4e2f8b3f2..6a458dc0d0fc63 100644 --- a/tests/bsim/bluetooth/audio/src/csip_set_member_test.c +++ b/tests/bsim/bluetooth/audio/src/csip_set_member_test.c @@ -70,7 +70,7 @@ static void bt_ready(int err) return; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); } diff --git a/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c b/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c index 2171b6c1aff61d..60854912903dec 100644 --- a/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c +++ b/tests/bsim/bluetooth/audio/src/gmap_ugt_test.c @@ -416,8 +416,8 @@ static void test_main(void) return; } - err = bt_le_adv_start(BT_LE_ADV_CONN, gmap_acceptor_ad, ARRAY_SIZE(gmap_acceptor_ad), - NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, gmap_acceptor_ad, + ARRAY_SIZE(gmap_acceptor_ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/has_test.c b/tests/bsim/bluetooth/audio/src/has_test.c index 949192c4070194..8cf802455f7814 100644 --- a/tests/bsim/bluetooth/audio/src/has_test.c +++ b/tests/bsim/bluetooth/audio/src/has_test.c @@ -31,6 +31,19 @@ static const struct bt_has_preset_ops preset_ops = { .select = preset_select, }; +static void start_adv(void) +{ + int err; + + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); + if (err) { + FAIL("Advertising failed to start (err %d)\n", err); + return; + } + + LOG_DBG("Advertising successfully started"); +} + static void test_common(void) { struct bt_has_features_param has_param = {0}; @@ -46,13 +59,7 @@ static void test_common(void) LOG_DBG("Bluetooth initialized"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); - if (err) { - FAIL("Advertising failed to start (err %d)\n", err); - return; - } - - LOG_DBG("Advertising successfully started"); + start_adv(); has_param.type = BT_HAS_HEARING_AID_TYPE_BINAURAL; has_param.preset_sync_support = true; @@ -115,6 +122,7 @@ static void test_offline_behavior(void) WAIT_FOR_FLAG(flag_connected); WAIT_FOR_UNSET_FLAG(flag_connected); + start_adv(); preset_param.index = test_preset_index_3; preset_param.properties = test_preset_properties; diff --git a/tests/bsim/bluetooth/audio/src/ias_test.c b/tests/bsim/bluetooth/audio/src/ias_test.c index 72daba4465b76d..32eb09f4b1bce6 100644 --- a/tests/bsim/bluetooth/audio/src/ias_test.c +++ b/tests/bsim/bluetooth/audio/src/ias_test.c @@ -58,7 +58,7 @@ static void test_main(void) return; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/mcs_test.c b/tests/bsim/bluetooth/audio/src/mcs_test.c index b94f2cf96e0200..424c7e17d44b2f 100644 --- a/tests/bsim/bluetooth/audio/src/mcs_test.c +++ b/tests/bsim/bluetooth/audio/src/mcs_test.c @@ -12,17 +12,11 @@ extern enum bst_result_t bst_result; -/* Callback after Bluetoot initialization attempt */ -static void bt_ready(int err) +static void start_adv(void) { - if (err) { - FAIL("Bluetooth init failed (err %d)\n", err); - return; - } - - printk("Bluetooth initialized\n"); + int err; - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); return; @@ -45,15 +39,20 @@ static void test_main(void) } /* Initialize Bluetooth, get connected */ - err = bt_enable(bt_ready); + err = bt_enable(NULL); if (err) { FAIL("Bluetooth init failed (err %d)\n", err); return; } - - WAIT_FOR_FLAG(flag_connected); + printk("Bluetooth initialized\n"); PASS("MCS passed\n"); + + while (1) { + start_adv(); + WAIT_FOR_FLAG(flag_connected); + WAIT_FOR_UNSET_FLAG(flag_connected); + } } static const struct bst_test_instance test_mcs[] = { diff --git a/tests/bsim/bluetooth/audio/src/media_controller_test.c b/tests/bsim/bluetooth/audio/src/media_controller_test.c index cf8ce038c6b957..2f06d5833e8b27 100644 --- a/tests/bsim/bluetooth/audio/src/media_controller_test.c +++ b/tests/bsim/bluetooth/audio/src/media_controller_test.c @@ -1647,7 +1647,7 @@ void test_media_controller_remote_player(void) initialize_bluetooth(); initialize_media(); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); } diff --git a/tests/bsim/bluetooth/audio/src/micp_mic_dev_test.c b/tests/bsim/bluetooth/audio/src/micp_mic_dev_test.c index ca95b727cb6702..713e89afe3de35 100644 --- a/tests/bsim/bluetooth/audio/src/micp_mic_dev_test.c +++ b/tests/bsim/bluetooth/audio/src/micp_mic_dev_test.c @@ -420,7 +420,7 @@ static void test_main(void) printk("MICP initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c b/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c index c60562bcd512bb..d04269b3913399 100644 --- a/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c +++ b/tests/bsim/bluetooth/audio/src/pacs_notify_server_test.c @@ -176,7 +176,7 @@ static void test_main(void) } LOG_DBG("Start Advertising"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)", err); return; @@ -210,7 +210,7 @@ static void test_main(void) trigger_notifications(); LOG_DBG("Start Advertising"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)", err); return; @@ -227,7 +227,7 @@ static void test_main(void) } LOG_DBG("Start Advertising"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)", err); return; @@ -261,7 +261,7 @@ static void test_main(void) } LOG_DBG("Start Advertising"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)", err); return; diff --git a/tests/bsim/bluetooth/audio/src/tbs_client_test.c b/tests/bsim/bluetooth/audio/src/tbs_client_test.c index b2a6e34fc00345..1fc34b8f09c7ca 100644 --- a/tests/bsim/bluetooth/audio/src/tbs_client_test.c +++ b/tests/bsim/bluetooth/audio/src/tbs_client_test.c @@ -494,7 +494,7 @@ static void test_main(void) printk("Audio Server: Bluetooth discovered\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; diff --git a/tests/bsim/bluetooth/audio/src/vcp_vol_rend_test.c b/tests/bsim/bluetooth/audio/src/vcp_vol_rend_test.c index 23f02909a8ad8b..82570b59e41284 100644 --- a/tests/bsim/bluetooth/audio/src/vcp_vol_rend_test.c +++ b/tests/bsim/bluetooth/audio/src/vcp_vol_rend_test.c @@ -1032,7 +1032,7 @@ static void test_main(void) printk("VCP initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, AD_SIZE, NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, AD_SIZE, NULL, 0); if (err != 0) { FAIL("Advertising failed to start (err %d)\n", err); return; From 0b8688ff6ef18743caaa05039b333595ca4077e9 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1305/1389] sensor_shell: fix assertion due to NULL pointer deref The `SENSOR_CHAN_VSHUNT` was added in #60717 but was never added to the `sensor_channel_name[SENSOR_CHAN_COMMON_COUNT]` table. Since the length of `sensor_channel_name` is fixed to `SENSOR_CHAN_COMMON_COUNT`, this means that the index at `SENSOR_CHAN_VSHUNT` points to `NULL`. When we use the `sensor get` command for anything bigger than `SENSOR_CHAN_VSHUNT`, we will deref that `NULL` pointer when we do `strcmp` in the for-loop of `parse_named_int`. Fix this by defining `SENSOR_CHAN_VSHUNT` in the table. Signed-off-by: Yong Cong Sin --- drivers/sensor/sensor_shell.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 972f62c7fe3fe8..7f9c9b3e50c573 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -78,6 +78,7 @@ static const char *sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = { [SENSOR_CHAN_VOC] = "voc", [SENSOR_CHAN_GAS_RES] = "gas_resistance", [SENSOR_CHAN_VOLTAGE] = "voltage", + [SENSOR_CHAN_VSHUNT] = "vshunt", [SENSOR_CHAN_CURRENT] = "current", [SENSOR_CHAN_POWER] = "power", [SENSOR_CHAN_RESISTANCE] = "resistance", From 25c5094bf5bd500104d73958e427661eb6eddf99 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1306/1389] sensor_shell: fix hang when device is not a sensor If `CONFIG_SENSOR_INFO` is enabled, use the `sensor_info` section to validate that the argument is a sensor before using, otherwise the shell command will hang the application. Signed-off-by: Yong Cong Sin --- drivers/sensor/sensor_shell.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 7f9c9b3e50c573..0000040f18afae 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -144,6 +144,20 @@ static struct sample_stats sensor_stats[CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES] static const struct device *sensor_trigger_devices[CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES]; +static bool device_is_sensor(const struct device *dev) +{ +#ifdef CONFIG_SENSOR_INFO + STRUCT_SECTION_FOREACH(sensor_info, sensor) { + if (sensor->dev == dev) { + return true; + } + } + return false; +#else + return true; +#endif /* CONFIG_SENSOR_INFO */ +} + static int find_sensor_trigger_device(const struct device *sensor) { for (int i = 0; i < CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES; i++) { @@ -529,6 +543,12 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } + if (!device_is_sensor(dev)) { + shell_error(sh, "Device is not a sensor (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); + return -ENODEV; + } + if (argc == 2) { /* read all channel types */ for (int i = 0; i < ARRAY_SIZE(iodev_sensor_shell_channels); ++i) { @@ -591,6 +611,12 @@ static int cmd_sensor_attr_set(const struct shell *shell_ptr, size_t argc, char return -ENODEV; } + if (!device_is_sensor(dev)) { + shell_error(shell_ptr, "Device is not a sensor (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); + return -ENODEV; + } + for (size_t i = 2; i < argc; i += 3) { int channel = parse_named_int(argv[i], sensor_channel_name, ARRAY_SIZE(sensor_channel_name)); @@ -669,6 +695,12 @@ static int cmd_sensor_attr_get(const struct shell *shell_ptr, size_t argc, char return -ENODEV; } + if (!device_is_sensor(dev)) { + shell_error(shell_ptr, "Device is not a sensor (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); + return -ENODEV; + } + if (argc > 2) { for (size_t i = 2; i < argc; i += 2) { cmd_sensor_attr_get_handler(shell_ptr, dev, argv[i], argv[i + 1], From 5040b7ff22d390fec810ad9b465d4f61e0a9ce4d Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1307/1389] samples: sensor: sensor_shell: update pytest to validate fix Update the pytest script to exercise the entire `sensor_channel_name` table with `parse_named_int()`. The `gauge_desired_charging_current` is selected because it is the last one in the table before `all`, `all` is not used because `sensor get sensor@0 all` doesn't return anything. Signed-off-by: Yong Cong Sin --- samples/sensor/sensor_shell/pytest/test_sensor_shell.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/sensor/sensor_shell/pytest/test_sensor_shell.py b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py index c13f888a28507f..9cbca8ea36f38a 100644 --- a/samples/sensor/sensor_shell/pytest/test_sensor_shell.py +++ b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py @@ -27,6 +27,11 @@ def test_sensor_shell_get(shell: Shell): lines = shell.exec_command('sensor get sensor@1 53') assert any(['channel type=53(gauge_time_to_empty)' in line for line in lines]), 'expected response not found' + # Channel should be the last one before 'all' (because 'all' doesn't print anything) so that the + # for-loop in `parse_named_int()` will go through everything + lines = shell.exec_command('sensor get sensor@0 gauge_desired_charging_current') + assert any(['channel type=58(gauge_desired_charging_current)' in line for line in lines]), 'expected response not found' + logger.info('response is valid') From 5038ba347261c1d12432d381af489b6ce2bff39b Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:37 +0200 Subject: [PATCH 1308/1389] sensors: shell: use SENSOR_CHANNEL_3_AXIS whenever possible Instead of specifying 3 axis channels manually, use `SENSOR_CHANNEL_3_AXIS` instead. Signed-off-by: Yong Cong Sin --- drivers/sensor/sensor_shell.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 0000040f18afae..e175d6d05fa51b 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -984,8 +984,7 @@ static void data_ready_trigger_handler(const struct device *sensor, continue; } /* Skip 3 axis channels */ - if (i == SENSOR_CHAN_ACCEL_XYZ || i == SENSOR_CHAN_GYRO_XYZ || - i == SENSOR_CHAN_MAGN_XYZ) { + if (SENSOR_CHANNEL_3_AXIS(i)) { continue; } From 48fc86879b909bea48592e5b1ae1e6e6dbd73fda Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1309/1389] sensors: add new channel `SENSOR_CHAN_POS_DXYZ` Add new channel: `SENSOR_CHAN_POS_DXYZ`, so that it is consistent with other 3-axis channels. Updated pytest, `sensor_shell` & `fake_sensor` accordingly. Signed-off-by: Yong Cong Sin --- drivers/sensor/default_rtio_sensor.c | 5 +++++ drivers/sensor/sensor_shell.c | 6 ++++-- include/zephyr/drivers/sensor.h | 6 ++++-- include/zephyr/drivers/sensor_data_types.h | 1 + samples/sensor/sensor_shell/pytest/test_sensor_shell.py | 8 ++++---- samples/sensor/sensor_shell/src/fake_sensor.c | 2 ++ 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/sensor/default_rtio_sensor.c b/drivers/sensor/default_rtio_sensor.c index c95dcedfe87954..c6b45e3e173a63 100644 --- a/drivers/sensor/default_rtio_sensor.c +++ b/drivers/sensor/default_rtio_sensor.c @@ -304,6 +304,9 @@ static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channe case SENSOR_CHAN_MAGN_XYZ: channel.chan_type = SENSOR_CHAN_MAGN_X; break; + case SENSOR_CHAN_POS_DXYZ: + channel.chan_type = SENSOR_CHAN_POS_DX; + break; default: break; } @@ -343,6 +346,7 @@ int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, case SENSOR_CHAN_POS_DX: case SENSOR_CHAN_POS_DY: case SENSOR_CHAN_POS_DZ: + case SENSOR_CHAN_POS_DXYZ: *base_size = sizeof(struct sensor_three_axis_data); *frame_size = sizeof(struct sensor_three_axis_sample_data); return 0; @@ -481,6 +485,7 @@ static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, case SENSOR_CHAN_POS_DX: case SENSOR_CHAN_POS_DY: case SENSOR_CHAN_POS_DZ: + case SENSOR_CHAN_POS_DXYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_POS_DX, SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, chan_spec.chan_idx); diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index e175d6d05fa51b..7edefe69ea1101 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -86,6 +86,7 @@ static const char *sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = { [SENSOR_CHAN_POS_DX] = "pos_dx", [SENSOR_CHAN_POS_DY] = "pos_dy", [SENSOR_CHAN_POS_DZ] = "pos_dz", + [SENSOR_CHAN_POS_DXYZ] = "pos_dxyz", [SENSOR_CHAN_RPM] = "rpm", [SENSOR_CHAN_GAUGE_VOLTAGE] = "gauge_voltage", [SENSOR_CHAN_GAUGE_AVG_CURRENT] = "gauge_avg_current", @@ -364,6 +365,7 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_POS_DX: case SENSOR_CHAN_POS_DY: case SENSOR_CHAN_POS_DZ: continue; @@ -392,7 +394,7 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: - case SENSOR_CHAN_POS_DX: { + case SENSOR_CHAN_POS_DXYZ: { struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)decoded_buffer; @@ -446,7 +448,7 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: - case SENSOR_CHAN_POS_DX: { + case SENSOR_CHAN_POS_DXYZ: { struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)decoded_buffer; diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index 2bd6b5c5b892d8..b227fd72002f81 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -150,6 +150,8 @@ enum sensor_channel { SENSOR_CHAN_POS_DY, /** Position change on the Z axis, in points. */ SENSOR_CHAN_POS_DZ, + /** Position change on the X, Y and Z axis, in points. */ + SENSOR_CHAN_POS_DXYZ, /** Revolutions per minute, in RPM. */ SENSOR_CHAN_RPM, @@ -929,12 +931,12 @@ struct __attribute__((__packed__)) sensor_data_generic_header { * * @param[in] chan The channel to check * @retval true if @p chan is any of @ref SENSOR_CHAN_ACCEL_XYZ, @ref SENSOR_CHAN_GYRO_XYZ, or - * @ref SENSOR_CHAN_MAGN_XYZ + * @ref SENSOR_CHAN_MAGN_XYZ, or @ref SENSOR_CHAN_POS_DXYZ * @retval false otherwise */ #define SENSOR_CHANNEL_3_AXIS(chan) \ ((chan) == SENSOR_CHAN_ACCEL_XYZ || (chan) == SENSOR_CHAN_GYRO_XYZ || \ - (chan) == SENSOR_CHAN_MAGN_XYZ) + (chan) == SENSOR_CHAN_MAGN_XYZ || (chan) == SENSOR_CHAN_POS_DXYZ) /** * @brief Get the sensor's decoder API diff --git a/include/zephyr/drivers/sensor_data_types.h b/include/zephyr/drivers/sensor_data_types.h index dd7f1f39c6d185..e1a2bc5c3e4013 100644 --- a/include/zephyr/drivers/sensor_data_types.h +++ b/include/zephyr/drivers/sensor_data_types.h @@ -47,6 +47,7 @@ struct sensor_data_header { * - :c:enum:`SENSOR_CHAN_POS_DX` * - :c:enum:`SENSOR_CHAN_POS_DY` * - :c:enum:`SENSOR_CHAN_POS_DZ` + * - :c:enum:`SENSOR_CHAN_POS_DXYZ` */ struct sensor_three_axis_data { struct sensor_data_header header; diff --git a/samples/sensor/sensor_shell/pytest/test_sensor_shell.py b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py index 9cbca8ea36f38a..7a01bec9978c7d 100644 --- a/samples/sensor/sensor_shell/pytest/test_sensor_shell.py +++ b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py @@ -25,12 +25,12 @@ def test_sensor_shell_get(shell: Shell): assert any(['channel type=31(voltage)' in line for line in lines]), 'expected response not found' lines = shell.exec_command('sensor get sensor@1 53') - assert any(['channel type=53(gauge_time_to_empty)' in line for line in lines]), 'expected response not found' + assert any(['channel type=53(gauge_state_of_health)' in line for line in lines]), 'expected response not found' # Channel should be the last one before 'all' (because 'all' doesn't print anything) so that the # for-loop in `parse_named_int()` will go through everything lines = shell.exec_command('sensor get sensor@0 gauge_desired_charging_current') - assert any(['channel type=58(gauge_desired_charging_current)' in line for line in lines]), 'expected response not found' + assert any(['channel type=59(gauge_desired_charging_current)' in line for line in lines]), 'expected response not found' logger.info('response is valid') @@ -42,7 +42,7 @@ def test_sensor_shell_attr_get(shell: Shell): assert any(['sensor@0(channel=co2, attr=sampling_frequency)' in line for line in lines]), 'expected response not found' lines = shell.exec_command('sensor attr_get sensor@1 53 3') - assert any(['sensor@1(channel=gauge_time_to_empty, attr=slope_th)' in line for line in lines]), 'expected response not found' + assert any(['sensor@1(channel=gauge_state_of_health, attr=slope_th)' in line for line in lines]), 'expected response not found' logger.info('response is valid') @@ -55,7 +55,7 @@ def test_sensor_shell_attr_set(shell: Shell): assert any([expected_line in line for line in lines]), 'expected response not found' lines = shell.exec_command('sensor attr_set sensor@1 53 3 1') - expected_line = 'sensor@1 channel=gauge_time_to_empty, attr=slope_th set to value=1' + expected_line = 'sensor@1 channel=gauge_state_of_health, attr=slope_th set to value=1' assert any([expected_line in line for line in lines]), 'expected response not found' logger.info('response is valid') diff --git a/samples/sensor/sensor_shell/src/fake_sensor.c b/samples/sensor/sensor_shell/src/fake_sensor.c index 212ef5e0565560..2d6df21251a83d 100644 --- a/samples/sensor/sensor_shell/src/fake_sensor.c +++ b/samples/sensor/sensor_shell/src/fake_sensor.c @@ -56,6 +56,8 @@ static int channel_get(const struct device *dev, enum sensor_channel chan, struc case SENSOR_CHAN_GYRO_XYZ: __fallthrough; case SENSOR_CHAN_MAGN_XYZ: + __fallthrough; + case SENSOR_CHAN_POS_DXYZ: for (int i = 0; i < 3; i++, val++) { val->val1 = chan; val->val2 = 1; From 900359a304360f8dbf6e9dbe08ee09cc4f7ba65b Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1310/1389] boards: nrf54h20dk: Add SUIT storage definition Add a definition of SUIT storage, so there will be a common source of the SUIT storage location for both SDFW and scripts generating SUIT storage areas, assigned to local domains. Signed-off-by: Tomasz Chyrowicz --- dts/common/nordic/nrf54h20.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 4e71c0be76945e..0e429ab3a9dd21 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -74,6 +74,10 @@ #address-cells = <1>; #size-cells = <1>; + suit_storage_partition: memory@e1eb000 { + reg = <0xe1eb000 DT_SIZE_K(24)>; + }; + cpurad_uicr_ext: memory@e1ff000 { reg = <0xe1ff000 DT_SIZE_K(2)>; }; From 0a3c3b9f30b8705bbe28ee7c9857349d64bb3ea5 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1311/1389] samples: subsys: ipc: ipc_service: keep using remote harness Temporary solution as there is no such harness as remote. However console regex are not defined yet. Signed-off-by: Piotr Kosycarz --- samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml index 401bbf517357fa..c9ebfbadde1d30 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml @@ -14,6 +14,7 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true + harness: remote extra_args: DTC_OVERLAY_FILE=boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay remote_DTC_OVERLAY_FILE=boards/nrf5340dk_nrf5340_cpunet_icbmsg.overlay From 6f9dd19ee7a388aa59b87b213814f00c73ed86f8 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1312/1389] drivers: spi: stm32: Skip pinctrl suspend/resume for subghzspi Subghzspi instances cannot have any pinctrl configs. This causes a failure of the power management suspend and resume operations for the subghzspi instance because no "default" pinctrl is found. Fix that by skipping the pinctrl parts on subghzspi instances. At the same time fix a copy and paste in the suspend error message. Fixes: b567a7db83ae Signed-off-by: Aurelien Jarno --- drivers/spi/spi_ll_stm32.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 7b557ebd07b5c1..1fa3ea167d7384 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -1241,10 +1241,12 @@ static int spi_stm32_pm_action(const struct device *dev, switch (action) { case PM_DEVICE_ACTION_RESUME: - /* Set pins to active state */ - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (err < 0) { - return err; + if (!spi_stm32_is_subghzspi(dev)) { + /* Set pins to active state */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + return err; + } } /* enable clock */ @@ -1258,21 +1260,24 @@ static int spi_stm32_pm_action(const struct device *dev, /* Stop device clock. */ err = clock_control_off(clk, (clock_control_subsys_t)&config->pclken[0]); if (err != 0) { - LOG_ERR("Could not enable SPI clock"); + LOG_ERR("Could not disable SPI clock"); return err; } - /* Move pins to sleep state */ - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); - if ((err < 0) && (err != -ENOENT)) { - /* - * If returning -ENOENT, no pins where defined for sleep mode : - * Do not output on console (might sleep already) when going to sleep, - * "SPI pinctrl sleep state not available" - * and don't block PM suspend. - * Else return the error. - */ - return err; + if (!spi_stm32_is_subghzspi(dev)) { + /* Move pins to sleep state */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if ((err < 0) && (err != -ENOENT)) { + /* + * If returning -ENOENT, no pins where defined for sleep mode : + * Do not output on console (might sleep already) when going to + * sleep, + * "SPI pinctrl sleep state not available" + * and don't block PM suspend. + * Else return the error. + */ + return err; + } } break; default: From f1bef0ed6da77dcf283d2af2610f8d6e59566e5c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1313/1389] drivers/flash/spi_nor: Fix and rework spi_nor_set_address_mode The commit removes unneeded check for enter_4byte_addr_exist in the function, as the utility function is supposed to set the address by parsing enter_4byte_addr parameter, while the enter_4byte_addr_exist used to exist only for DTS entries that directly set enter-4byte-addr parameters for a flash node. The change also moves LOG_DBG reporting enter_4byte_addr before it is processed, to allow logging what actually function will be working with, before it does so. The enter_4byte_addr_exist is removed as it is no longer used anywhere. Setting of data->flag_access_32bit has been moved in the same code block as call to the spi_nor_cmd_write, as it can be only consequence of successful call to that function. Signed-off-by: Dominik Ermel --- drivers/flash/spi_nor.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index f0b4df33590f47..79d6410f994394 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -155,7 +155,6 @@ struct spi_nor_config { bool dpd_exist:1; bool dpd_wakeup_sequence_exist:1; bool mxicy_mx25r_power_mode_exist:1; - bool enter_4byte_addr_exist:1; bool reset_gpios_exist:1; bool requires_ulbpr_exist:1; bool wp_gpios_exist:1; @@ -1034,10 +1033,10 @@ static int spi_nor_read_jedec_id(const struct device *dev, static int spi_nor_set_address_mode(const struct device *dev, uint8_t enter_4byte_addr) { - const struct spi_nor_config *cfg = dev->config; - int ret = -ENOSYS; + int ret = 0; + + LOG_DBG("Checking enter-4byte-addr %02x", enter_4byte_addr); - if (cfg->enter_4byte_addr_exist) { /* Do nothing if not provided (either no bits or all bits * set). */ @@ -1046,8 +1045,6 @@ static int spi_nor_set_address_mode(const struct device *dev, return 0; } - LOG_DBG("Checking enter-4byte-addr %02x", enter_4byte_addr); - /* This currently only supports command 0xB7 (Enter 4-Byte * Address Mode), with or without preceding WREN. */ @@ -1061,18 +1058,18 @@ static int spi_nor_set_address_mode(const struct device *dev, /* Enter after WREN. */ ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); } + if (ret == 0) { ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_4BA); - } - if (ret == 0) { - struct spi_nor_data *data = dev->data; + if (ret == 0) { + struct spi_nor_data *data = dev->data; - data->flag_access_32bit = true; + data->flag_access_32bit = true; + } } release_device(dev); - } return ret; } @@ -1655,7 +1652,6 @@ static const struct flash_driver_api spi_nor_api = { .dpd_exist = DT_INST_PROP(idx, has_dpd), \ .dpd_wakeup_sequence_exist = DT_INST_NODE_HAS_PROP(idx, dpd_wakeup_sequence), \ .mxicy_mx25r_power_mode_exist = DT_INST_NODE_HAS_PROP(idx, mxicy_mx25r_power_mode), \ - .enter_4byte_addr_exist = DT_INST_NODE_HAS_PROP(idx, enter_4byte_addr), \ .reset_gpios_exist = DT_INST_NODE_HAS_PROP(idx, reset_gpios), \ .requires_ulbpr_exist = DT_INST_PROP(idx, requires_ulbpr), \ .wp_gpios_exist = DT_INST_NODE_HAS_PROP(idx, wp_gpios), \ From f25ec2558fa26f572a913f5721528775a27f4959 Mon Sep 17 00:00:00 2001 From: Alex Bellon Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1314/1389] docs: security: Create CVE-2024 section Create new section for CVE-2024. Signed-off-by: Alex Bellon --- doc/security/vulnerabilities.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/security/vulnerabilities.rst b/doc/security/vulnerabilities.rst index 33ebd3f3d9b79b..77f39e79ea1f28 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1687,6 +1687,9 @@ This has been fixed in main for v3.6.0 - `PR 66887 fix for 2.7 `_ +CVE-2024 +======== + CVE-2024-1638 ------------- From 10c89948aa974e3a12cf7c1daef59ee19b3e0e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1315/1389] tests: drivers: clock_control: nrf_lf_clock_start: Fix SYNTH test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test was not covering nrf54l15 which had Synth source bitfield renamed. Changing the test to use Kconfig to determine if Synth is present. Signed-off-by: Krzysztof Chruściński --- tests/drivers/clock_control/nrf_lf_clock_start/src/main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/drivers/clock_control/nrf_lf_clock_start/src/main.c b/tests/drivers/clock_control/nrf_lf_clock_start/src/main.c index f1b1e52c7c51e6..b2524e94409160 100644 --- a/tests/drivers/clock_control/nrf_lf_clock_start/src/main.c +++ b/tests/drivers/clock_control/nrf_lf_clock_start/src/main.c @@ -38,15 +38,12 @@ static void rc_check(bool on, nrf_clock_lfclk_t type) static void synth_check(bool on, nrf_clock_lfclk_t type) { - #if !defined(CLOCK_LFCLKSRC_SRC_Synth) && \ - !defined(CLOCK_LFCLKSRC_SRC_LFSYNT) - #define NRF_CLOCK_LFCLK_SYNTH 0 - #endif - +#ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH if (!IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT)) { zassert_true(on, "Clock should be on"); zassert_equal(type, NRF_CLOCK_LFCLK_SYNTH); } +#endif } ZTEST(nrf_lf_clock_start, test_clock_check) From 84df2be6cce3f642d1daf6c94509c7f6dbcbb785 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1316/1389] flash: spi_nor: error-checking fixes Check the return values of commands such as spi_nor_cmd_* and spi_nor_wait_until_ready and ensure they are propagated back to the caller on error. Signed-off-by: Robert Hancock --- drivers/flash/spi_nor.c | 74 +++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index 79d6410f994394..1c46a9103ef572 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -624,13 +624,15 @@ static int spi_nor_wrsr(const struct device *dev, { int ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); - if (ret == 0) { - ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, &sr, - sizeof(sr)); - spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); + if (ret != 0) { + return ret; } - - return ret; + ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, &sr, + sizeof(sr)); + if (ret != 0) { + return ret; + } + return spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); } #if ANY_INST_HAS_MXICY_MX25R_POWER_MODE @@ -692,18 +694,23 @@ static int mxicy_wrcr(const struct device *dev, } ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); + if (ret != 0) { + return ret; + } - if (ret == 0) { - uint8_t data[] = { - sr, - cr & 0xFF, /* Configuration register 1 */ - cr >> 8 /* Configuration register 2 */ - }; - - ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, - data, sizeof(data)); - spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); + uint8_t data[] = { + sr, + cr & 0xFF, /* Configuration register 1 */ + cr >> 8 /* Configuration register 2 */ + }; + + ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, + data, sizeof(data)); + if (ret != 0) { + return ret; } + + ret = spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); } return ret; @@ -851,7 +858,10 @@ static int spi_nor_write(const struct device *dev, off_t addr, src = (const uint8_t *)src + to_write; addr += to_write; - spi_nor_wait_until_ready(dev, WAIT_READY_WRITE); + ret = spi_nor_wait_until_ready(dev, WAIT_READY_WRITE); + if (ret != 0) { + break; + } } } @@ -889,11 +899,14 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) ret = spi_nor_write_protection_set(dev, false); while ((size > 0) && (ret == 0)) { - spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); + ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); + if (ret) { + break; + } if (size == flash_size) { /* chip erase */ - spi_nor_cmd_write(dev, SPI_NOR_CMD_CE); + ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_CE); size -= flash_size; } else { const struct jesd216_erase_type *erase_types = @@ -913,7 +926,7 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) } } if (bet != NULL) { - spi_nor_cmd_addr_write(dev, bet->cmd, addr, NULL, 0); + ret = spi_nor_cmd_addr_write(dev, bet->cmd, addr, NULL, 0); addr += BIT(bet->exp); size -= BIT(bet->exp); } else { @@ -922,18 +935,11 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) ret = -EINVAL; } } + if (ret != 0) { + break; + } -#ifdef __XCC__ - /* - * FIXME: remove this hack once XCC is fixed. - * - * Without this volatile return value, XCC would segfault - * compiling this file complaining about failure in CGPREP - * phase. - */ - volatile int xcc_ret = -#endif - spi_nor_wait_until_ready(dev, WAIT_READY_ERASE); + ret = spi_nor_wait_until_ready(dev, WAIT_READY_ERASE); } int ret2 = spi_nor_write_protection_set(dev, true); @@ -1321,9 +1327,13 @@ static int spi_nor_configure(const struct device *dev) rc = spi_nor_rdsr(dev); if (rc > 0 && (rc & SPI_NOR_WIP_BIT)) { LOG_WRN("Waiting until flash is ready"); - spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); + rc = spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); } release_device(dev); + if (rc < 0) { + LOG_ERR("Failed to wait until flash is ready (%d)", rc); + return -ENODEV; + } /* now the spi bus is configured, we can verify SPI * connectivity by reading the JEDEC ID. From 47c17a07cc33c281f620e70ee91e49b9017cb118 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1317/1389] lib: open-amp: Use fixed width types for resource table This structure is shared between cores which may have different type widths. Use fixed width types when defining the structure. We can also use struct resource_table to help as it is already defined with fixed width types and removes the need to redefine these elements. Signed-off-by: Andrew Davis --- lib/open-amp/resource_table.c | 6 ++++-- lib/open-amp/resource_table.h | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/open-amp/resource_table.c b/lib/open-amp/resource_table.c index 2d58beb4b92899..8229a213ed5639 100644 --- a/lib/open-amp/resource_table.c +++ b/lib/open-amp/resource_table.c @@ -34,8 +34,10 @@ extern char ram_console[]; #define __resource Z_GENERIC_SECTION(.resource_table) static struct fw_resource_table __resource resource_table = { - .ver = 1, - .num = RSC_TABLE_NUM_ENTRY, + .hdr = { + .ver = 1, + .num = RSC_TABLE_NUM_ENTRY, + }, .offset = { #if (CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF > 0) diff --git a/lib/open-amp/resource_table.h b/lib/open-amp/resource_table.h index ba3b57e7ad824f..f3254ebb676a7b 100644 --- a/lib/open-amp/resource_table.h +++ b/lib/open-amp/resource_table.h @@ -41,10 +41,8 @@ enum rsc_table_entries { }; struct fw_resource_table { - unsigned int ver; - unsigned int num; - unsigned int reserved[2]; - unsigned int offset[RSC_TABLE_NUM_ENTRY]; + struct resource_table hdr; + uint32_t offset[RSC_TABLE_NUM_ENTRY]; #if (CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF > 0) struct fw_rsc_vdev vdev; From 874e0e376b31f0f8ebc9d062402bd85e0cd40e40 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1318/1389] lib: open-amp: Use struct fw_resource_table type instead of void The type of the resource table is known, casting to and from void* only hides this type which can prevent the compiler from giving helpful warnings. One warning would have been the accidental use of "st_resource_table" in a cast, a struct which does not exist. Use the fw_resource_table type when dealing with resource tables. Signed-off-by: Andrew Davis --- lib/open-amp/resource_table.c | 4 ++-- lib/open-amp/resource_table.h | 14 +++++++------- .../subsys/ipc/openamp_rsc_table/src/main_remote.c | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/open-amp/resource_table.c b/lib/open-amp/resource_table.c index 8229a213ed5639..53e38f185f0a36 100644 --- a/lib/open-amp/resource_table.c +++ b/lib/open-amp/resource_table.c @@ -74,8 +74,8 @@ static struct fw_resource_table __resource resource_table = { #endif }; -void rsc_table_get(void **table_ptr, int *length) +void rsc_table_get(struct fw_resource_table **table_ptr, int *length) { - *table_ptr = (void *)&resource_table; + *table_ptr = &resource_table; *length = sizeof(resource_table); } diff --git a/lib/open-amp/resource_table.h b/lib/open-amp/resource_table.h index f3254ebb676a7b..dc577fafa7edcd 100644 --- a/lib/open-amp/resource_table.h +++ b/lib/open-amp/resource_table.h @@ -56,23 +56,23 @@ struct fw_resource_table { #endif } METAL_PACKED_END; -void rsc_table_get(void **table_ptr, int *length); +void rsc_table_get(struct fw_resource_table **table_ptr, int *length); #if (CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF > 0) -inline struct fw_rsc_vdev *rsc_table_to_vdev(void *rsc_table) +inline struct fw_rsc_vdev *rsc_table_to_vdev(struct fw_resource_table *rsc_table) { - return &((struct fw_resource_table *)rsc_table)->vdev; + return &rsc_table->vdev; } -inline struct fw_rsc_vdev_vring *rsc_table_get_vring0(void *rsc_table) +inline struct fw_rsc_vdev_vring *rsc_table_get_vring0(struct fw_resource_table *rsc_table) { - return &((struct fw_resource_table *)rsc_table)->vring0; + return &rsc_table->vring0; } -inline struct fw_rsc_vdev_vring *rsc_table_get_vring1(void *rsc_table) +inline struct fw_rsc_vdev_vring *rsc_table_get_vring1(struct fw_resource_table *rsc_table) { - return &((struct fw_resource_table *)rsc_table)->vring1; + return &rsc_table->vring1; } #endif diff --git a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c index 8bc1a475d081b3..c8d12092ace05a 100644 --- a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c +++ b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c @@ -53,6 +53,7 @@ static const struct device *const ipm_handle = DEVICE_DT_GET(DT_CHOSEN(zephyr_ipc)); static metal_phys_addr_t shm_physmap = SHM_START_ADDR; +static metal_phys_addr_t rsc_tab_physmap; static struct metal_io_region shm_io_data; /* shared memory */ static struct metal_io_region rsc_io_data; /* rsc_table memory */ @@ -67,7 +68,7 @@ static struct metal_io_region *shm_io = &shm_io_data; static struct metal_io_region *rsc_io = &rsc_io_data; static struct rpmsg_virtio_device rvdev; -static void *rsc_table; +static struct fw_resource_table *rsc_table; static struct rpmsg_device *rpdev; static char rx_sc_msg[20]; /* should receive "Hello world!" */ @@ -139,7 +140,6 @@ int mailbox_notify(void *priv, uint32_t id) int platform_init(void) { - void *rsc_tab_addr; int rsc_size; struct metal_init_params metal_params = METAL_INIT_DEFAULTS; int status; @@ -155,11 +155,11 @@ int platform_init(void) SHM_SIZE, -1, 0, NULL); /* declare resource table region */ - rsc_table_get(&rsc_tab_addr, &rsc_size); - rsc_table = (struct st_resource_table *)rsc_tab_addr; + rsc_table_get(&rsc_table, &rsc_size); + rsc_tab_physmap = (uintptr_t)rsc_table; metal_io_init(rsc_io, rsc_table, - (metal_phys_addr_t *)rsc_table, rsc_size, -1, 0, NULL); + &rsc_tab_physmap, rsc_size, -1, 0, NULL); /* setup IPM */ if (!device_is_ready(ipm_handle)) { From 5931d9260ad8d23618b966f369dd5bfe247e3a2e Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1319/1389] drivers: mbox: Add driver for STM32 HSEM This driver implements a simple MBOX device which supports a single instance, two channels (one for each direction), and only signalling mode with no data transfer. Signalling to another core is achieved by taking and giving two hardware semaphores, similar to the STM32 HSEM IPM driver. Signed-off-by: Celina Sophie Kalus --- drivers/mbox/CMakeLists.txt | 1 + drivers/mbox/Kconfig | 1 + drivers/mbox/Kconfig.stm32_hsem | 8 + drivers/mbox/mbox_stm32_hsem.c | 259 ++++++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 drivers/mbox/Kconfig.stm32_hsem create mode 100644 drivers/mbox/mbox_stm32_hsem.c diff --git a/drivers/mbox/CMakeLists.txt b/drivers/mbox/CMakeLists.txt index 1d5c65cded7704..ce0cbbc6e9c5c6 100644 --- a/drivers/mbox/CMakeLists.txt +++ b/drivers/mbox/CMakeLists.txt @@ -14,3 +14,4 @@ zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_LOCAL mbox_nrf_vevif_local.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_REMOTE mbox_nrf_vevif_remote.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_BELLBOARD_LOCAL mbox_nrf_bellboard_local.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_BELLBOARD_REMOTE mbox_nrf_bellboard_remote.c) +zephyr_library_sources_ifdef(CONFIG_MBOX_STM32_HSEM mbox_stm32_hsem.c) diff --git a/drivers/mbox/Kconfig b/drivers/mbox/Kconfig index 7f00324ba474ab..ba72f0e894f58a 100644 --- a/drivers/mbox/Kconfig +++ b/drivers/mbox/Kconfig @@ -19,6 +19,7 @@ source "drivers/mbox/Kconfig.nxp_mailbox" source "drivers/mbox/Kconfig.andes" source "drivers/mbox/Kconfig.nrf_vevif" source "drivers/mbox/Kconfig.nrf_bellboard" +source "drivers/mbox/Kconfig.stm32_hsem" config MBOX_INIT_PRIORITY int "MBOX init priority" diff --git a/drivers/mbox/Kconfig.stm32_hsem b/drivers/mbox/Kconfig.stm32_hsem new file mode 100644 index 00000000000000..586061bccbc691 --- /dev/null +++ b/drivers/mbox/Kconfig.stm32_hsem @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Celina Sophie Kalus +# SPDX-License-Identifier: Apache-2.0 + +config MBOX_STM32_HSEM + bool "MBOX STM32 HSEM driver" + depends on DT_HAS_ST_MBOX_STM32_HSEM_ENABLED + help + MBOX Driver for STM32 hardware semaphore diff --git a/drivers/mbox/mbox_stm32_hsem.c b/drivers/mbox/mbox_stm32_hsem.c new file mode 100644 index 00000000000000..a1e9ca92607f00 --- /dev/null +++ b/drivers/mbox/mbox_stm32_hsem.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include + +#include "stm32_hsem.h" + +LOG_MODULE_REGISTER(mbox_stm32_hsem_ipc, CONFIG_MBOX_LOG_LEVEL); + +#define DT_DRV_COMPAT st_mbox_stm32_hsem + +#define HSEM_CPU1 1 +#define HSEM_CPU2 2 + +#if DT_NODE_EXISTS(DT_NODELABEL(cpu0)) +#define HSEM_CPU_ID HSEM_CPU1 +#elif DT_NODE_EXISTS(DT_NODELABEL(cpu1)) +#define HSEM_CPU_ID HSEM_CPU2 +#else +#error "Neither cpu0 nor cpu1 defined!" +#endif + +#if HSEM_CPU_ID == HSEM_CPU1 +#define MBOX_TX_HSEM_ID CFG_HW_IPM_CPU2_SEMID +#define MBOX_RX_HSEM_ID CFG_HW_IPM_CPU1_SEMID +#else /* HSEM_CPU2 */ +#define MBOX_TX_HSEM_ID CFG_HW_IPM_CPU1_SEMID +#define MBOX_RX_HSEM_ID CFG_HW_IPM_CPU2_SEMID +#endif /* HSEM_CPU_ID */ + +#define MAX_CHANNELS 2 + +struct mbox_stm32_hsem_data { + const struct device *dev; + mbox_callback_t cb; + void *user_data; +}; + +static struct mbox_stm32_hsem_data stm32_hsem_mbox_data; + +static struct mbox_stm32_hsem_conf { + struct stm32_pclken pclken; +} stm32_hsem_mbox_conf = { + .pclken = { + .bus = DT_INST_CLOCKS_CELL(0, bus), + .enr = DT_INST_CLOCKS_CELL(0, bits) + }, +}; + +static inline void stm32_hsem_enable_rx_interrupt(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + LL_HSEM_EnableIT_C1IER(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + LL_HSEM_EnableIT_C2IER(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline void stm32_hsem_disable_rx_interrupt(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + LL_HSEM_DisableIT_C1IER(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + LL_HSEM_DisableIT_C2IER(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline void stm32_hsem_clear_rx_interrupt(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + LL_HSEM_ClearFlag_C1ICR(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + LL_HSEM_ClearFlag_C2ICR(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline uint32_t stm32_hsem_is_rx_interrupt_active(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + return LL_HSEM_IsActiveFlag_C1ISR(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + return LL_HSEM_IsActiveFlag_C2ISR(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline bool is_rx_channel_valid(const struct device *dev, uint32_t ch) +{ + /* Only support one RX channel */ + return (ch == MBOX_RX_HSEM_ID); +} + +static inline bool is_tx_channel_valid(const struct device *dev, uint32_t ch) +{ + /* Only support one TX channel */ + return (ch == MBOX_TX_HSEM_ID); +} + +static void mbox_dispatcher(const struct device *dev) +{ + struct mbox_stm32_hsem_data *data = dev->data; + + /* Check semaphore rx_semid interrupt status */ + if (!stm32_hsem_is_rx_interrupt_active()) + return; + + if (data->cb != NULL) { + data->cb(dev, MBOX_RX_HSEM_ID, data->user_data, NULL); + } + + /* Clear semaphore rx_semid interrupt status and masked status */ + stm32_hsem_clear_rx_interrupt(); +} + +static int mbox_stm32_hsem_send(const struct device *dev, uint32_t channel, + const struct mbox_msg *msg) +{ + if (msg) { + LOG_ERR("Sending data not supported."); + return -EINVAL; + } + + if (!is_tx_channel_valid(dev, channel)) { + return -EINVAL; + } + + /* + * Locking and unlocking the hardware semaphore + * causes an interrupt on the receiving side. + */ + z_stm32_hsem_lock(MBOX_TX_HSEM_ID, HSEM_LOCK_DEFAULT_RETRY); + z_stm32_hsem_unlock(MBOX_TX_HSEM_ID); + + return 0; +} + +static int mbox_stm32_hsem_register_callback(const struct device *dev, uint32_t channel, + mbox_callback_t cb, void *user_data) +{ + struct mbox_stm32_hsem_data *data = dev->data; + + if (!(is_rx_channel_valid(dev, channel))) { + return -EINVAL; + } + + data->cb = cb; + data->user_data = user_data; + + return 0; +} + +static int mbox_stm32_hsem_mtu_get(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* We only support signalling */ + return 0; +} + +static uint32_t mbox_stm32_hsem_max_channels_get(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Only two channels supported, one RX and one TX */ + return MAX_CHANNELS; +} + +static int mbox_stm32_hsem_set_enabled(const struct device *dev, uint32_t channel, bool enable) +{ + if (!is_rx_channel_valid(dev, channel)) { + return -EINVAL; + } + + if (enable) { + stm32_hsem_clear_rx_interrupt(); + stm32_hsem_enable_rx_interrupt(); + } else { + stm32_hsem_disable_rx_interrupt(); + } + + return 0; +} + +#if HSEM_CPU_ID == HSEM_CPU1 +static int mbox_stm32_clock_init(const struct device *dev) +{ + const struct mbox_stm32_hsem_conf *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + if (!device_is_ready(clk)) { + LOG_ERR("Clock control device not ready."); + return -ENODEV; + } + + if (clock_control_on(clk, (clock_control_subsys_t *)&cfg->pclken) != 0) { + LOG_WRN("Failed to enable clock."); + return -EIO; + } + + return 0; +} +#endif /* HSEM_CPU_ID */ + +static int mbox_stm32_hsem_init(const struct device *dev) +{ + struct mbox_stm32_hsem_data *data = dev->data; + int ret = 0; + + data->dev = dev; + +#if HSEM_CPU_ID == HSEM_CPU1 + ret = mbox_stm32_clock_init(dev); + + if (ret != 0) { + return ret; + } +#endif /* HSEM_CPU_ID */ + + /* Configure interrupt service routine */ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + mbox_dispatcher, DEVICE_DT_INST_GET(0), 0); + + irq_enable(DT_INST_IRQN(0)); + + return ret; +} + +static const struct mbox_driver_api mbox_stm32_hsem_driver_api = { + .send = mbox_stm32_hsem_send, + .register_callback = mbox_stm32_hsem_register_callback, + .mtu_get = mbox_stm32_hsem_mtu_get, + .max_channels_get = mbox_stm32_hsem_max_channels_get, + .set_enabled = mbox_stm32_hsem_set_enabled, +}; + +DEVICE_DT_INST_DEFINE( + 0, + mbox_stm32_hsem_init, + NULL, + &stm32_hsem_mbox_data, + &stm32_hsem_mbox_conf, + POST_KERNEL, + CONFIG_MBOX_INIT_PRIORITY, + &mbox_stm32_hsem_driver_api); From 4f5094d0adfc808400b605ba523565cb23063f2d Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1320/1389] dts: bindings: mbox: Add STM32 HSEM MBOX driver Add a device tree binding for the new driver. Since there already exists an IPM driver using the unsharable hardware semaphore interrupt, the new driver is not added to any boards or SOCs per default to avoid compatibility problems. See #37300 for the IPM driver. Signed-off-by: Celina Sophie Kalus --- dts/bindings/mbox/st,mbox-stm32-hsem.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 dts/bindings/mbox/st,mbox-stm32-hsem.yaml diff --git a/dts/bindings/mbox/st,mbox-stm32-hsem.yaml b/dts/bindings/mbox/st,mbox-stm32-hsem.yaml new file mode 100644 index 00000000000000..50226f31182428 --- /dev/null +++ b/dts/bindings/mbox/st,mbox-stm32-hsem.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Celina Sophie Kalus +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 HSEM MBOX + +compatible: "st,mbox-stm32-hsem" + +include: [base.yaml, mailbox-controller.yaml] + +properties: + clocks: + required: true + + interrupts: + required: true + +mbox-cells: + - channel From 22c4525dab2f69a751b30cc6cc8f669f8da17aa7 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1321/1389] dts: bindings: ipm: Add dummy mbox-cells property The MBOX driver interface expects a device tree property '#mbox-cells' which is not known by the IPM driver. This causes build problems when both drivers are given for a single shared DT node. To fix this problem for this driver specifically, add a dummy '#mbox-cells' property to the bindings of the STM32 HSEM IPM driver. This does not affect any other IPM driver, and the STM32 HSEM IPM driver is still functioning with this dummy property. Signed-off-by: Celina Sophie Kalus --- dts/bindings/ipm/st,stm32-hsem-mailbox.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml b/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml index 813ca865f97b3c..c8df24f2572cf1 100644 --- a/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml +++ b/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml @@ -13,3 +13,11 @@ properties: interrupts: required: true + + "#mbox-cells": + type: int + description: | + Dummy property for device tree compatibility with MBOX driver. + +mbox-cells: + - channel From 8f4adf37b6bc2e1462db3751be2d3830392330f0 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1322/1389] samples: ipc: icmsg: Add received bytes metric By adding this metric, any problem with the remote core sending messages is observable. Signed-off-by: Celina Sophie Kalus --- samples/subsys/ipc/ipc_service/icmsg/src/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/samples/subsys/ipc/ipc_service/icmsg/src/main.c b/samples/subsys/ipc/ipc_service/icmsg/src/main.c index d10fa6c8bf6bb4..4556b7687f33c4 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/src/main.c +++ b/samples/subsys/ipc/ipc_service/icmsg/src/main.c @@ -21,8 +21,12 @@ K_SEM_DEFINE(bound_sem, 0, 1); static unsigned char expected_message = 'A'; static size_t expected_len = PACKET_SIZE_START; +static size_t received; + static void ep_bound(void *priv) { + received = 0; + k_sem_give(&bound_sem); LOG_INF("Ep bounded"); } @@ -36,6 +40,7 @@ static void ep_recv(const void *data, size_t len, void *priv) __ASSERT(len == expected_len, "Unexpected length. Expected %zu, got %zu", expected_len, len); + received += len; expected_message++; expected_len++; @@ -129,6 +134,8 @@ int main(void) LOG_INF("Wait 500ms. Let net core finish its sends"); k_msleep(500); + LOG_INF("Received %zu [Bytes] in total", received); + LOG_INF("Stop network core"); nrf53_cpunet_enable(false); From 17ccb07b6acfc1be95731b2e7e2d566cf9226ace Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1323/1389] samples: ipc: icmsg: Do not return busy error codes When sending a lot of data, a busy error code returned by the IPC is to be expected. But if the last attempted send returns busy, this error code is returned to the calling function, causing an error log message. Fix this by setting return variable to 0 on this acceptable error. Signed-off-by: Celina Sophie Kalus --- samples/subsys/ipc/ipc_service/icmsg/src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/ipc/ipc_service/icmsg/src/main.c b/samples/subsys/ipc/ipc_service/icmsg/src/main.c index 4556b7687f33c4..6d2d2216a3f9ea 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/src/main.c +++ b/samples/subsys/ipc/ipc_service/icmsg/src/main.c @@ -68,6 +68,7 @@ static int send_for_time(struct ipc_ept *ep, const int64_t sending_time_ms) ret = ipc_service_send(ep, &msg, mlen); if (ret == -ENOMEM) { /* No space in the buffer. Retry. */ + ret = 0; continue; } else if (ret < 0) { LOG_ERR("Failed to send (%c) failed with ret %d", msg.data[0], ret); From bfc13922858263a0f7aed79a6792381c6f414dae Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1324/1389] samples: ipc: icmsg: Add support for stm32h747i_disco With the addition of the STM32 hardware semaphore MBOX driver, ICMsg is now supported on the stm32h747i_disco board. Signed-off-by: Celina Sophie Kalus --- .../ipc/ipc_service/icmsg/CMakeLists.txt | 3 +- .../ipc/ipc_service/icmsg/Kconfig.sysbuild | 3 +- .../stm32h747i_disco_stm32h747xx_m7.conf | 1 + .../stm32h747i_disco_stm32h747xx_m7.overlay | 41 ++++++++++++++++ .../stm32h747i_disco_stm32h747xx_m4.conf | 5 ++ .../stm32h747i_disco_stm32h747xx_m4.overlay | 48 +++++++++++++++++++ .../subsys/ipc/ipc_service/icmsg/src/main.c | 4 ++ .../ipc/ipc_service/icmsg/sysbuild.cmake | 4 +- 8 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf create mode 100644 samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay create mode 100644 samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf create mode 100644 samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay diff --git a/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt b/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt index ca0ce8a8cff85a..43effdcf6ff5e5 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt +++ b/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt @@ -8,7 +8,8 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if(NOT CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) +if(NOT CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP AND + NOT CONFIG_BOARD_STM32H747I_DISCO) message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() diff --git a/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild b/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild index d0849e37ddef1f..2de1b5072e1c3e 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild +++ b/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild @@ -4,6 +4,7 @@ source "share/sysbuild/Kconfig" -config NET_CORE_BOARD +config REMOTE_BOARD string default "nrf5340dk/nrf5340/cpunet" if $(BOARD) = "nrf5340dk" + default "stm32h747i_disco/stm32h747xx/m4" if $(BOARD) = "stm32h747i_disco" diff --git a/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf new file mode 100644 index 00000000000000..acba758575a87b --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf @@ -0,0 +1 @@ +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay new file mode 100644 index 00000000000000..52a2facb9bf3ad --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,ipc_shm; + }; + + /* Define new memory regions for TX and RX */ + /delete-node/ memory@38000000; + + sram_tx: memory@38000000 { + zephyr,memory-region = "SRAM_TX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38000000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + sram_rx: memory@38008000 { + zephyr,memory-region = "SRAM_RX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38008000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&mailbox 11>, <&mailbox 10>; + mbox-names = "tx", "rx"; + status = "okay"; + }; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf new file mode 100644 index 00000000000000..110236f8fbde81 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf @@ -0,0 +1,5 @@ +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_LOG_BACKEND_UART=y + +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay new file mode 100644 index 00000000000000..4b8d6f59f4f531 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,ipc_shm; + + zephyr,console = &uart8; + zephyr,shell-uart = &uart8; + }; + + /* Define new memory regions for TX and RX */ + /delete-node/ memory@38000000; + + sram_rx: memory@38000000 { + zephyr,memory-region = "SRAM_RX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38000000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + sram_tx: memory@38008000 { + zephyr,memory-region = "SRAM_TX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38008000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&mailbox 10>, <&mailbox 11>; + mbox-names = "tx", "rx"; + status = "okay"; + }; +}; + +&uart8 { + status = "okay"; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/subsys/ipc/ipc_service/icmsg/src/main.c b/samples/subsys/ipc/ipc_service/icmsg/src/main.c index 6d2d2216a3f9ea..d3a7e695b9125e 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/src/main.c +++ b/samples/subsys/ipc/ipc_service/icmsg/src/main.c @@ -8,7 +8,9 @@ #include #include +#if CONFIG_NET_CORE_BOARD #include +#endif /* CONFIG_NET_CORE_BOARD */ #include #include "common.h" @@ -137,6 +139,7 @@ int main(void) LOG_INF("Received %zu [Bytes] in total", received); +#if CONFIG_NET_CORE_BOARD LOG_INF("Stop network core"); nrf53_cpunet_enable(false); @@ -175,6 +178,7 @@ int main(void) LOG_ERR("send_for_time() failure"); return ret; } +#endif /* CONFIG_NET_CORE_BOARD */ LOG_INF("IPC-service HOST demo ended"); diff --git a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake index d0d79b8f240840..b1f0947aff7c40 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake +++ b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake @@ -1,7 +1,7 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") +if ("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") message(FATAL_ERROR "Target ${BOARD} not supported for this sample. " "There is no remote board selected in Kconfig.sysbuild") @@ -10,5 +10,5 @@ endif() ExternalZephyrProject_Add( APPLICATION remote SOURCE_DIR ${APP_DIR}/remote - BOARD ${SB_CONFIG_NET_CORE_BOARD} + BOARD ${SB_CONFIG_REMOTE_BOARD} ) From 52ed375f029732bcf66a0a0078c673097050e611 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1325/1389] samples: drivers: mbox: Add support for stm32h747i_disco board With the addition of the STM32 hardware semaphore MBOX driver, this sample is now supported by the board. Signed-off-by: Celina Sophie Kalus --- samples/drivers/mbox/CMakeLists.txt | 3 ++- samples/drivers/mbox/Kconfig.sysbuild | 1 + .../stm32h747i_disco_stm32h747xx_m7.conf | 1 + .../stm32h747i_disco_stm32h747xx_m7.overlay | 17 ++++++++++++ samples/drivers/mbox/remote/CMakeLists.txt | 3 ++- .../stm32h747i_disco_stm32h747xx_m4.conf | 5 ++++ .../stm32h747i_disco_stm32h747xx_m4.overlay | 26 +++++++++++++++++++ 7 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf create mode 100644 samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay create mode 100644 samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf create mode 100644 samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay diff --git a/samples/drivers/mbox/CMakeLists.txt b/samples/drivers/mbox/CMakeLists.txt index d279843dacd24d..3ca0508ab8c64f 100644 --- a/samples/drivers/mbox/CMakeLists.txt +++ b/samples/drivers/mbox/CMakeLists.txt @@ -17,7 +17,8 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP OR CONFIG_BOARD_MIMXRT1170_EVK_MIMXRT1176_CM7 OR CONFIG_BOARD_MIMXRT1160_EVK_MIMXRT1166_CM7 OR CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0 OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP) + CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR + CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M7) message(STATUS "${BOARD}${BOARD_QUALIFIERS} compile as Main in this sample") else() message(FATAL_ERROR "${BOARD}${BOARD_QUALIFIERS} is not supported for this sample") diff --git a/samples/drivers/mbox/Kconfig.sysbuild b/samples/drivers/mbox/Kconfig.sysbuild index b8d7e17c29a362..c89a6f7b3f78be 100644 --- a/samples/drivers/mbox/Kconfig.sysbuild +++ b/samples/drivers/mbox/Kconfig.sysbuild @@ -15,3 +15,4 @@ string default "mimxrt1160_evk/mimxrt1166/cm4" if $(BOARD) = "mimxrt1160_evk" default "lpcxpresso55s69/lpc55s69/cpu1" if $(BOARD) = "lpcxpresso55s69" default "nrf54h20dk/nrf54h20/cpuppr" if $(BOARD) = "nrf54h20dk" + default "stm32h747i_disco/stm32h747xx/m4" if $(BOARD) = "stm32h747i_disco" diff --git a/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf new file mode 100644 index 00000000000000..acba758575a87b --- /dev/null +++ b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf @@ -0,0 +1 @@ +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay new file mode 100644 index 00000000000000..d86cbbc2d42ea1 --- /dev/null +++ b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + mbox-consumer { + compatible = "vnd,mbox-consumer"; + mboxes = <&mailbox 11>, <&mailbox 10>; + mbox-names = "tx", "rx"; + }; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/drivers/mbox/remote/CMakeLists.txt b/samples/drivers/mbox/remote/CMakeLists.txt index 9c19a0e8b46950..9bc1c67a61c08e 100644 --- a/samples/drivers/mbox/remote/CMakeLists.txt +++ b/samples/drivers/mbox/remote/CMakeLists.txt @@ -15,7 +15,8 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET OR CONFIG_BOARD_MIMXRT1170_EVK_MIMXRT1176_CM4 OR CONFIG_BOARD_MIMXRT1160_EVK_MIMXRT1166_CM4 OR CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU1 OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR) + CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR OR + CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M4) message(STATUS "${BOARD}${BOARD_QUALIFIERS} compile as remote in this sample") else() message(FATAL_ERROR "${BOARD}${BOARD_QUALIFIERS} is not supported for this sample") diff --git a/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf new file mode 100644 index 00000000000000..110236f8fbde81 --- /dev/null +++ b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf @@ -0,0 +1,5 @@ +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_LOG_BACKEND_UART=y + +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay new file mode 100644 index 00000000000000..c39e05aeb9c8d8 --- /dev/null +++ b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,console = &uart8; + zephyr,shell-uart = &uart8; + }; + + mbox-consumer { + compatible = "vnd,mbox-consumer"; + mboxes = <&mailbox 10>, <&mailbox 11>; + mbox-names = "tx", "rx"; + }; +}; + +&uart8 { + status = "okay"; +}; + +&mailbox { + status = "okay"; +}; From 4ea1f4aa655839a5819e532ebfb6eb99a2bf9c9e Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1326/1389] dts: stm32h7_dualcore: Add MBOX driver Adding the new STM32 hardware semaphore driver into the device tree. Signed-off-by: Celina Sophie Kalus --- dts/arm/st/h7/stm32h7_dualcore.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dts/arm/st/h7/stm32h7_dualcore.dtsi b/dts/arm/st/h7/stm32h7_dualcore.dtsi index 591d68b7916309..1ba052502ac157 100644 --- a/dts/arm/st/h7/stm32h7_dualcore.dtsi +++ b/dts/arm/st/h7/stm32h7_dualcore.dtsi @@ -17,9 +17,10 @@ soc { mailbox: mailbox@58026400 { - compatible = "st,stm32-hsem-mailbox"; + compatible = "st,stm32-hsem-mailbox", "st,mbox-stm32-hsem"; reg = <0x58026400 0x400>; clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x02000000>; + #mbox-cells = <1>; status = "disabled"; }; }; From 559bdc801f26e91878b07b7bec2679cb65961d3d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 22:39:38 +0200 Subject: [PATCH 1327/1389] drivers: timer: smartbond: Fix timer2 timeout set When function sys_clock_set_timout() is called with small value (i.e. 1) calculated time to be programmed to TIMER2 reload register may be such that is expires before code set's it up. In that case timer interrupt will be scheduled in far future. With this change, code checks after it sets reload value if requested time already passed and if so TIMER2 interrupt is marked as pending to avoid races. Signed-off-by: Jerzy Kasenberg --- drivers/timer/smartbond_timer.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/timer/smartbond_timer.c b/drivers/timer/smartbond_timer.c index 4ab03f5d956e06..9726b6d9b9af76 100644 --- a/drivers/timer/smartbond_timer.c +++ b/drivers/timer/smartbond_timer.c @@ -108,6 +108,18 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) target_val = ((target_val + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK; set_reload(target_val); + + /* + * If time was so small that it already fired or should fire + * just now, mark interrupt as pending to avoid losing timer event. + * Condition is true when target_val (point in time that should be + * used for wakeup) is behind timer value or is equal to it. + * In that case we don't know if reload value was set in time or + * not but time expired anyway so make sure that interrupt is pending. + */ + if ((int32_t)(target_val - timer_val_32_noupdate() - 1) < 0) { + NVIC_SetPendingIRQ(TIMER2_IRQn); + } } uint32_t sys_clock_elapsed(void) From 5fdb04bc713bbaa5ae12f82480e20b85dbc5fdf4 Mon Sep 17 00:00:00 2001 From: Ping Wang Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1328/1389] Bluetooth: Audio: Get function for bt_audio_codec_qos_pref. Get the preferred QoS settings via bt_bap_ep_get_info() Therefore no need to use the internal header file to get it. This PR fixes https://github.com/zephyrproject-rtos/zephyr/issues/72359 Signed-off-by: Ping Wang --- include/zephyr/bluetooth/audio/bap.h | 3 +++ subsys/bluetooth/audio/bap_stream.c | 1 + 2 files changed, 4 insertions(+) diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index cc96141213153c..4e67d594877851 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -410,6 +410,9 @@ struct bt_bap_ep_info { * otherwise NULL */ struct bt_bap_ep *paired_ep; + + /** Pointer to the preferred QoS settings associated with the endpoint */ + const struct bt_audio_codec_qos_pref *qos_pref; }; /** diff --git a/subsys/bluetooth/audio/bap_stream.c b/subsys/bluetooth/audio/bap_stream.c index e3f044cacb6fd3..6ac3fd8c5f5278 100644 --- a/subsys/bluetooth/audio/bap_stream.c +++ b/subsys/bluetooth/audio/bap_stream.c @@ -118,6 +118,7 @@ int bt_bap_ep_get_info(const struct bt_bap_ep *ep, struct bt_bap_ep_info *info) info->id = ep->status.id; info->state = ep->status.state; info->dir = dir; + info->qos_pref = &ep->qos_pref; if (ep->iso == NULL) { info->paired_ep = NULL; From efd9a6b22751896ab710b48d0251c727862fa160 Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1329/1389] net: wifi: Add disconnection success code When disconnect request is successful, the status was taking as WIFI_REASON_DISCONN_UNSPECIFIED only. Adding WIFI_REASON_DISCONN_SUCCESS which can be help to determine status of disconnect request. If this status is failed then reason can be useful. Signed-off-by: Kapil Bhatt --- include/zephyr/net/wifi_mgmt.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 0442a91c2f2fba..8c2b61fa936405 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -427,8 +427,10 @@ enum wifi_conn_status { * in the disconnect result event for detailed reason. */ enum wifi_disconn_reason { + /** Success, overload status as reason */ + WIFI_REASON_DISCONN_SUCCESS = 0, /** Unspecified reason */ - WIFI_REASON_DISCONN_UNSPECIFIED = WIFI_STATUS_DISCONN_FIRST_STATUS, + WIFI_REASON_DISCONN_UNSPECIFIED, /** Disconnected due to user request */ WIFI_REASON_DISCONN_USER_REQUEST, /** Disconnected due to AP leaving */ From 29b0ee124c7dc429a9cb6d58b31c7a916ec5487a Mon Sep 17 00:00:00 2001 From: Alexander Sarmanow Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1330/1389] samples: bluetooth: df: fix misleading comment in rx overlay The comment is talking about Tx and AoD, while this sample code is about Rx and AoA. Signed-off-by: Alexander Sarmanow --- .../boards/nrf52833dk_nrf52820.overlay | 4 ++-- .../boards/nrf52833dk_nrf52833.overlay | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay index cdda1ac13f729d..fa37e5f76de316 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay +++ b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay @@ -11,13 +11,13 @@ */ dfe-antenna-num = <10>; /* This is an example switch pattern that will be used to set an - * antenna for Tx PDU (period before start of Tx CTE). + * antenna for Rx PDU (period before start of Rx CTE). */ dfe-pdu-antenna = <0x1>; /* These are example GPIO pin numbers that are provided to * Radio peripheral. The pins will be acquired by Radio to - * drive antenna switching when AoD is enabled. + * drive antenna switching when AoA is enabled. */ dfegpio0-gpios = <&gpio0 3 0>; dfegpio1-gpios = <&gpio0 4 0>; diff --git a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay index cdda1ac13f729d..fa37e5f76de316 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay +++ b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay @@ -11,13 +11,13 @@ */ dfe-antenna-num = <10>; /* This is an example switch pattern that will be used to set an - * antenna for Tx PDU (period before start of Tx CTE). + * antenna for Rx PDU (period before start of Rx CTE). */ dfe-pdu-antenna = <0x1>; /* These are example GPIO pin numbers that are provided to * Radio peripheral. The pins will be acquired by Radio to - * drive antenna switching when AoD is enabled. + * drive antenna switching when AoA is enabled. */ dfegpio0-gpios = <&gpio0 3 0>; dfegpio1-gpios = <&gpio0 4 0>; From 8a0e1e648e3c4d5f73130ded35effba6a803d0d1 Mon Sep 17 00:00:00 2001 From: Nikolay Agishev Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1331/1389] DOC: ARCMWDT: Add tip for arc-gnu-toolchain installation Installation of single toolchain causes problems for customers who are not familiar with Zephyr infrastructure. This tip is supposed to help them. Signed-off-by: Nikolay Agishev --- doc/develop/toolchains/designware_arc_mwdt.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/develop/toolchains/designware_arc_mwdt.rst b/doc/develop/toolchains/designware_arc_mwdt.rst index 24d5d53dc1b226..f41976c8c98005 100644 --- a/doc/develop/toolchains/designware_arc_mwdt.rst +++ b/doc/develop/toolchains/designware_arc_mwdt.rst @@ -13,6 +13,9 @@ DesignWare ARC MetaWare Development Toolkit (MWDT) Even though ARC MWDT toolchain is used for Zephyr RTOS build, still the GNU preprocessor & GNU objcopy might be used for some steps like device tree preprocessing and ``.bin`` file generation. We used Zephyr SDK as a source of these ARC GNU tools as well. + To setup ARC GNU toolchain please use SDK Bundle (Full or Minimal) instead of manual installation + of separate tarballs. It installs and registers toolchain and host tools in the system, + that allows you to avoid toolchain related issues while building Zephyr. #. :ref:`Set these environment variables `: From e41d8ee898718c02b0419868316a024d41829d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1332/1389] tests: drivers: wdt_basic_api: Add missing failure indications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two API calls that are supposed to set up the watchdog are not actually causing the test to fail, only error messages are printed. This patch adds the proper return statements. Signed-off-by: Andrzej Głąbek --- tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c b/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c index 9415149c89f991..77a8e81fe0cffb 100644 --- a/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c +++ b/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c @@ -212,11 +212,13 @@ static int test_wdt_no_callback(void) err = wdt_install_timeout(wdt, &m_cfg_wdt0); if (err < 0) { TC_PRINT("Watchdog install error\n"); + return TC_FAIL; } err = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG); if (err < 0) { TC_PRINT("Watchdog setup error\n"); + return TC_FAIL; } TC_PRINT("Waiting to restart MCU\n"); From 8238a22205036c5ba5b7d4b2a1f67f0ba3c6feb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1333/1389] tests: drivers: wdt_basic_api: Allow testing without PAUSE_HALTED_BY_DBG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a follow-up to commit e53e5448eee2257ad360457ecfd79541381bba89. In the above commit, the calls to `wdt_setup()` were modified to use the `WDT_OPT_PAUSE_HALTED_BY_DBG` option to prevent problems with flashing of boards after this test was executed on them (the still active watchdog could interrupt such flashing), but this option is not essential to the test itself. And if a watchdog driver does not support pausing when the CPU is halted by a debugger (this is the case for example for wdt_counter), it is not able to pass the test because of that option. Add then the possibility to continue the test when pausing by debugger is not supported. Signed-off-by: Andrzej Głąbek --- tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c b/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c index 77a8e81fe0cffb..a92e54edb2766a 100644 --- a/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c +++ b/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c @@ -216,6 +216,10 @@ static int test_wdt_no_callback(void) } err = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG); + if (err == -ENOTSUP) { + TC_PRINT("- pausing watchdog by debugger is not supported\n"); + err = wdt_setup(wdt, 0); + } if (err < 0) { TC_PRINT("Watchdog setup error\n"); return TC_FAIL; @@ -270,6 +274,10 @@ static int test_wdt_callback_1(void) } err = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG); + if (err == -ENOTSUP) { + TC_PRINT("- pausing watchdog by debugger is not supported\n"); + err = wdt_setup(wdt, 0); + } if (err < 0) { TC_PRINT("Watchdog setup error\n"); return TC_FAIL; @@ -330,6 +338,10 @@ static int test_wdt_callback_2(void) } err = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG); + if (err == -ENOTSUP) { + TC_PRINT("- pausing watchdog by debugger is not supported\n"); + err = wdt_setup(wdt, 0); + } if (err < 0) { TC_PRINT("Watchdog setup error\n"); return TC_FAIL; From 55e45cda919b99d0dbd932def59b272359f092ee Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1334/1389] scripts: Allow using quarantine mechanism with test_plan.py script In twister, applying quarantine is a part of apply_filters() function. However, this function is not called when --load-test is used. Therefore, if one wants to use quarantines in combination with dynamic scope from the test_plan.py script, one has to pass such info through the script. Signed-off-by: Maciej Perkowski --- scripts/ci/test_plan.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 1bbfd331debd0c..edbbbf2d923be2 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -95,7 +95,7 @@ def __repr__(self): class Filters: def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, - pull_request=False, platforms=[], detailed_test_id=True, tc_roots_th=20): + pull_request=False, platforms=[], detailed_test_id=True, quarantine_list=None, tc_roots_th=20): self.modified_files = modified_files self.testsuite_root = testsuite_root self.resolved_files = [] @@ -108,6 +108,7 @@ def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, self.detailed_test_id = detailed_test_id self.ignore_path = ignore_path self.tag_cfg_file = alt_tags + self.quarantine_list = quarantine_list self.tc_roots_th = tc_roots_th def process(self): @@ -129,6 +130,9 @@ def get_plan(self, options, integration=False, use_testsuite_root=True): cmd+=["-T", root] if integration: cmd.append("--integration") + if self.quarantine_list: + for q in self.quarantine_list: + cmd += ["--quarantine-list", q] logging.info(" ".join(cmd)) _ = subprocess.call(cmd) @@ -414,6 +418,12 @@ def parse_args(): "testcase.yaml files under here will be processed. May be " "called multiple times. Defaults to the 'samples/' and " "'tests/' directories at the base of the Zephyr tree.") + parser.add_argument( + "--quarantine-list", action="append", metavar="FILENAME", + help="Load list of test scenarios under quarantine. The entries in " + "the file need to correspond to the test scenarios names as in " + "corresponding tests .yaml files. These scenarios " + "will be skipped with quarantine as the reason.") # Include paths in names by default. parser.set_defaults(detailed_test_id=True) @@ -442,7 +452,7 @@ def parse_args(): print("=========") f = Filters(files, args.ignore_path, args.alt_tags, args.testsuite_root, - args.pull_request, args.platform, args.detailed_test_id, + args.pull_request, args.platform, args.detailed_test_id, args.quarantine_list, args.testcase_roots_threshold) f.process() From 402623dd0f3f048a109f4fa0394ff87bd96d3daa Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1335/1389] intel-adsp/ace: pm: Only core 0 can d0i3 Secondary cores are not allowed to be power gated on runtime-idle. They have to explicitely set off by host command. Remove this state from secondary CPUs so power management logic does not need workarounds to enforce this behavior. Signed-off-by: Flavio Ceolin --- dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi | 4 +-- soc/intel/intel_adsp/ace/power.c | 29 +++++++-------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi index d9595311a974ad..15b7128aea5ede 100644 --- a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi @@ -25,14 +25,14 @@ device_type = "cpu"; compatible = "cdns,tensilica-xtensa-lx7"; reg = <1>; - cpu-power-states = <&d0i3 &d3>; + cpu-power-states = <&d3>; }; cpu2: cpu@2 { device_type = "cpu"; compatible = "cdns,tensilica-xtensa-lx7"; reg = <2>; - cpu-power-states = <&d0i3 &d3>; + cpu-power-states = <&d3>; }; power-states { diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index 2e260eb2f9cf74..0f3cf6a3815bd2 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -266,6 +266,7 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) { ARG_UNUSED(substate_id); uint32_t cpu = arch_proc_id(); + uint32_t battr; int ret; ARG_UNUSED(ret); @@ -340,19 +341,20 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) power_gate_entry(cpu); } break; + + /* Only core 0 handles this state */ case PM_STATE_RUNTIME_IDLE: + battr = DSPCS.bootctl[cpu].battr & (~LPSCTL_BATTR_MASK); + DSPCS.bootctl[cpu].bctl &= ~DSPBR_BCTL_WAITIPPG; DSPCS.bootctl[cpu].bctl &= ~DSPBR_BCTL_WAITIPCG; soc_cpu_power_down(cpu); - if (cpu == 0) { - uint32_t battr = DSPCS.bootctl[cpu].battr & (~LPSCTL_BATTR_MASK); - - battr |= (DSPBR_BATTR_LPSCTL_RESTORE_BOOT & LPSCTL_BATTR_MASK); - DSPCS.bootctl[cpu].battr = battr; - } + battr |= (DSPBR_BATTR_LPSCTL_RESTORE_BOOT & LPSCTL_BATTR_MASK); + DSPCS.bootctl[cpu].battr = battr; ret = pm_device_runtime_put(INTEL_ADSP_HST_DOMAIN_DEV); __ASSERT_NO_MSG(ret == 0); + power_gate_entry(cpu); break; default: @@ -395,17 +397,6 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) soc_cpus_active[cpu] = true; sys_cache_data_flush_and_invd_all(); } else if (state == PM_STATE_RUNTIME_IDLE) { - if (cpu != 0) { - /* NOTE: HW should support dynamic power gating on secondary cores. - * But since there is no real profit from it, functionality is not - * fully implemented. - * SOF PM policy will not allowed primary core to enter d0i3 state - * when secondary cores are active. - */ - __ASSERT(false, "state not supported on secondary core"); - return; - } - soc_cpu_power_up(cpu); if (!WAIT_FOR(soc_cpu_is_powered(cpu), @@ -418,9 +409,7 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) #else DSPCS.bootctl[cpu].bctl |= DSPBR_BCTL_WAITIPCG | DSPBR_BCTL_WAITIPPG; #endif /* CONFIG_ADSP_IDLE_CLOCK_GATING */ - if (cpu == 0) { - DSPCS.bootctl[cpu].battr &= (~LPSCTL_BATTR_MASK); - } + DSPCS.bootctl[cpu].battr &= (~LPSCTL_BATTR_MASK); soc_cpus_active[cpu] = true; sys_cache_data_flush_and_invd_all(); From 7795b07cd1fbe00ee41ac9371a3ebee8c819789e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1336/1389] intel_adsp/ace: pm: Remove unnecessary cache flush core_desc is not located (nor is accessed) in cached memory. There is no need to flush it. Signed-off-by: Flavio Ceolin --- soc/intel/intel_adsp/ace/power.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index 0f3cf6a3815bd2..70a519f24ba321 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -150,7 +150,13 @@ static ALWAYS_INLINE void _save_core_context(uint32_t core_id) core_desc[core_id].thread_ptr = XTENSA_RUR("THREADPTR"); __asm__ volatile("mov %0, a0" : "=r"(core_desc[core_id].a0)); __asm__ volatile("mov %0, a1" : "=r"(core_desc[core_id].a1)); + +#if CONFIG_MP_MAX_NUM_CPUS == 1 + /* With one core only, the memory is mapped in cache and we need to flush + * it. + */ sys_cache_data_flush_range(&core_desc[core_id], sizeof(struct core_state)); +#endif } static ALWAYS_INLINE void _restore_core_context(void) From 96eb8f3541d0f48c815ac7fc395a5459cb8d9ed1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1337/1389] intel_adsp/ace: pm: Keep irq locked until restore context Keep interruptions locked until we properly restore the core context. Signed-off-by: Flavio Ceolin --- 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 70a519f24ba321..9fd884904d9c45 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -224,7 +224,7 @@ __asm__(".align 4\n\t" "dsp_restore_vector:\n\t" " movi a0, 0\n\t" " movi a1, 1\n\t" - " movi a2, 0x40020\n\t"/* PS_UM|PS_WOE */ + " movi a2, " STRINGIFY(PS_UM | PS_WOE | PS_INTLEVEL(XCHAL_EXCM_LEVEL)) "\n\t" " wsr a2, PS\n\t" " wsr a1, WINDOWSTART\n\t" " wsr a0, WINDOWBASE\n\t" @@ -243,7 +243,7 @@ static ALWAYS_INLINE void power_off_exit(void) __asm__( " movi a0, 0\n\t" " movi a1, 1\n\t" - " movi a2, 0x40020\n\t"/* PS_UM|PS_WOE */ + " movi a2, " STRINGIFY(PS_UM | PS_WOE | PS_INTLEVEL(XCHAL_EXCM_LEVEL)) "\n\t" " wsr a2, PS\n\t" " wsr a1, WINDOWSTART\n\t" " wsr a0, WINDOWBASE\n\t" From d94e5d549de82673fd98b5685915fac9d741b691 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1338/1389] intel_adsp/ace: pm: Remove unnecessary cache flush soc_cpus_active is not in cached memory. Signed-off-by: Flavio Ceolin --- soc/intel/intel_adsp/ace/power.c | 1 - 1 file changed, 1 deletion(-) diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index 9fd884904d9c45..08f416e0326a3e 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -195,7 +195,6 @@ void power_gate_entry(uint32_t core_id) } soc_cpus_active[core_id] = false; - sys_cache_data_flush_range(soc_cpus_active, sizeof(soc_cpus_active)); k_cpu_idle(); /* It is unlikely we get in here, but when this happens From 0987bbdc87913dd586682f8e66e4264b7fc85451 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1339/1389] power_domain: intel_adsp: Use register definitions Make it a little bit easier to read using already existent definitions for the registers used here. Signed-off-by: Flavio Ceolin --- drivers/power_domain/power_domain_intel_adsp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/power_domain/power_domain_intel_adsp.c b/drivers/power_domain/power_domain_intel_adsp.c index 3f816c6914657f..50b4582507ac06 100644 --- a/drivers/power_domain/power_domain_intel_adsp.c +++ b/drivers/power_domain/power_domain_intel_adsp.c @@ -8,6 +8,7 @@ #include #include #include +#include #if CONFIG_SOC_INTEL_ACE15_MTPM #include @@ -27,10 +28,10 @@ static int pd_intel_adsp_set_power_enable(struct pg_bits *bits, bool power_enabl uint16_t SPA_bit_mask = BIT(bits->SPA_bit); if (power_enable) { - sys_write16(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrctl) | SPA_bit_mask, - (mem_addr_t)&ACE_DfPMCCU.dfpwrctl); + sys_write16(sys_read16((mem_addr_t)ACE_PWRCTL) | SPA_bit_mask, + (mem_addr_t)ACE_PWRCTL); - if (!WAIT_FOR(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrsts) & BIT(bits->CPA_bit), + if (!WAIT_FOR(sys_read16((mem_addr_t)ACE_PWRSTS) & BIT(bits->CPA_bit), 10000, k_busy_wait(1))) { return -EIO; } @@ -46,8 +47,8 @@ static int pd_intel_adsp_set_power_enable(struct pg_bits *bits, bool power_enabl return -EINVAL; } #endif - sys_write16(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrctl) & ~(SPA_bit_mask), - (mem_addr_t)&ACE_DfPMCCU.dfpwrctl); + sys_write16(sys_read16((mem_addr_t)ACE_PWRCTL) & ~(SPA_bit_mask), + (mem_addr_t)ACE_PWRCTL); } return 0; From f1995597f310b60f223e16131fbd394f84c6d406 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1340/1389] intel_adsp/ace: power: Do not re-implement cache func Do not re-implement a function to get a cached pointer. Zephyr cache API already provides it. Signed-off-by: Flavio Ceolin --- soc/intel/intel_adsp/ace/power.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index 08f416e0326a3e..4dadb89378af61 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -22,8 +22,6 @@ #define LPSRAM_MAGIC_VALUE 0x13579BDF #define LPSCTL_BATTR_MASK GENMASK(16, 12) -#define SRAM_ALIAS_BASE 0xA0000000 -#define SRAM_ALIAS_MASK 0xF0000000 #if CONFIG_SOC_INTEL_ACE15_MTPM /* Used to force any pending transaction by HW issuing an upstream read before @@ -53,10 +51,6 @@ __imr void power_init(void) #ifdef CONFIG_PM -#define uncache_to_cache(address) \ - ((__typeof__(address))(((uint32_t)(address) & \ - ~SRAM_ALIAS_MASK) | SRAM_ALIAS_BASE)) - #define L2_INTERRUPT_NUMBER 4 #define L2_INTERRUPT_MASK (1< Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1341/1389] tests/kernel/timer/timer_behavior/pytest: aligh grpcio version Align grpcio version with logic2-automation package fixing its fail on Channel.unary_unary() call with missing _registered_method argument.. Signed-off-by: Dmitrii Golovanov --- tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt b/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt index 1a5dc09125b60c..6d0ef856a66f05 100644 --- a/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt +++ b/tests/kernel/timer/timer_behavior/pytest/requirements-saleae.txt @@ -1,2 +1,3 @@ numpy +grpcio-tools>=1.63.0 logic2-automation From ff8c9f85975c7c5b670632be49783727ed43c9cb Mon Sep 17 00:00:00 2001 From: Babak Arisian Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1342/1389] Bluetooth: Audio: add bt_audio_get_chan_count Implement a function bt_audio_get_chan_count that takes an enum bt_audio_location and returns the number of channels in that value. This PR fixes #69617 (https://github.com/zephyrproject-rtos/zephyr/issues/69617) Signed-off-by: Babak Arisian --- include/zephyr/bluetooth/audio/audio.h | 9 ++++++++ .../bluetooth/broadcast_audio_sink/src/main.c | 22 +++---------------- subsys/bluetooth/audio/audio.c | 20 +++++++++++++++++ subsys/bluetooth/audio/shell/audio.h | 16 -------------- subsys/bluetooth/audio/shell/bap.c | 3 ++- subsys/bluetooth/audio/shell/bap_usb.c | 2 +- .../audio/src/bap_broadcast_sink_test.c | 16 ++------------ 7 files changed, 37 insertions(+), 51 deletions(-) diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 4274279890039e..a7d248026a18f5 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -631,6 +631,15 @@ struct bt_audio_codec_cfg { int bt_audio_data_parse(const uint8_t ltv[], size_t size, bool (*func)(struct bt_data *data, void *user_data), void *user_data); +/** + * @brief Function to get the number of channels from the channel allocation + * + * @param chan_allocation The channel allocation + * + * @return The number of channels + */ +uint8_t bt_audio_get_chan_count(enum bt_audio_location chan_allocation); + /** @brief Audio Capability type */ enum bt_audio_dir { BT_AUDIO_DIR_SINK = 0x01, diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c index 38f9f546078377..b08c4f96c9afb3 100644 --- a/samples/bluetooth/broadcast_audio_sink/src/main.c +++ b/samples/bluetooth/broadcast_audio_sink/src/main.c @@ -151,22 +151,6 @@ static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3); K_THREAD_DEFINE(decoder_tid, LC3_ENCODER_STACK_SIZE, lc3_decoder_thread, NULL, NULL, NULL, LC3_ENCODER_PRIORITY, 0, -1); -static size_t get_chan_cnt(enum bt_audio_location chan_allocation) -{ - size_t cnt = 0U; - - if (chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO) { - return 1; - } - - while (chan_allocation != 0) { - cnt += chan_allocation & 1U; - chan_allocation >>= 1; - } - - return cnt; -} - /* Consumer thread of the decoded stream data */ static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3) { @@ -207,7 +191,7 @@ static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3) stream->in_buf = NULL; k_mutex_unlock(&stream->lc3_decoder_mutex); - frames_per_block = get_chan_cnt(stream->chan_allocation); + frames_per_block = bt_audio_get_chan_count(stream->chan_allocation); if (buf->len != (frames_per_block * octets_per_frame * frames_blocks_per_sdu)) { printk("Expected %u frame blocks with %u frames of size %u, but " @@ -386,7 +370,7 @@ static int lc3_enable(struct broadcast_sink_stream *sink_stream) /* An SDU can consist of X frame blocks, each with Y frames (one per channel) of size Z in * them. The minimum SDU size required for this is X * Y * Z. */ - chan_alloc_bit_cnt = get_chan_cnt(sink_stream->chan_allocation); + chan_alloc_bit_cnt = bt_audio_get_chan_count(sink_stream->chan_allocation); sdu_size_required = chan_alloc_bit_cnt * sink_stream->lc3_octets_per_frame * sink_stream->lc3_frames_blocks_per_sdu; if (sdu_size_required < sink_stream->stream.qos->sdu) { @@ -771,7 +755,7 @@ static bool find_valid_bis_in_subgroup_cb(const struct bt_bap_base_subgroup *sub } else { /* If the subgroup contains a single channel, then we just grab the first BIS index */ - if (get_chan_cnt(chan_allocation) == 1 && + if (bt_audio_get_chan_count(chan_allocation) == 1 && chan_allocation == CONFIG_TARGET_BROADCAST_CHANNEL) { uint32_t subgroup_bis_indexes; diff --git a/subsys/bluetooth/audio/audio.c b/subsys/bluetooth/audio/audio.c index 164a52afa5ee1c..619f52c7abc2e0 100644 --- a/subsys/bluetooth/audio/audio.c +++ b/subsys/bluetooth/audio/audio.c @@ -67,6 +67,26 @@ int bt_audio_data_parse(const uint8_t ltv[], size_t size, return 0; } +uint8_t bt_audio_get_chan_count(enum bt_audio_location chan_allocation) +{ + if (chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO) { + return 1; + } + +#ifdef POPCOUNT + return POPCOUNT(chan_allocation); +#else + uint8_t cnt = 0U; + + while (chan_allocation != 0U) { + cnt += chan_allocation & 1U; + chan_allocation >>= 1U; + } + + return cnt; +#endif +} + #if defined(CONFIG_BT_CONN) static uint8_t bt_audio_security_check(const struct bt_conn *conn) diff --git a/subsys/bluetooth/audio/shell/audio.h b/subsys/bluetooth/audio/shell/audio.h index 8d537557dae96a..1a73258d2e8a31 100644 --- a/subsys/bluetooth/audio/shell/audio.h +++ b/subsys/bluetooth/audio/shell/audio.h @@ -220,22 +220,6 @@ int cap_ac_unicast(const struct shell *sh, const struct bap_unicast_ac_param *pa #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */ #endif /* CONFIG_BT_BAP_UNICAST */ -static inline uint8_t get_chan_cnt(enum bt_audio_location chan_allocation) -{ - uint8_t cnt = 0U; - - if (chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO) { - return 1; - } - - while (chan_allocation != 0) { - cnt += chan_allocation & 1U; - chan_allocation >>= 1; - } - - return cnt; -} - static inline void print_qos(const struct shell *sh, const struct bt_audio_codec_qos *qos) { #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_UNICAST) diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index 4ffa9539940323..b045ecbcda4c67 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -2855,7 +2855,8 @@ static void stream_started_cb(struct bt_bap_stream *bap_stream) ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &sh_stream->lc3_chan_allocation); if (ret == 0) { - sh_stream->lc3_chan_cnt = get_chan_cnt(sh_stream->lc3_chan_allocation); + sh_stream->lc3_chan_cnt = + bt_audio_get_chan_count(sh_stream->lc3_chan_allocation); } else { shell_error(ctx_shell, "Could not get channel allocation: %d", ret); sh_stream->lc3_chan_allocation = BT_AUDIO_LOCATION_MONO_AUDIO; diff --git a/subsys/bluetooth/audio/shell/bap_usb.c b/subsys/bluetooth/audio/shell/bap_usb.c index 30afd5ae093c3a..cd597c65de1620 100644 --- a/subsys/bluetooth/audio/shell/bap_usb.c +++ b/subsys/bluetooth/audio/shell/bap_usb.c @@ -214,7 +214,7 @@ int bap_usb_add_frame_to_usb(enum bt_audio_location chan_allocation, const int16 return -EINVAL; } - if (get_chan_cnt(chan_allocation) != 1) { + if (bt_audio_get_chan_count(chan_allocation) != 1) { LOG_DBG("Invalid channel allocation %d", chan_allocation); return -EINVAL; diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c index cabd365ab5d00b..04fe1ce07a6701 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c @@ -66,18 +66,6 @@ static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams)); static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U); static uint32_t bis_index_bitfield; -static uint8_t count_bits(enum bt_audio_location chan_allocation) -{ - uint8_t cnt = 0U; - - while (chan_allocation != 0) { - cnt += chan_allocation & 1U; - chan_allocation >>= 1; - } - - return cnt; -} - static bool valid_base_subgroup(const struct bt_bap_base_subgroup *subgroup) { struct bt_audio_codec_cfg codec_cfg = {0}; @@ -128,7 +116,7 @@ static bool valid_base_subgroup(const struct bt_bap_base_subgroup *subgroup) ret = bt_audio_codec_cfg_get_chan_allocation(&codec_cfg, &chan_allocation); if (ret == 0) { - chan_cnt = count_bits(chan_allocation); + chan_cnt = bt_audio_get_chan_count(chan_allocation); } else { printk("Could not get subgroup channel allocation: %d\n", ret); /* Channel allocation is an optional field, and omitting it implicitly means mono */ @@ -444,7 +432,7 @@ static void validate_stream_codec_cfg(const struct bt_bap_stream *stream) return; } - chan_cnt = count_bits(chan_allocation); + chan_cnt = bt_audio_get_chan_count(chan_allocation); } else { FAIL("Could not get subgroup channel allocation: %d\n", ret); From 311c6b0f15a7b0176074fc6636dab07ad34b06d1 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1343/1389] tests: drivers: rtc api testing with timeout Add a timeout to the tests/drivers/rtc_api testcase so twister can end properly when running with twister. Signed-off-by: Francois Ramu --- tests/drivers/rtc/rtc_api/testcase.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drivers/rtc/rtc_api/testcase.yaml b/tests/drivers/rtc/rtc_api/testcase.yaml index 7da5c991a49a8b..415818b7db301a 100644 --- a/tests/drivers/rtc/rtc_api/testcase.yaml +++ b/tests/drivers/rtc/rtc_api/testcase.yaml @@ -9,5 +9,6 @@ tests: - api filter: dt_alias_exists("rtc") depends_on: rtc + timeout: 100 platform_exclude: - qemu_x86_64 From eaf1671c677e7c8b1810d3b18154104aa4961f77 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1344/1389] drivers: rtc: stm32 rtc driver configure time and Date Set a Calendar using the LL functions LL_RTC_TIME_Init and LL_RTC_DATE_Init. Add more DBG info On the stm32F2 serie, check RS Flag after setting calendar registers. Signed-off-by: Francois Ramu --- drivers/rtc/rtc_ll_stm32.c | 78 +++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 2cdda0158f3e87..1dd6002c3b2e23 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -392,6 +392,8 @@ static int rtc_stm32_init(const struct device *dev) static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr) { struct rtc_stm32_data *data = dev->data; + LL_RTC_TimeTypeDef rtc_time; + LL_RTC_DateTypeDef rtc_date; uint32_t real_year = timeptr->tm_year + TM_YEAR_REF; int err = 0; @@ -416,42 +418,47 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t LL_PWR_EnableBkUpAccess(); #endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ - LL_RTC_DisableWriteProtection(RTC); - - ErrorStatus status = LL_RTC_EnterInitMode(RTC); - - if (status != SUCCESS) { - err = -EIO; - goto protect_unlock_return; - } - - LL_RTC_DATE_SetYear(RTC, bin2bcd(real_year - RTC_YEAR_REF)); - LL_RTC_DATE_SetMonth(RTC, bin2bcd(timeptr->tm_mon + 1)); - LL_RTC_DATE_SetDay(RTC, bin2bcd(timeptr->tm_mday)); - - if (timeptr->tm_wday == 0) { - /* sunday (tm_wday = 0) is not represented by the same value in hardware */ - LL_RTC_DATE_SetWeekDay(RTC, LL_RTC_WEEKDAY_SUNDAY); - } else { - /* all the other values are consistent with what is expected by hardware */ - LL_RTC_DATE_SetWeekDay(RTC, timeptr->tm_wday); - } - - LL_RTC_TIME_SetHour(RTC, bin2bcd(timeptr->tm_hour)); - LL_RTC_TIME_SetMinute(RTC, bin2bcd(timeptr->tm_min)); - LL_RTC_TIME_SetSecond(RTC, bin2bcd(timeptr->tm_sec)); - - LL_RTC_DisableInitMode(RTC); - -protect_unlock_return: - LL_RTC_EnableWriteProtection(RTC); + /* Enter Init mode inside the LL_RTC_Time and Date Init functions */ + rtc_time.Hours = bin2bcd(timeptr->tm_hour); + rtc_time.Minutes = bin2bcd(timeptr->tm_min); + rtc_time.Seconds = bin2bcd(timeptr->tm_sec); + LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BCD, &rtc_time); + + /* Set Date after Time to be sure the DR is correctly updated on stm32F2 serie. */ + rtc_date.Year = bin2bcd((real_year - RTC_YEAR_REF)); + rtc_date.Month = bin2bcd((timeptr->tm_mon + 1)); + rtc_date.Day = bin2bcd(timeptr->tm_mday); + rtc_date.WeekDay = ((timeptr->tm_wday == 0) ? (LL_RTC_WEEKDAY_SUNDAY) : (timeptr->tm_wday)); + /* WeekDay sunday (tm_wday = 0) is not represented by the same value in hardware, + * all the other values are consistent with what is expected by hardware. + */ + LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BCD, &rtc_date); #if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); #endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ +#ifdef CONFIG_SOC_SERIES_STM32F2X + /* + * Because stm32F2 serie has no shadow registers, + * wait until TR and DR registers are synchronised : flag RS + */ + while (LL_RTC_IsActiveFlag_RS(RTC) != 1) { + ; + } +#endif /* CONFIG_SOC_SERIES_STM32F2X */ + k_mutex_unlock(&data->lock); + LOG_DBG("Calendar set : %d/%d/%d - %dh%dm%ds", + LL_RTC_DATE_GetDay(RTC), + LL_RTC_DATE_GetMonth(RTC), + LL_RTC_DATE_GetYear(RTC), + LL_RTC_TIME_GetHour(RTC), + LL_RTC_TIME_GetMinute(RTC), + LL_RTC_TIME_GetSecond(RTC) + ); + return err; } @@ -504,7 +511,8 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr k_mutex_unlock(&data->lock); - timeptr->tm_year = bcd2bin(__LL_RTC_GET_YEAR(rtc_date)) + RTC_YEAR_REF - TM_YEAR_REF; + /* tm_year is the value since 1900 and Rtc year is from 2000 */ + timeptr->tm_year = bcd2bin(__LL_RTC_GET_YEAR(rtc_date)) + (RTC_YEAR_REF - TM_YEAR_REF); /* tm_mon allowed values are 0-11 */ timeptr->tm_mon = bcd2bin(__LL_RTC_GET_MONTH(rtc_date)) - 1; timeptr->tm_mday = bcd2bin(__LL_RTC_GET_DAY(rtc_date)); @@ -530,11 +538,19 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr #else timeptr->tm_nsec = 0; #endif - /* unknown values */ timeptr->tm_yday = -1; timeptr->tm_isdst = -1; + /* __LL_RTC_GET_YEAR(rtc_date)is the real year (from 2000) */ + LOG_DBG("Calendar get : %d/%d/%d - %dh%dm%ds", + timeptr->tm_mday, + timeptr->tm_mon, + __LL_RTC_GET_YEAR(rtc_date), + timeptr->tm_hour, + timeptr->tm_min, + timeptr->tm_sec); + return 0; } From 0d67ea5da50fa2e3c361d2e256ae62dde46c4434 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1345/1389] drivers: rtc: stm32 rtc driver disable alarm interrupt if not used Note that the Init of the alarm has no need for BCD2BIN conversion, the LL_RTC_ALMx_Init will do. Add more log debug The driver must clear the ALARM enable bit before wrting the alarm registers. Signed-off-by: Francois Ramu --- drivers/rtc/rtc_ll_stm32.c | 39 ++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 1dd6002c3b2e23..024669a1a94989 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -187,7 +187,10 @@ static inline ErrorStatus rtc_stm32_init_alarm(RTC_TypeDef *rtc, uint32_t format LL_RTC_AlarmTypeDef *ll_alarm_struct, uint16_t id) { ll_alarm_struct->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE; - /* RTC write protection is disabled & enabled again inside LL_RTC_ALMx_Init functions */ + /* + * RTC write protection is disabled & enabled again inside LL_RTC_ALMx_Init functions + * The LL_RTC_ALMx_Init does convert bin2bcd by itself + */ if (id == RTC_STM32_ALRM_A) { return LL_RTC_ALMA_Init(rtc, format, ll_alarm_struct); } @@ -776,6 +779,7 @@ static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint1 if (rtc_stm32_is_active_alarm(RTC, id)) { LL_RTC_DisableWriteProtection(RTC); rtc_stm32_disable_alarm(RTC, id); + rtc_stm32_disable_interrupt_alarm(RTC, id); LL_RTC_EnableWriteProtection(RTC); } LOG_DBG("Alarm %d has been disabled", id); @@ -808,9 +812,9 @@ static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint1 p_rtc_alrm->user_mask = mask; - LOG_DBG("set alarm: second = %d, min = %d, hour = %d," - "wday = %d, mday = %d, mask = 0x%04x", - timeptr->tm_sec, timeptr->tm_min, timeptr->tm_hour, + LOG_DBG("set alarm %d : second = %d, min = %d, hour = %d," + " wday = %d, mday = %d, mask = 0x%04x", + id, timeptr->tm_sec, timeptr->tm_min, timeptr->tm_hour, timeptr->tm_wday, timeptr->tm_mday, mask); #if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION @@ -820,15 +824,14 @@ static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint1 /* Disable the write protection for RTC registers */ LL_RTC_DisableWriteProtection(RTC); - if (rtc_stm32_is_active_alarm(RTC, id)) { - /* Disable Alarm if already active */ - rtc_stm32_disable_alarm(RTC, id); - } + /* Disable ALARM so that the RTC_ISR_ALRAWF/RTC_ISR_ALRBWF is 0 */ + rtc_stm32_disable_alarm(RTC, id); + rtc_stm32_disable_interrupt_alarm(RTC, id); #ifdef RTC_ISR_ALRAWF if (id == RTC_STM32_ALRM_A) { /* Wait till RTC ALRAWF flag is set before writing to RTC registers */ - while ((LL_RTC_ReadReg(RTC, ISR) & RTC_ISR_ALRAWF) == 0U) { + while (!LL_RTC_IsActiveFlag_ALRAW(RTC)) { ; } } @@ -837,7 +840,7 @@ static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint1 #ifdef RTC_ISR_ALRBWF if (id == RTC_STM32_ALRM_B) { /* Wait till RTC ALRBWF flag is set before writing to RTC registers */ - while ((LL_RTC_ReadReg(RTC, ISR) & RTC_ISR_ALRBWF) == 0U) { + while (!LL_RTC_IsActiveFlag_ALRBW(RTC)) { ; } } @@ -874,6 +877,22 @@ static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint1 unlock: k_mutex_unlock(&data->lock); + if (id == RTC_STM32_ALRM_A) { + LOG_DBG("Alarm A : %dh%dm%ds mask = 0x%x", + LL_RTC_ALMA_GetHour(RTC), + LL_RTC_ALMA_GetMinute(RTC), + LL_RTC_ALMA_GetSecond(RTC), + LL_RTC_ALMA_GetMask(RTC)); + } +#ifdef RTC_ALARM_B + if (id == RTC_STM32_ALRM_B) { + LOG_DBG("Alarm B : %dh%dm%ds mask = 0x%x", + LL_RTC_ALMB_GetHour(RTC), + LL_RTC_ALMB_GetMinute(RTC), + LL_RTC_ALMB_GetSecond(RTC), + LL_RTC_ALMB_GetMask(RTC)); + } +#endif /* #ifdef RTC_ALARM_B */ return err; } From 54495a78f9f022e74dbaa294b3793078019ff194 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Sun, 26 May 2024 22:39:39 +0200 Subject: [PATCH 1346/1389] tests/posix/env: set CONFIG_PICOLIBC=y Chosing by default in the prj.conf PICOLIBC ensures we also use an embedded libC even when built for a native target and even if we dont set POSIX_API. This ensures the test will build and pass properly when built with default configuration from command line without using the test yaml. This change does not affect the build result for other targets as those defaulted already to PICOLIBC. Signed-off-by: Alberto Escolar Piedras --- tests/posix/env/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/posix/env/prj.conf b/tests/posix/env/prj.conf index 7389f7de33e708..7529d301e2ed18 100644 --- a/tests/posix/env/prj.conf +++ b/tests/posix/env/prj.conf @@ -1,3 +1,6 @@ CONFIG_ZTEST=y CONFIG_POSIX_ENV=y +# Let's explicitly choose PICOLIBC, so it is used if supported even if it would not have been the +# default (otherwise native targets default to the host C library) +CONFIG_PICOLIBC=y CONFIG_COMMON_LIBC_MALLOC=y From d552154e313e1ce0e61d3f9faff37d67dac361c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1347/1389] samples: nrfx_prs: Fix pin assignment on nRF5340 DK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pins P0.06 and P0.07 are shorted on nRF5340 DKs prepared for on-target tests because that is required for UART tests. That causes background SPIM transfers in this sample to fail because SPIM is not able to drive its SCK line configured as P0.06. Rearrange then the pins used in this sample, so that SCK is not on a pin involved in a GPIO loopback. Signed-off-by: Andrzej Głąbek --- .../nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay index d187d4a5f99d20..4bbf47524a8043 100644 --- a/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -1,20 +1,20 @@ &pinctrl { spi1_default_alt: spi1_default_alt { group1 { - psels = , - ; + psels = , + ; }; group2 { - psels = ; + psels = ; bias-pull-down; }; }; spi1_sleep_alt: spi1_sleep_alt { group1 { - psels = , - , - ; + psels = , + , + ; low-power-enable; }; }; From e2d6a9dbe88a9036971b243b4223c5261cc81826 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1348/1389] maintainers: crypto: Add crypto documentation in its section Add crypto related docs in the crypto section. Signed-off-by: Flavio Ceolin --- MAINTAINERS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index a980ed92529dc0..ad197d1cf376dc 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1091,6 +1091,7 @@ Release Notes: - include/zephyr/crypto/ - samples/drivers/crypto/ - tests/crypto/ + - doc/services/crypto/ labels: - "area: Crypto / RNG" tests: @@ -2413,7 +2414,6 @@ Mbed TLS: - ithinuel files: - tests/crypto/mbedtls/ - - doc/services/crypto/ - tests/benchmarks/mbedtls/ labels: - "area: Crypto / RNG" From fa5f2a045e223b605ab2d12951553b27a6990184 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1349/1389] doc/services/llext: Mention the LLEXT EDK Mention the EDK existence, the build target and discuss some features. Signed-off-by: Ederson de Souza --- doc/services/llext/index.rst | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/doc/services/llext/index.rst b/doc/services/llext/index.rst index d742f198530d30..899936cda61ab2 100644 --- a/doc/services/llext/index.rst +++ b/doc/services/llext/index.rst @@ -18,6 +18,66 @@ needed by the :c:func:`llext_load` function. An implementation over a buffer containing an ELF in addressable memory in memory is available as :c:struct:`llext_buf_loader`. +LLEXT Extension Development Kit +******************************* + +To build the extensions to be loaded by the llext subsystem, it's necessary to +have access to the headers and compiler flags used by the main Zephyr +application. While building an extension as part of the Zephyr application +is straightforward, it can be more complex as a standalone project. + +The LLEXT Extension Development Kit (EDK) provides a set of headers and compile +flags that can be used to build extensions as standalone projects. The EDK +can be generated by the Zephyr build system by running the following command +which uses the ``llext-edk`` target to generate the EDK: + +.. code-block:: shell + + west build -t llext-edk + +The generated EDK can be found in the build directory under the ``zephyr`` +directory. It's a tarball that contains the headers and compile flags needed +to build extensions. The extension developer can then include the headers +and use the compile flags in their build system to build the extension. + +Compile flags +------------- + +Convenience files ``cmake.cflags`` (for CMake based projects) and +``Makefile.cflags`` are provided by the EDK containing the needed compile flags. +The main flag is ``LLEXT_CFLAGS`` which contains the flags needed to build an +extension. Also provided is a granular set of flags that can be used in support +of different use cases, such as when building mocks for unit tests. The provided +flags are: + +- ``LLEXT_CFLAGS``: Flags needed to build an extension. +- ``LLEXT_ALL_INCLUDE_CFLAGS``: Include flags needed to include all headers. +- ``LLEXT_INCLUDE_CFLAGS``: Include flags for non build generated headers. +- ``LLEXT_GENERATED_INCLUDE_CFLAGS``: Include flags for build generated headers. +- ``LLEXT_BASE_CFLAGS``: All other flags needed to build an extension, + excluding the include flags. +- ``LLEXT_GENERATED_IMACROS_CFLAGS``: Include only ``-imacros`` flags for build + generated headers. + +LLEXT EDK Kconfig options +------------------------- + +The LLEXT EDK can be configured using the following Kconfig options: + +:kconfig:option:`CONFIG_LLEXT_EDK_NAME` + The name of the generated EDK tarball. + +:kconfig:option:`CONFIG_LLEXT_EDK_USERSPACE_ONLY` + If set, the EDK will include headers that do not contain code to route + syscalls to the kernel. This is useful when building extensions that will + run exclusively in user mode. + +EDK Sample +---------- + +Refer to :zephyr:code-sample:`llext-edk` for an example of how to use the +LLEXT EDK. + API Reference ************* From fa505acd41600d02cd37494a53367a19e06d79d9 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1350/1389] soc: renesas: smartbond: Fix exiting from suspend state We need to enable irqs that were disabled when entering suspend state. Signed-off-by: Andrzej Kaczmarek --- soc/renesas/smartbond/da1469x/power.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soc/renesas/smartbond/da1469x/power.c b/soc/renesas/smartbond/da1469x/power.c index 1b325c47eb8092..80a497acff5423 100644 --- a/soc/renesas/smartbond/da1469x/power.c +++ b/soc/renesas/smartbond/da1469x/power.c @@ -39,6 +39,10 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) { ARG_UNUSED(state); ARG_UNUSED(substate_id); + + if (state == PM_STATE_STANDBY) { + __enable_irq(); + } } static int renesas_da1469x_pm_init(void) From 41680aa037821ca36e14944e1fa12a68e487fbe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1351/1389] boards: nordic: 54l: use wdt31 instead of wdt30 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use wdt31 instead of wdt30 as wdt30 is hardware fixed to secure. Signed-off-by: Sebastian Bøe --- boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi | 2 +- .../drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay | 2 +- .../watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay | 2 +- .../watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay | 2 +- .../wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi index 028bcfccd54b14..75dbe784097931 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi @@ -60,7 +60,7 @@ sw1 = &button1; sw2 = &button2; sw3 = &button3; - watchdog0 = &wdt30; + watchdog0 = &wdt31; }; }; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay index 66157d79fb36ff..5c765a8a896331 100644 --- a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -3,6 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&wdt30 { +&wdt31 { status = "okay"; }; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay index 66157d79fb36ff..5c765a8a896331 100644 --- a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -3,6 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&wdt30 { +&wdt31 { status = "okay"; }; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay index 66157d79fb36ff..5c765a8a896331 100644 --- a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay @@ -3,6 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&wdt30 { +&wdt31 { status = "okay"; }; diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay index aa2789dd45e879..8d3dce3b380057 100644 --- a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -4,6 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&wdt30 { +&wdt31 { status = "okay"; }; From 0d6c97326655d17eacde3ca1a4526624e80fff21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1352/1389] samples: wdt_basic_api: nrf: Add missing nrf overlays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing nrf overlays to fix the sample at build time. Copied from samples/drivers/watchdog/boards. It is not clear why the build failure was not detected earlier. Signed-off-by: Sebastian Bøe --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 8 ++++++++ .../boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay | 8 ++++++++ .../boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay create mode 100644 tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..94e0d719af4ef5 --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt010 { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay new file mode 100644 index 00000000000000..5c765a8a896331 --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt31 { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay new file mode 100644 index 00000000000000..5c765a8a896331 --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt31 { + status = "okay"; +}; From c4dc9ca468b7271ce1c135169dd7246c6cb466e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1353/1389] dts: nordic: 54l: Don't define wdt30 for the non-secure domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't define wdt30 for the non-secure domain as it is hardware fixed to secure. Signed-off-by: Sebastian Bøe --- dts/common/nordic/nrf54l15.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index a15ead439534bd..b3c44f4c6b732b 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -567,12 +567,16 @@ status = "disabled"; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + /* intentionally empty because WDT30 is hardware fixed to Secure */ +#else wdt30: watchdog@108000 { compatible = "nordic,nrf-wdt"; reg = <0x108000 0x620>; interrupts = <264 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; }; +#endif wdt31: watchdog@109000 { compatible = "nordic,nrf-wdt"; From 2f2e8b3637fa76dbb4c3862c09527c6c74cee15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1354/1389] dts: nordic: 54l: Don't define UICR for the non-secure domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't define UICR for the non-secure domain as it is hardware fixed to secure. Signed-off-by: Sebastian Bøe --- dts/common/nordic/nrf54l15.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index b3c44f4c6b732b..93bfaa5db53d78 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -104,11 +104,14 @@ #address-cells = <1>; #size-cells = <1>; +#ifdef USE_NON_SECURE_ADDRESS_MAP + /* intentionally empty because UICR is hardware fixed to Secure */ +#else uicr: uicr@ffd000 { compatible = "nordic,nrf-uicr"; reg = <0xffd000 0x1000>; }; - +#endif ficr: ficr@ffc000 { compatible = "nordic,nrf-ficr"; reg = <0xffc000 0x1000>; From e92923104785aaf31d668a2f1fe118427e290316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1355/1389] dts: nordic: 54l: Change the peripheral address map for ns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define peripherals with the 0x4000_0000 address range when building for non-secure. Signed-off-by: Sebastian Bøe --- dts/common/nordic/nrf54l15.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index 93bfaa5db53d78..0b8eb1c549a879 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -134,10 +134,17 @@ ranges = <0x0 0x2002f000 0x11000>; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + global_peripherals: peripheral@40000000 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000000 0x10000000>; +#else global_peripherals: peripheral@50000000 { #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x50000000 0x10000000>; +#endif dppic00: dppic@42000 { compatible = "nordic,nrf-dppic"; From 4e22fe527cb43ad6a0fe765626158ce84cd0045a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1356/1389] boards: nordic: 54L: Refactor the board DT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the 54L board file to be able to better support out-of-tree non-secure boards. This aligns better with nrf53's DT. Signed-off-by: Sebastian Bøe --- .../nrf54l15pdk/nrf54l15_cpuapp_common.dtsi | 150 ++++++++++++++++++ .../nrf54l15pdk_nrf54l15_cpuapp.dts | 139 +--------------- 2 files changed, 152 insertions(+), 137 deletions(-) create mode 100644 boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi diff --git a/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi new file mode 100644 index 00000000000000..2fa2ec36428dab --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is common to the secure and non-secure domain */ + +#include +#include "nrf54l15pdk_nrf54l15-common.dtsi" + +/ { + chosen { + zephyr,console = &uart20; + zephyr,shell-uart = &uart20; + zephyr,uart-mcumgr = &uart20; + zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; + zephyr,ieee802154 = &ieee802154; + }; + + aliases { + spi-flash0 = &mx25r64; + }; +}; + +&cpuapp_sram { + status = "okay"; +}; + +&lfxo { + load-capacitors = "internal"; + load-capacitance-femtofarad = <15500>; +}; + +&hfxo { + load-capacitors = "internal"; + load-capacitance-femtofarad = <15000>; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(324)>; + }; + slot0_ns_partition: partition@61000 { + label = "image-0-nonsecure"; + reg = <0x61000 DT_SIZE_K(324)>; + }; + slot1_partition: partition@b2000 { + label = "image-1"; + reg = <0xb2000 DT_SIZE_K(324)>; + }; + slot1_ns_partition: partition@103000 { + label = "image-1-nonsecure"; + reg = <0x103000 DT_SIZE_K(324)>; + }; + /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ + storage_partition: partition@15c000 { + label = "storage"; + reg = <0x15c000 DT_SIZE_K(36)>; + }; + }; +}; + +&uart20 { + status = "okay"; + hw-flow-control; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +&gpiote30 { + status = "okay"; +}; + +&radio { + status = "okay"; +}; + +&ieee802154 { + status = "okay"; +}; + +&temp { + status = "okay"; +}; + +&clock { + status = "okay"; +}; + +&spi00 { + status = "okay"; + cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi00_default>; + pinctrl-1 = <&spi00_sleep>; + pinctrl-names = "default", "sleep"; + + mx25r64: mx25r6435f@0 { + compatible = "jedec,spi-nor"; + status = "disabled"; + reg = <0>; + spi-max-frequency = <8000000>; + jedec-id = [c2 28 17]; + sfdp-bfp = [ + e5 20 f1 ff ff ff ff 03 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f5 00 82 ed 04 cc 44 83 48 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + size = <67108864>; + has-dpd; + t-enter-dpd = <10000>; + t-exit-dpd = <35000>; + }; +}; + +&adc { + status = "okay"; +}; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts index 24b15763bdc8f6..831479ea950377 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts @@ -5,150 +5,15 @@ */ /dts-v1/; -#include -#include "nrf54l15pdk_nrf54l15-common.dtsi" + +#include "nrf54l15_cpuapp_common.dtsi" / { compatible = "nordic,nrf54l15pdk_nrf54l15-cpuapp"; model = "Nordic nRF54L15 PDK nRF54L15 Application MCU"; chosen { - zephyr,console = &uart20; - zephyr,shell-uart = &uart20; - zephyr,uart-mcumgr = &uart20; - zephyr,flash-controller = &rram_controller; - zephyr,flash = &cpuapp_rram; zephyr,code-partition = &slot0_partition; zephyr,sram = &cpuapp_sram; - zephyr,ieee802154 = &ieee802154; - }; - - aliases { - spi-flash0 = &mx25r64; - }; -}; - -&cpuapp_sram { - status = "okay"; -}; - -&lfxo { - load-capacitors = "internal"; - load-capacitance-femtofarad = <15500>; -}; - -&hfxo { - load-capacitors = "internal"; - load-capacitance-femtofarad = <15000>; -}; - -&grtc { - owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; - /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ - child-owned-channels = <3 4 7 8 9 10 11>; - status = "okay"; -}; - -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; - -&uart20 { - status = "okay"; - hw-flow-control; -}; - -&gpio0 { - status = "okay"; -}; - -&gpio1 { - status = "okay"; -}; - -&gpio2 { - status = "okay"; -}; - -&gpiote20 { - status = "okay"; -}; - -&gpiote30 { - status = "okay"; -}; - -&radio { - status = "okay"; -}; - -&ieee802154 { - status = "okay"; -}; - -&temp { - status = "okay"; -}; - -&clock { - status = "okay"; -}; - -&spi00 { - status = "okay"; - cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&spi00_default>; - pinctrl-1 = <&spi00_sleep>; - pinctrl-names = "default", "sleep"; - - mx25r64: mx25r6435f@0 { - compatible = "jedec,spi-nor"; - status = "disabled"; - reg = <0>; - spi-max-frequency = <8000000>; - jedec-id = [c2 28 17]; - sfdp-bfp = [ - e5 20 f1 ff ff ff ff 03 44 eb 08 6b 08 3b 04 bb - ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 - 10 d8 00 ff 23 72 f5 00 82 ed 04 cc 44 83 48 44 - 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff - ]; - size = <67108864>; - has-dpd; - t-enter-dpd = <10000>; - t-exit-dpd = <35000>; }; }; - -&adc { - status = "okay"; -}; From 4b4a289d20fd476e2b4c4c6121a8623a81091124 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1357/1389] drivers: clock_control: smartbond: Update CMAC sleep clock The CMAC uses lp_clk as a sleep clock so it has to be updated if frequency of lp_clk has changed. This happens either after XTAL32K settling or RCX calibration. Signed-off-by: Andrzej Kaczmarek --- .../clock_control/clock_control_smartbond.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index 6da9c88b9a5a93..30f9820f2b0043 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -13,6 +13,9 @@ #include #include #include +#if defined(CONFIG_BT_DA1469X) +#include +#endif LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -53,6 +56,14 @@ static void calibration_work_cb(struct k_work *work) lpc_clock_state.rcx_freq = da1469x_clock_lp_rcx_freq_get(); LOG_DBG("RCX calibration done, RCX freq: %d", (int)lpc_clock_state.rcx_freq); + +#if defined(CONFIG_BT_DA1469X) + /* Update CMAC sleep clock with calculated frequency if RCX is set as lp_clk */ + if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) == + (1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos)) { + cmac_request_lp_clock_freq_set(lpc_clock_state.rcx_freq); + } +#endif } if (lpc_clock_state.rc32k_started) { da1469x_clock_lp_rc32k_calibrate(); @@ -82,6 +93,14 @@ static void xtal32k_settle_work_cb(struct k_work *work) if (lpc_clock_state.xtal32k_started && !lpc_clock_state.xtal32k_ready) { LOG_DBG("XTAL32K settled."); lpc_clock_state.xtal32k_ready = true; + +#if defined(CONFIG_BT_DA1469X) + /* Update CMAC sleep clock if XTAL32K is set as lp_clk */ + if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) == + (2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos)) { + cmac_request_lp_clock_freq_set(32768); + } +#endif } } From d129815c6ec0f9ecef5b6837cf762048c4b790fc Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1358/1389] boards: native: fixed i2c dependency loop This was discovered when trying to add select GPIO to emulator Kconfig. Signed-off-by: Swift Tian --- boards/native/native_posix/Kconfig.defconfig | 7 ------- boards/native/native_sim/Kconfig.defconfig | 6 ------ 2 files changed, 13 deletions(-) diff --git a/boards/native/native_posix/Kconfig.defconfig b/boards/native/native_posix/Kconfig.defconfig index 9132dd9c14d482..6db6f0aee1b5a9 100644 --- a/boards/native/native_posix/Kconfig.defconfig +++ b/boards/native/native_posix/Kconfig.defconfig @@ -37,11 +37,4 @@ config UART_CONSOLE endif # CONSOLE -if I2C - -config EMUL - default y - -endif # I2C - endif # BOARD_NATIVE_POSIX diff --git a/boards/native/native_sim/Kconfig.defconfig b/boards/native/native_sim/Kconfig.defconfig index e154d43a525316..02d6b1d6465998 100644 --- a/boards/native/native_sim/Kconfig.defconfig +++ b/boards/native/native_sim/Kconfig.defconfig @@ -37,11 +37,5 @@ config UART_CONSOLE endif # CONSOLE -if I2C - -config EMUL - default y - -endif # I2C endif # BOARD_NATIVE_SIM From b9648432c6df7f8580978adc3ca8a0d984b49f37 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1359/1389] tests: subsys: fix emul test compile Add CONFIG_EMUL=y to the test .conf Signed-off-by: Swift Tian --- tests/subsys/emul/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/subsys/emul/prj.conf b/tests/subsys/emul/prj.conf index 81a9aca7dbd98b..66ef801fe376ca 100644 --- a/tests/subsys/emul/prj.conf +++ b/tests/subsys/emul/prj.conf @@ -5,3 +5,4 @@ CONFIG_ZTEST=y CONFIG_SENSOR=y CONFIG_BMI160_TRIGGER_NONE=y +CONFIG_EMUL=y From 83230ff52d08c22b21e938d48e38d15c97a772f0 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1360/1389] tests: sensor: fix compile Add CONFIG_EMUL=y to prj.conf Signed-off-by: Swift Tian --- tests/drivers/build_all/sensor/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drivers/build_all/sensor/prj.conf b/tests/drivers/build_all/sensor/prj.conf index 2fb7bedcac8d6d..156aa046560ecc 100644 --- a/tests/drivers/build_all/sensor/prj.conf +++ b/tests/drivers/build_all/sensor/prj.conf @@ -15,3 +15,4 @@ CONFIG_MFD=y CONFIG_W1=y CONFIG_SENSOR=y CONFIG_ICM42605_TRIGGER_NONE=y +CONFIG_EMUL=y From a770294184e6db8fa3852fec4c3c5a2e24ad1111 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1361/1389] samples: subsys: fix sensing/simple compile Add CONFIG_EMUL=y to native_sim.conf Signed-off-by: Swift Tian --- samples/subsys/sensing/simple/boards/native_sim.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/sensing/simple/boards/native_sim.conf b/samples/subsys/sensing/simple/boards/native_sim.conf index b5a8eb94dc8e3c..a8d13b8a035809 100644 --- a/samples/subsys/sensing/simple/boards/native_sim.conf +++ b/samples/subsys/sensing/simple/boards/native_sim.conf @@ -3,3 +3,4 @@ CONFIG_BMI160_TRIGGER_NONE=y CONFIG_EMUL_BMI160=y CONFIG_SENSOR=y CONFIG_SENSOR_INFO=y +CONFIG_EMUL=y From 7f5a41ad260a5c4efd6788d31415a673bc0a3002 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1362/1389] samples: lvgl: fix accelerometer_chart compile Add CONFIG_EMUL=y to prj.conf. Signed-off-by: Swift Tian --- samples/modules/lvgl/accelerometer_chart/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/modules/lvgl/accelerometer_chart/prj.conf b/samples/modules/lvgl/accelerometer_chart/prj.conf index a5d6e2e831e7fb..4930ab3bc2f6fb 100644 --- a/samples/modules/lvgl/accelerometer_chart/prj.conf +++ b/samples/modules/lvgl/accelerometer_chart/prj.conf @@ -7,3 +7,4 @@ CONFIG_LV_Z_MEM_POOL_SIZE=16384 CONFIG_DISPLAY=y CONFIG_INPUT=y CONFIG_SENSOR=y +CONFIG_EMUL=y From 5e1801da418260d0bd2458103897b4cb86552a35 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1363/1389] doc: add a note in 3.7 migration guide CONFIG_EMUL is no longer default with CONFIG_I2C as it causes I2C dependency loop. Signed-off-by: Swift Tian --- doc/releases/migration-guide-3.7.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index cc9a8b1bce7a56..5dc2312a57d9ad 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -35,6 +35,9 @@ Boards All symbols are renamed as follows: ``SOC_IT81202BX``, ``SOC_IT81202CX``, ``SOC_IT81302BX``, ``SOC_IT81302CX``, ``SOC_IT82002AW``, ``SOC_IT82202AX``, ``SOC_IT82302AX``. And, rename the ``SOC_SERIES_ITE_IT8XXX2`` to ``SOC_SERIES_IT8XXX2``. (:github:`71680`) +* For native_sim/posix: :kconfig:option:`CONFIG_EMUL` is no longer enabled by default when + :kconfig:option:`CONFIG_I2C` is set. Users who need this setting enabled should set it in + their project config file. (:github:`73067`) Modules ******* From dd070b14b3da9007fd1519c381190fd0859b84b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1364/1389] mgmt: hawkbit: option for cold reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add option for cold reboot. Signed-off-by: Fin Maaß --- subsys/mgmt/hawkbit/Kconfig | 16 ++++++++++++++++ subsys/mgmt/hawkbit/hawkbit.c | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/subsys/mgmt/hawkbit/Kconfig b/subsys/mgmt/hawkbit/Kconfig index e2011fd4cadd1a..6b806f28a8091d 100644 --- a/subsys/mgmt/hawkbit/Kconfig +++ b/subsys/mgmt/hawkbit/Kconfig @@ -145,6 +145,22 @@ config HAWKBIT_STATIC_CERT_TAG endif +choice HAWKBIT_REBOOT_MODE + prompt "Reboot mode after update" + default HAWKBIT_REBOOT_WARM + +config HAWKBIT_REBOOT_WARM + bool "Warm reboot after update" + help + Do a warm reboot after the update. + +config HAWKBIT_REBOOT_COLD + bool "Cold reboot after update" + help + Do a cold reboot after the update. + +endchoice + module = HAWKBIT module-str = Log Level for hawkbit module-help = Enables logging for hawkBit code. diff --git a/subsys/mgmt/hawkbit/hawkbit.c b/subsys/mgmt/hawkbit/hawkbit.c index 854500850b6e20..6b42cbf78fedae 100644 --- a/subsys/mgmt/hawkbit/hawkbit.c +++ b/subsys/mgmt/hawkbit/hawkbit.c @@ -1190,7 +1190,7 @@ static bool send_request(enum http_method method, enum hawkbit_http_request type void hawkbit_reboot(void) { LOG_PANIC(); - sys_reboot(SYS_REBOOT_WARM); + sys_reboot(IS_ENABLED(CONFIG_HAWKBIT_REBOOT_COLD) ? SYS_REBOOT_COLD : SYS_REBOOT_WARM); } static bool check_hawkbit_server(void) From 2f574b5ed9204b5082c642d99c3fed2dae1adddf Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Sun, 26 May 2024 22:39:40 +0200 Subject: [PATCH 1365/1389] cmake: find python path adjustment Fixes: #70258 Specify NO_CMAKE_PATH to prevent CMake find_program from having a preference for searching CMAKE_PREFIX_PATH. Some tool like NixOS / Nix package manager sets this variable to point inside the nix store, like this: CMAKE_PREFIX_PATH=/nix/store/gpvnsgf8zhqjjgk63dd...-python3-3.11.6-env thus causing `find_program()` to prefer this over the tool in the default path. Support Nix environments by specifying NO_CMAKE_PATH and in addition support `VIRTUAL_ENV` environment setting for search path when set by the virtual environment. Signed-off-by: Torsten Rasmussen --- cmake/modules/python.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/python.cmake b/cmake/modules/python.cmake index 6fc765f8f58f8d..2464bb1517cb38 100644 --- a/cmake/modules/python.cmake +++ b/cmake/modules/python.cmake @@ -25,7 +25,7 @@ if(NOT Python3_EXECUTABLE) # cause just using find_program directly could result in a python2.7 as python, # and not finding a valid python3. foreach(candidate "python" "python3") - find_program(Python3_EXECUTABLE ${candidate}) + find_program(Python3_EXECUTABLE ${candidate} PATHS ENV VIRTUAL_ENV NO_CMAKE_PATH) if(Python3_EXECUTABLE) execute_process (COMMAND "${Python3_EXECUTABLE}" -c "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))" From f6d3776fde881c0a985fd692c5591146344ed0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1366/1389] tests: drivers: uart: async_api: Add nrf54h20 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlays for nrf54h20dk. Signed-off-by: Krzysztof Chruściński --- .../boards/nrf54h20dk_nrf54h20_common.dtsi | 26 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 7 +++++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 7 +++++ 3 files changed, 40 insertions(+) create mode 100644 tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi create mode 100644 tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 00000000000000..9aa338deaad71a --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&pinctrl { + uart137_default_alt: uart137_default_alt { + group1 { + psels = , + ; + }; + }; + + uart137_sleep_alt: uart137_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut: &uart137 { + status = "okay"; + pinctrl-0 = <&uart137_default_alt>; + pinctrl-1 = <&uart137_sleep_alt>; + pinctrl-names = "default", "sleep"; + current-speed = <115200>; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000000..be5897fd0516fb --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&dut { + memory-regions = <&cpuapp_dma_region>; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000000..beca628a2f0805 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&dut { + memory-regions = <&cpurad_dma_region>; +}; From c3c4483a540574d05e32fcbf3178178dabde5425 Mon Sep 17 00:00:00 2001 From: Sreeram Tatapudi Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1367/1389] boards: arm: Introduce Infineon CYW920829M2EVK-02 board - Add initial version of CYW920829M2EVK-02 board - [drivers: clock_control] Make it possible to set up both iho and imo clocks instead of just one or the other Signed-off-by: Sreeram Tatapudi --- .../Kconfig.cyw920829m2evk_02 | 7 + boards/infineon/cyw920829m2evk_02/board.cmake | 4 + boards/infineon/cyw920829m2evk_02/board.yml | 5 + .../cyw920829m2evk_02-common.dtsi | 60 +++ .../cyw920829m2evk_02-pinctrl.dtsi | 13 + .../cyw920829m2evk_02/cyw920829m2evk_02.dts | 107 ++++ .../cyw920829m2evk_02/cyw920829m2evk_02.yaml | 21 + .../cyw920829m2evk_02_defconfig | 31 ++ .../doc/img/cyw920829m2evk_02.webp | Bin 0 -> 52226 bytes .../infineon/cyw920829m2evk_02/doc/index.rst | 125 +++++ .../cyw920829m2evk_02/support/openocd.cfg | 10 + .../cyw920829m2evk_02/support/qspi_config.cfg | 29 ++ .../clock_control/clock_control_ifx_cat1.c | 268 +++++++++- drivers/gpio/gpio_ifx_cat1.c | 10 +- .../cat1b/cyw20829/clock_source_def.h | 7 + .../cat1b/cyw20829/cyw20829.40-qfn.dtsi | 206 ++++++++ .../cat1b/cyw20829/cyw20829.56-qfn.dtsi | 257 +++++++++ .../cat1b/cyw20829/cyw20829.77-bga.dtsi | 256 +++++++++ dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi | 301 +++++++++++ .../cat1b/cyw20829/system_clocks.dtsi | 105 ++++ .../infineon/cat1b/mpns/CYW20829A0KML.dtsi | 8 + .../infineon/cat1b/mpns/CYW20829A0LKML.dtsi | 8 + .../infineon/cat1b/mpns/CYW20829B0KML.dtsi | 8 + .../infineon/cat1b/mpns/CYW20829B0LKML.dtsi | 13 + .../infineon/cat1b/mpns/CYW89829A0KML.dtsi | 8 + .../infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi | 8 + .../infineon/cat1b/mpns/CYW89829B0KML.dtsi | 8 + .../hal_infineon/mtb-hal-cat1/CMakeLists.txt | 9 + .../hal_infineon/mtb-pdl-cat1/CMakeLists.txt | 17 +- .../mtb-template-cat1/CMakeLists.txt | 22 +- soc/infineon/cat1b/CMakeLists.txt | 5 + soc/infineon/cat1b/Kconfig | 9 + soc/infineon/cat1b/Kconfig.defconfig | 10 + soc/infineon/cat1b/Kconfig.soc | 14 + soc/infineon/cat1b/common/CMakeLists.txt | 4 + soc/infineon/cat1b/common/pinctrl_soc.h | 133 +++++ soc/infineon/cat1b/cyw20829/CMakeLists.txt | 13 + soc/infineon/cat1b/cyw20829/Kconfig | 13 + soc/infineon/cat1b/cyw20829/Kconfig.defconfig | 17 + soc/infineon/cat1b/cyw20829/Kconfig.soc | 79 +++ soc/infineon/cat1b/cyw20829/app_header.c | 45 ++ soc/infineon/cat1b/cyw20829/bootstrap.ld | 114 ++++ soc/infineon/cat1b/cyw20829/linker.ld | 486 ++++++++++++++++++ soc/infineon/cat1b/cyw20829/soc.c | 61 +++ soc/infineon/cat1b/cyw20829/soc.h | 18 + soc/infineon/cat1b/soc.yml | 12 + 46 files changed, 2952 insertions(+), 12 deletions(-) create mode 100644 boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 create mode 100644 boards/infineon/cyw920829m2evk_02/board.cmake create mode 100644 boards/infineon/cyw920829m2evk_02/board.yml create mode 100644 boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi create mode 100644 boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi create mode 100644 boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts create mode 100644 boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml create mode 100644 boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig create mode 100644 boards/infineon/cyw920829m2evk_02/doc/img/cyw920829m2evk_02.webp create mode 100644 boards/infineon/cyw920829m2evk_02/doc/index.rst create mode 100644 boards/infineon/cyw920829m2evk_02/support/openocd.cfg create mode 100644 boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg create mode 100644 dts/arm/infineon/cat1b/cyw20829/clock_source_def.h create mode 100644 dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi create mode 100644 dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi create mode 100644 dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi create mode 100644 dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi create mode 100644 dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi create mode 100644 dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi create mode 100644 soc/infineon/cat1b/CMakeLists.txt create mode 100644 soc/infineon/cat1b/Kconfig create mode 100644 soc/infineon/cat1b/Kconfig.defconfig create mode 100644 soc/infineon/cat1b/Kconfig.soc create mode 100644 soc/infineon/cat1b/common/CMakeLists.txt create mode 100644 soc/infineon/cat1b/common/pinctrl_soc.h create mode 100644 soc/infineon/cat1b/cyw20829/CMakeLists.txt create mode 100644 soc/infineon/cat1b/cyw20829/Kconfig create mode 100644 soc/infineon/cat1b/cyw20829/Kconfig.defconfig create mode 100644 soc/infineon/cat1b/cyw20829/Kconfig.soc create mode 100644 soc/infineon/cat1b/cyw20829/app_header.c create mode 100644 soc/infineon/cat1b/cyw20829/bootstrap.ld create mode 100644 soc/infineon/cat1b/cyw20829/linker.ld create mode 100644 soc/infineon/cat1b/cyw20829/soc.c create mode 100644 soc/infineon/cat1b/cyw20829/soc.h create mode 100644 soc/infineon/cat1b/soc.yml diff --git a/boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 b/boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 new file mode 100644 index 00000000000000..1565606bbbe287 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 @@ -0,0 +1,7 @@ +# The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02) + +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_CYW920829M2EVK_02 + select SOC_CYW20829B0LKML diff --git a/boards/infineon/cyw920829m2evk_02/board.cmake b/boards/infineon/cyw920829m2evk_02/board.cmake new file mode 100644 index 00000000000000..9fa085b7448b3c --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/board.cmake @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/infineon/cyw920829m2evk_02/board.yml b/boards/infineon/cyw920829m2evk_02/board.yml new file mode 100644 index 00000000000000..e25e3922b53595 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/board.yml @@ -0,0 +1,5 @@ +board: + name: cyw920829m2evk_02 + vendor: infineon + socs: + - name: cyw20829b0lkml diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi new file mode 100644 index 00000000000000..d795ccce728be3 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + led0 = &user_led0; + led1 = &user_led1; + sw0 = &user_bt0; + sw1 = &user_bt1; + }; + + leds { + compatible = "gpio-leds"; + user_led0: led_0 { + label = "LED_0"; + gpios = <&gpio_prt1 1 GPIO_ACTIVE_LOW>; + }; + + user_led1: led_1 { + label = "LED_1"; + gpios = <&gpio_prt5 2 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_bt0: user_btn0 { + label = "SW_1"; + gpios = <&gpio_prt0 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + + user_bt1: user_btn1 { + label = "SW_2"; + gpios = <&gpio_prt1 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + }; +}; + +&gpio_prt0 { + status = "okay"; +}; + +&gpio_prt1 { + status = "okay"; +}; + +&gpio_prt3 { + status = "okay"; +}; + +&gpio_prt5 { + status = "okay"; +}; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi new file mode 100644 index 00000000000000..fb6b4571ff5d08 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Configure pin control bias mode for uart2 pins */ +&p3_3_scb2_uart_tx { + drive-push-pull; +}; + +&p3_2_scb2_uart_rx { + input-enable; +}; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts new file mode 100644 index 00000000000000..c96208e5a3ac2b --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "cyw920829m2evk_02-common.dtsi" +#include "cyw920829m2evk_02-pinctrl.dtsi" + +/ { + model = "The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02)"; + compatible = "infineon,cyw920829m2evk_02", "infineon,CYW20829"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &app_region; + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; + +uart2: &scb2 { + compatible = "infineon,cat1-uart"; + status = "okay"; + current-speed = <115200>; + + pinctrl-0 = <&p3_3_scb2_uart_tx &p3_2_scb2_uart_rx>; + pinctrl-names = "default"; +}; + +&fll0 { + status = "okay"; +}; + +&path_mux0 { + status = "okay"; +}; + +&path_mux1 { + status = "okay"; +}; + +&path_mux2 { + status = "okay"; +}; + +&path_mux3 { + status = "okay"; +}; + +&clk_hf0 { + status = "okay"; + clocks = <&fll0>; +}; + +&clk_hf1 { + status = "okay"; +}; + +&clk_hf2 { + status = "okay"; +}; + +&clk_hf3 { + status = "okay"; +}; + +&flash_controller { + + flash0: flash@60000000 { + compatible = "soc-nv-flash"; + reg = <0x60000000 DT_SIZE_K(512)>; + write-block-size = <16>; + erase-block-size = <256>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + toc2_region: flash@60000000 { + compatible = "zephyr,memory-region", "soc-nv-flash"; + zephyr,memory-region = "APP_HEADER_FLASH"; + reg = <0x60000000 0x50>; + }; + bootstrap_region: flash@60000050 { + compatible = "zephyr,memory-region", "soc-nv-flash"; + zephyr,memory-region = "BOOTSTRAP_FLASH"; + reg = <0x60000050 0x2550>; + }; + app_region: flash@60002600 { + compatible = "soc-nv-flash"; + reg = <0x60002600 0x5da00>; + }; + storage_partition: flash@60060000 { + compatible = "soc-nv-flash"; + reg = <0x60060000 0x20000>; + }; + }; + }; +}; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml new file mode 100644 index 00000000000000..590385dc4ec7ae --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml @@ -0,0 +1,21 @@ +# +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: cyw920829m2evk_02 +name: The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02) +type: mcu +arch: arm +ram: 1024 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb +supported: + - gpio + - uart + - clock_control + - bluetooth + +vendor: infineon diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig new file mode 100644 index 00000000000000..a59cfbf692a1d9 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig @@ -0,0 +1,31 @@ +# +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 +# + +# General configuration +CONFIG_CORTEX_M_SYSTICK=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_BUILD_OUTPUT_BIN=y + +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable pin controller +CONFIG_PINCTRL=y + +# Enable GPIO driver +CONFIG_GPIO=y + +# Enable clock controller +CONFIG_CLOCK_CONTROL=y + +# Main Stack Size +CONFIG_MAIN_STACK_SIZE=2048 diff --git a/boards/infineon/cyw920829m2evk_02/doc/img/cyw920829m2evk_02.webp b/boards/infineon/cyw920829m2evk_02/doc/img/cyw920829m2evk_02.webp new file mode 100644 index 0000000000000000000000000000000000000000..130fc8dac657555851a4e97f28e729fae72f28a4 GIT binary patch literal 52226 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 zt69iJEyT|_5Ptu55C8xG000000000000000000000000000000000000000000000 K000000002Zz@}dS literal 0 HcmV?d00001 diff --git a/boards/infineon/cyw920829m2evk_02/doc/index.rst b/boards/infineon/cyw920829m2evk_02/doc/index.rst new file mode 100644 index 00000000000000..ac92f59d12a906 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/doc/index.rst @@ -0,0 +1,125 @@ +.. _cyw920829m2evk_02: + +INFINEON CYW920829M2EVK-02 +############################ + +Overview +******** + +The AIROC™ CYW20829 Bluetooth® LE MCU Evaluation Kit (CYW920829M2EVK-02) with its included on-board peripherals enables evaluation, prototyping, and development of a wide array of Bluetooth® Low Energy applications, all on Infineon's low power, high performance AIROC™ CYW20829. The AIROC™ CYW20829's robust RF performance and 10 dBm TX output power without an external power amplifier (PA). This provides enough link budget for the entire spectrum of Bluetooth® LE use cases including industrial IoT applications, smart home, asset tracking, beacons and sensors, and medical devices. + +The system features Dual Arm® Cortex® - M33s for powering the MCU and Bluetooth subsystem with programmable and reconfigurable analog and digital blocks. In addition, on the kit, there is a suite of on-board peripherals including six-axis inertial measurement unit (IMU), thermistor, analog mic, user programmable buttons (2), LEDs (2), and RGB LED. There is also extensive GPIO support with extended headers and Arduino Uno R3 compatibility for third-party shields. + +.. image:: img/cyw920829m2evk_02.webp + :align: center + :alt: CYW920829M2EVK_02 + +Hardware +******** + +For more information about the CYW20829 SoC and CYW920829M2EVK-02 board: + +- `CYW920829M2EVK-02 Website`_ +- `CYW920829M2EVK-02 BT User Guide`_ + + +Kit Features: +============= + +- AIROC™ CYW20829 Bluetooth® LE MCU in 56 pin QFN package +- Arduino compatible headers for hardware expansion +- On-board sensors - 6-axis IMU, Thermistor, Infineon analog microphone, and Infineon digital microphone +- User switches, RGB LED and user LEDs +- USB connector for power, programming and USB-UART bridge + +Kit Contents: +============= + +- CYW20829 evaluation board (CYW9BTM2BASE3+CYW920829M2IPA2) +- USB Type-A to Micro-B cable +- Six jumper wires (five inches each) +- Quick start guide + + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| GPIO | on-chip | GPIO | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-----------------------+ + + +The default configuration can be found in the Kconfig + +:zephyr_file:`boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig` + +System Clock +============ + +The AIROC™ CYW20829 Bluetooth® MCU SoC is configured to use the internal IMO+FLL as a source for +the system clock. Other sources for the system clock are provided in the SOC, depending on your +system requirements. + +Build blinking led sample +************************* + +Here is an example for the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: cyw920829m2evk_02 + :goals: build flash + +OpenOCD Installation +==================== + +To get the OpenOCD package, it is required that you + +1. Download and install the `ModusToolbox`_ software. +2. After the installation, add the directory containing the OpenOCD scripts to your environment's PATH variable. + + +Programming and Debugging +************************* + +The CYW920829M2EVK-02 includes an onboard programmer/debugger (KitProg3) to provide debugging, flash programming, and serial communication over USB. Flash and debug commands must be pointed to the Cypress OpenOCD you downloaded above. + +On Windows: + +.. code-block:: console + + west flash --openocd path/to/infineon/openocd/bin/openocd.exe + west debug --openocd path/to/infineon/openocd/bin/openocd.exe + +On Linux: + +.. code-block:: console + + west flash --openocd path/to/infineon/openocd/bin/openocd + west debug --openocd path/to/infineon/openocd/bin/openocd + +Once the gdb console starts after executing the west debug command, you may now set breakpoints and perform other standard GDB debugging on the CYW20829 CM33 core. + +.. _CYW920829M2EVK-02 Website: + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-bluetooth-le-bluetooth-multiprotocol/airoc-bluetooth-le/cyw20829/ + +.. _CYW920829M2EVK-02 BT User Guide: + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-bluetooth-le-bluetooth-multiprotocol/airoc-bluetooth-le/cyw20829/#!?fileId=8ac78c8c8929aa4d018a16f726c46b26 + +.. _ModusToolbox: + https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox + +.. _Infineon OpenOCD: + https://github.com/infineon/openocd/releases/tag/release-v4.3.0 diff --git a/boards/infineon/cyw920829m2evk_02/support/openocd.cfg b/boards/infineon/cyw920829m2evk_02/support/openocd.cfg new file mode 100644 index 00000000000000..419ffc13abc1a1 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/support/openocd.cfg @@ -0,0 +1,10 @@ +# +# Copyright (c) 2018 Linaro Limited. +# +# SPDX-License-Identifier: Apache-2.0 + +source [find interface/kitprog3.cfg] + +transport select swd + +source [find target/cyw20829.cfg] diff --git a/boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg b/boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg new file mode 100644 index 00000000000000..f702d5409dc0b7 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg @@ -0,0 +1,29 @@ +################################################################################ +# File Name: qspi_config.cfg +# +# Description: +# This file contains a SMIF Bank layout for use with OpenOCD. +# This file was automatically generated and should not be modified. +# QSPI Configurator: 4.22.0.1756 +# +################################################################################ +# Copyright 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ + +set SMIF_BANKS { + 0 {addr 0x60000000 size 0x100000 psize 0x0000100 esize 0x0001000} +} diff --git a/drivers/clock_control/clock_control_ifx_cat1.c b/drivers/clock_control/clock_control_ifx_cat1.c index 7e17b94951434a..4d8f4603b44e3a 100644 --- a/drivers/clock_control/clock_control_ifx_cat1.c +++ b/drivers/clock_control/clock_control_ifx_cat1.c @@ -18,7 +18,13 @@ /* Enumeration of enabled in device tree Clock, uses for indexing clock info table */ enum { +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) INFINEON_CAT1_CLOCK_IMO, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + INFINEON_CAT1_CLOCK_IHO, +#endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(path_mux0), okay) INFINEON_CAT1_CLOCK_PATHMUX0, @@ -60,6 +66,42 @@ enum { INFINEON_CAT1_CLOCK_HF4, #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf5), okay) + INFINEON_CAT1_CLOCK_HF5, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf6), okay) + INFINEON_CAT1_CLOCK_HF6, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf7), okay) + INFINEON_CAT1_CLOCK_HF7, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf8), okay) + INFINEON_CAT1_CLOCK_HF8, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf9), okay) + INFINEON_CAT1_CLOCK_HF9, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf10), okay) + INFINEON_CAT1_CLOCK_HF10, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf11), okay) + INFINEON_CAT1_CLOCK_HF11, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf12), okay) + INFINEON_CAT1_CLOCK_HF12, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf13), okay) + INFINEON_CAT1_CLOCK_HF13, +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_fast), okay) INFINEON_CAT1_CLOCK_FAST, #endif @@ -100,7 +142,13 @@ struct infineon_cat1_clock_info_t { static struct infineon_cat1_clock_info_t clock_info_table[INFINEON_CAT1_ENABLED_CLOCK_COUNT] = { /* We always have IMO */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) [INFINEON_CAT1_CLOCK_IMO] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_imo)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + [INFINEON_CAT1_CLOCK_IHO] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_iho)) }, +#endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(path_mux0), okay) [INFINEON_CAT1_CLOCK_PATHMUX0] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(path_mux0)) }, @@ -142,6 +190,42 @@ static struct infineon_cat1_clock_info_t [INFINEON_CAT1_CLOCK_HF4] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf4)) }, #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf5), okay) + [INFINEON_CAT1_CLOCK_HF5] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf5)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf6), okay) + [INFINEON_CAT1_CLOCK_HF6] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf6)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf7), okay) + [INFINEON_CAT1_CLOCK_HF7] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf7)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf8), okay) + [INFINEON_CAT1_CLOCK_HF8] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf8)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf9), okay) + [INFINEON_CAT1_CLOCK_HF9] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf9)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf10), okay) + [INFINEON_CAT1_CLOCK_HF10] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf10)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf11), okay) + [INFINEON_CAT1_CLOCK_HF11] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf11)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf12), okay) + [INFINEON_CAT1_CLOCK_HF12] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf12)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf13), okay) + [INFINEON_CAT1_CLOCK_HF13] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf13)) }, +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_fast), okay) [INFINEON_CAT1_CLOCK_FAST] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_fast)) }, #endif @@ -242,13 +326,67 @@ static cyhal_clock_t *_get_hal_obj_from_ord(uint32_t dt_ord) return ret_obj; } +#if DT_NODE_HAS_STATUS(DT_NODELABEL(dpll_hp), okay) +__WEAK void cycfg_ClockStartupError(uint32_t error) +{ + (void)error; /* Suppress the compiler warning */ + while (1) { + } +} + +void Cy_SysClk_Dpll_Hp0_Init(void) +{ +#define CY_CFG_SYSCLK_PLL_ERROR 3 + + static cy_stc_dpll_hp_config_t srss_0_clock_0_pll500m_0_hp_pllConfig = { + .pDiv = 0, + .nDiv = 15, + .kDiv = 1, + .nDivFract = 0, + .freqModeSel = CY_SYSCLK_DPLL_HP_CLK50MHZ_1US_CNT_VAL, + .ivrTrim = 0x8U, + .clkrSel = 0x1U, + .alphaCoarse = 0xCU, + .betaCoarse = 0x5U, + .flockThresh = 0x3U, + .flockWait = 0x6U, + .flockLkThres = 0x7U, + .flockLkWait = 0x4U, + .alphaExt = 0x14U, + .betaExt = 0x14U, + .lfEn = 0x1U, + .dcEn = 0x1U, + .outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO, + }; + static cy_stc_pll_manual_config_t srss_0_clock_0_pll500m_0_pllConfig = { + .hpPllCfg = &srss_0_clock_0_pll500m_0_hp_pllConfig, + }; + +#if !defined(CY_PDL_TZ_ENABLED) + if (Cy_SysClk_PllIsEnabled(SRSS_DPLL_HP_0_PATH_NUM)) { + return; + } +#endif + Cy_SysClk_PllDisable(SRSS_DPLL_HP_0_PATH_NUM); + if (CY_SYSCLK_SUCCESS != + Cy_SysClk_PllManualConfigure(SRSS_DPLL_HP_0_PATH_NUM, + &srss_0_clock_0_pll500m_0_pllConfig)) { + cycfg_ClockStartupError(CY_CFG_SYSCLK_PLL_ERROR); + } + if (CY_SYSCLK_SUCCESS != Cy_SysClk_PllEnable(SRSS_DPLL_HP_0_PATH_NUM, 10000u)) { + cycfg_ClockStartupError(CY_CFG_SYSCLK_PLL_ERROR); + } +} +#endif + static int clock_control_infineon_cat1_init(const struct device *dev) { ARG_UNUSED(dev); cy_rslt_t rslt; cyhal_clock_t *clock_obj = NULL; cyhal_clock_t *clock_source_obj = NULL; - uint32 frequency; + + __attribute__((unused)) uint32 frequency; uint32 clock_div; /* Configure IMO */ @@ -257,8 +395,16 @@ static int clock_control_infineon_cat1_init(const struct device *dev) if (cyhal_clock_get(clock_obj, &CYHAL_CLOCK_RSC_IMO)) { return -EIO; } -#else - #error "IMO clock must be enabled" +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_IHO].obj; + if (cyhal_clock_get(clock_obj, &CYHAL_CLOCK_RSC_IHO)) { + return -EIO; + } +#endif +#if !DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) && \ + !DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + #error "IMO clock or IHO clock must be enabled" #endif /* Configure the PathMux[0] to source defined in tree device 'path_mux0' node */ @@ -403,6 +549,105 @@ static int clock_control_infineon_cat1_init(const struct device *dev) } #endif + /* Configure the HF[5] to source defined in tree device 'clk_hf5' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf5), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF5].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf5)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf5), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[5], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[6] to source defined in tree device 'clk_hf6' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf6), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF6].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf6)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf6), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[6], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[7] to source defined in tree device 'clk_hf7' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf7), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF7].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf7)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf7), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[7], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[8] to source defined in tree device 'clk_hf8' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf8), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF8].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf8)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf8), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[8], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[9] to source defined in tree device 'clk_hf9' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf9), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF9].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf9)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf9), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[9], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[10] to source defined in tree device 'clk_hf10' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf10), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF10].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf10)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf10), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[10], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[11] to source defined in tree device 'clk_hf11' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf11), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF11].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf11)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf11), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[11], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[12] to source defined in tree device 'clk_hf12' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf12), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF12].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf12)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf12), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[12], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[13] to source defined in tree device 'clk_hf13' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf13), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF13].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf13)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf13), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[13], clock_div)) { + return -EIO; + } +#endif + /* Configure the clock fast to source defined in tree device 'clk_fast' node */ #if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_fast), okay) clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_FAST].obj; @@ -445,6 +690,11 @@ static int clock_control_infineon_cat1_init(const struct device *dev) } #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(dpll_hp), okay) + Cy_SysClk_Dpll_Hp0_Init(); + SystemCoreClockUpdate(); +#endif + return (int) rslt; } @@ -463,6 +713,7 @@ static const struct clock_control_driver_api clock_control_infineon_cat1_api = { .off = clock_control_infineon_cat_on_off }; +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) DEVICE_DT_DEFINE(DT_NODELABEL(clk_imo), &clock_control_infineon_cat1_init, NULL, @@ -471,3 +722,14 @@ DEVICE_DT_DEFINE(DT_NODELABEL(clk_imo), PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_infineon_cat1_api); +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) +DEVICE_DT_DEFINE(DT_NODELABEL(clk_iho), + &clock_control_infineon_cat1_init, + NULL, + NULL, + NULL, + PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, + &clock_control_infineon_cat1_api); +#endif diff --git a/drivers/gpio/gpio_ifx_cat1.c b/drivers/gpio/gpio_ifx_cat1.c index 5d1851ef9e4c40..f97b6f446c7338 100644 --- a/drivers/gpio/gpio_ifx_cat1.c +++ b/drivers/gpio/gpio_ifx_cat1.c @@ -59,7 +59,15 @@ struct gpio_cat1_data { /* Map port number to device object */ static const struct device *const port_dev_obj[IOSS_GPIO_GPIO_PORT_NR] = { - LISTIFY(15, GET_DEV_OBJ_FROM_LIST, (,)) + /* the integer used as the first variable in listify is equivalent to + * IOSS_GPIO_GPIO_PORT_NR for the respective categories, but using + * the macro in LISTIFY causes build failures + */ + #if CONFIG_SOC_FAMILY_INFINEON_CAT1A + LISTIFY(15, GET_DEV_OBJ_FROM_LIST, (,)) + #elif CONFIG_SOC_FAMILY_INFINEON_CAT1B + LISTIFY(6, GET_DEV_OBJ_FROM_LIST, (,)) + #endif }; static int gpio_cat1_configure(const struct device *dev, diff --git a/dts/arm/infineon/cat1b/cyw20829/clock_source_def.h b/dts/arm/infineon/cat1b/cyw20829/clock_source_def.h new file mode 100644 index 00000000000000..26921d08235d8a --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/clock_source_def.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024, Cypress Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +#define CLK_SOURCE_IHO +#define CLK_SOURCE_PILO diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi new file mode 100644 index 00000000000000..aff1340f797128 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cyw20829.dtsi" + +/ { + soc { + + pinctrl: pinctrl@40400000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p1_2_scb2_i2c_scl: p1_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_i2c_scl: p3_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_i2c_scl: p4_0_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_i2c_scl: p5_0_scb2_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p1_3_scb2_i2c_sda: p1_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_i2c_sda: p3_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_i2c_sda: p4_1_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb2_i2c_sda: p5_1_scb2_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_m_clk: p1_1_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_m_clk: p3_1_scb1_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p1_3_scb1_spi_m_miso: p1_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_m_miso: p3_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_m_miso: p4_1_scb0_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p1_2_scb1_spi_m_mosi: p1_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_m_mosi: p3_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_m_mosi: p4_0_scb0_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_m_select0: p1_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_m_select0: p5_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_m_select0: p5_1_scb0_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_5_scb1_spi_m_select1: p0_5_scb1_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_4_scb1_spi_m_select2: p0_4_scb1_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_s_clk: p1_1_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_s_clk: p3_1_scb1_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p1_3_scb1_spi_s_miso: p1_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_s_miso: p3_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_s_miso: p4_1_scb0_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p1_2_scb1_spi_s_mosi: p1_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_s_mosi: p3_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_s_mosi: p4_0_scb0_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_s_select0: p1_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_s_select0: p5_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_s_select0: p5_1_scb0_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_5_scb1_spi_s_select1: p0_5_scb1_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_4_scb1_spi_s_select2: p0_4_scb1_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + + /* scb_uart_cts */ + /omit-if-no-ref/ p1_0_scb1_uart_cts: p1_0_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb2_uart_cts: p4_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_uart_cts: p5_0_scb2_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p1_1_scb1_uart_rts: p1_1_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_rts: p3_1_scb2_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p1_2_scb1_uart_rx: p1_2_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rx: p3_2_scb2_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p1_3_scb1_uart_tx: p1_3_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_tx: p3_3_scb2_uart_tx { + pinmux = ; + }; + + }; + }; +}; + +&gpio_prt0 { + ngpios = <2>; +}; +&gpio_prt1 { + ngpios = <4>; +}; +&gpio_prt3 { + ngpios = <3>; +}; +&gpio_prt5 { + ngpios = <2>; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi new file mode 100644 index 00000000000000..a94c9744b9e9d1 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cyw20829.dtsi" + +/ { + + soc { + + pinctrl: pinctrl@40400000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb2_i2c_scl: p1_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_i2c_scl: p3_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_i2c_scl: p4_0_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_i2c_scl: p5_0_scb2_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb2_i2c_sda: p1_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_i2c_sda: p3_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_i2c_sda: p4_1_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb2_i2c_sda: p5_1_scb2_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_m_clk: p1_1_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_m_clk: p3_1_scb1_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_m_miso: p0_3_scb0_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_m_miso: p1_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_m_miso: p3_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_m_miso: p4_1_scb0_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_m_mosi: p0_2_scb0_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_m_mosi: p1_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_m_mosi: p3_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_m_mosi: p4_0_scb0_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_m_select0: p1_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_m_select0: p3_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_m_select0: p5_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_m_select0: p5_1_scb0_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_m_select1: p0_0_scb0_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_m_select1: p0_5_scb1_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_m_select1: p3_6_scb1_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_m_select2: p0_1_scb0_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_m_select2: p0_4_scb1_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_m_select2: p3_5_scb1_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_m_select3: p0_3_scb1_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_m_select3: p3_4_scb1_spi_m_select3 { + pinmux = ; + }; + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_s_clk: p1_1_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_s_clk: p3_1_scb1_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_s_miso: p0_3_scb0_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_s_miso: p1_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_s_miso: p3_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_s_miso: p4_1_scb0_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_s_mosi: p0_2_scb0_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_s_mosi: p1_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_s_mosi: p3_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_s_mosi: p4_0_scb0_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_s_select0: p1_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_s_select0: p3_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_s_select0: p5_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_s_select0: p5_1_scb0_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_s_select1: p0_0_scb0_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_s_select1: p0_5_scb1_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_s_select1: p3_6_scb1_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_s_select2: p0_1_scb0_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_s_select2: p0_4_scb1_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_s_select2: p3_5_scb1_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_s_select3: p0_3_scb1_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_s_select3: p3_4_scb1_spi_s_select3 { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p1_0_scb1_uart_cts: p1_0_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_uart_cts: p3_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb2_uart_cts: p4_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_uart_cts: p5_0_scb2_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p1_1_scb1_uart_rts: p1_1_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_rts: p3_1_scb2_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p1_2_scb1_uart_rx: p1_2_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rx: p3_2_scb2_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p1_3_scb1_uart_tx: p1_3_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_tx: p3_3_scb2_uart_tx { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi new file mode 100644 index 00000000000000..6975188c561675 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cyw20829.dtsi" + +/ { + soc { + + pinctrl: pinctrl@40400000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb2_i2c_scl: p1_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_i2c_scl: p3_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_i2c_scl: p4_0_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_i2c_scl: p5_0_scb2_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb2_i2c_sda: p1_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_i2c_sda: p3_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_i2c_sda: p4_1_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb2_i2c_sda: p5_1_scb2_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_m_clk: p1_1_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_m_clk: p3_1_scb1_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_m_miso: p0_3_scb0_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_m_miso: p1_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_m_miso: p3_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_m_miso: p4_1_scb0_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_m_mosi: p0_2_scb0_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_m_mosi: p1_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_m_mosi: p3_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_m_mosi: p4_0_scb0_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_m_select0: p1_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_m_select0: p3_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_m_select0: p5_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_m_select0: p5_1_scb0_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_m_select1: p0_0_scb0_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_m_select1: p0_5_scb1_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_m_select1: p3_6_scb1_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_m_select2: p0_1_scb0_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_m_select2: p0_4_scb1_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_m_select2: p3_5_scb1_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_m_select3: p0_3_scb1_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_m_select3: p3_4_scb1_spi_m_select3 { + pinmux = ; + }; + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_s_clk: p1_1_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_s_clk: p3_1_scb1_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_s_miso: p0_3_scb0_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_s_miso: p1_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_s_miso: p3_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_s_miso: p4_1_scb0_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_s_mosi: p0_2_scb0_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_s_mosi: p1_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_s_mosi: p3_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_s_mosi: p4_0_scb0_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_s_select0: p1_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_s_select0: p3_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_s_select0: p5_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_s_select0: p5_1_scb0_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_s_select1: p0_0_scb0_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_s_select1: p0_5_scb1_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_s_select1: p3_6_scb1_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_s_select2: p0_1_scb0_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_s_select2: p0_4_scb1_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_s_select2: p3_5_scb1_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_s_select3: p0_3_scb1_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_s_select3: p3_4_scb1_spi_s_select3 { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p1_0_scb1_uart_cts: p1_0_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_uart_cts: p3_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb2_uart_cts: p4_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_uart_cts: p5_0_scb2_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p1_1_scb1_uart_rts: p1_1_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_rts: p3_1_scb2_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p1_2_scb1_uart_rx: p1_2_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rx: p3_2_scb2_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p1_3_scb1_uart_tx: p1_3_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_tx: p3_3_scb2_uart_tx { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi new file mode 100644 index 00000000000000..a0653ea6ba30fa --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m33"; + reg = <0>; + }; + }; + + flash_controller: flash_controller@40250000 { + compatible = "infineon,cat1-flash-controller"; + reg = <0x40250000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x3DC00>; + }; + + sram_bootstrap: memory@2003DC00 { + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "BOOTSTRAP_RAM"; + reg = <0x2003DC00 0x2400>; + }; + + soc { + pinctrl: pinctrl@40400000 { + compatible = "infineon,cat1-pinctrl"; + reg = <0x40400000 0x20000>; + }; + + hsiom: hsiom@40400000 { + compatible = "infineon,cat1-hsiom"; + reg = <0x40400000 0x4000>; + interrupts = <7 6>, <6 6>; + status = "disabled"; + }; + + gpio_prt0: gpio@40410000 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410000 0x80>; + interrupts = <0 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt1: gpio@40410080 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410080 0x80>; + interrupts = <1 6>; + gpio-controller; + ngpios = <7>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt2: gpio@40410100 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410100 0x80>; + interrupts = <2 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt3: gpio@40410180 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410180 0x80>; + interrupts = <3 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt4: gpio@40410200 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410200 0x80>; + interrupts = <4 6>; + gpio-controller; + ngpios = <2>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt5: gpio@40410280 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410280 0x80>; + interrupts = <5 6>; + gpio-controller; + ngpios = <3>; + status = "disabled"; + #gpio-cells = <2>; + }; + + ipc0: ipc@401d0000 { + compatible = "infineon,cat1-ipc"; + reg = <0x401d0000 0x10000>; + status = "disabled"; + #ipc-config-cells = <3>; + }; + + scb0: scb@40590000 { + compatible = "infineon,cat1-scb"; + reg = <0x40590000 0xfd0>; + interrupts = <8 6>; + status = "disabled"; + }; + scb1: scb@405a0000 { + compatible = "infineon,cat1-scb"; + reg = <0x405a0000 0xfd0>; + interrupts = <17 6>; + status = "disabled"; + }; + scb2: scb@405b0000 { + compatible = "infineon,cat1-scb"; + reg = <0x405b0000 0xfd0>; + interrupts = <18 6>; + status = "disabled"; + }; + + watchdog0: watchdog@4020c000 { + compatible = "infineon,cat1-watchdog"; + reg = <0x4020c000 0x10>; + interrupts = <15 6>; + status = "disabled"; + }; + + mcwdt0: mcwdt@4020d000 { + compatible = "infineon,cat1-lp-timer"; + reg = <0x4020d000 0x40>; + interrupts = <9 6>; + status = "disabled"; + }; + + counter0_0: counter@404a0000 { + compatible = "infineon,cat1-counter"; + reg = <0x404a0000 0x80>; + interrupts = <42 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_1: counter@404a0080 { + compatible = "infineon,cat1-counter"; + reg = <0x404a0080 0x80>; + interrupts = <43 6>; + resolution = <32>; + status = "disabled"; + }; + counter1_0: counter@404a8000 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8000 0x80>; + interrupts = <44 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_1: counter@404a8080 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8080 0x80>; + interrupts = <45 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_2: counter@404a8100 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8100 0x80>; + interrupts = <46 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_3: counter@404a8180 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8180 0x80>; + interrupts = <47 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_4: counter@404a8200 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8200 0x80>; + interrupts = <48 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_5: counter@404a8280 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8280 0x80>; + interrupts = <49 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_6: counter@404a8300 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8300 0x80>; + interrupts = <50 6>; + resolution = <16>; + status = "disabled"; + }; + + pwm0_0: pwm@404a0000 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a0000 0x80>; + interrupts = <42 6>; + resolution = <32>; + status = "disabled"; + }; + pwm0_1: pwm@404a0080 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a0080 0x80>; + interrupts = <43 6>; + resolution = <32>; + status = "disabled"; + }; + pwm1_0: pwm@404a8000 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8000 0x80>; + interrupts = <44 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_1: pwm@404a8080 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8080 0x80>; + interrupts = <45 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_2: pwm@404a8100 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8100 0x80>; + interrupts = <46 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_3: pwm@404a8180 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8180 0x80>; + interrupts = <47 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_4: pwm@404a8200 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8200 0x80>; + interrupts = <48 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_5: pwm@404a8280 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8280 0x80>; + interrupts = <49 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_6: pwm@404a8300 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8300 0x80>; + interrupts = <50 6>; + resolution = <16>; + status = "disabled"; + }; + + dma0: dw@40180000 { + #dma-cells = <1>; + compatible = "infineon,cat1-dma"; + reg = <0x40180000 0x10000>; + dma-channels = <16>; + interrupts = <19 6>, /* CH0 */ + <20 6>, /* CH1 */ + <21 6>, /* CH2 */ + <22 6>, /* CH3 */ + <23 6>, /* CH4 */ + <24 6>, /* CH5 */ + <25 6>, /* CH6 */ + <26 6>, /* CH7 */ + <27 6>, /* CH8 */ + <28 6>, /* CH9 */ + <29 6>, /* CH10 */ + <30 6>, /* CH11 */ + <31 6>, /* CH12 */ + <32 6>, /* CH13 */ + <33 6>, /* CH14 */ + <34 6>; /* CH15 */ + status = "disabled"; + }; + + }; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi b/dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi new file mode 100644 index 00000000000000..b40054d67a36a0 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "clock_source_def.h" +/ { + clocks { + /* iho */ + clk_iho: clk_iho { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <48000000>; + status = "okay"; + }; + + /* imo */ + clk_imo: clk_imo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <8000000>; + status = "okay"; + }; + + /* fll */ + fll0: fll0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <96000000>; + status = "okay"; + }; + + /* path mux0 */ + path_mux0: path_mux0 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_iho>; + status = "disabled"; + }; + + /* path mux1 */ + path_mux1: path_mux1 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_iho>; + status = "disabled"; + }; + + /* path mux2 */ + path_mux2: path_mux2 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_iho>; + status = "disabled"; + }; + + /* path mux3 */ + path_mux3: path_mux3 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_imo>; + status = "disabled"; + }; + + /* clk_hf0 */ + clk_hf0: clk_hf0 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clocks = <&fll0>; + status = "disabled"; + }; + + /* clk_hf1 */ + clk_hf1: clk_hf1 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clocks = <&fll0>; + status = "disabled"; + }; + + /* clk_hf2 */ + clk_hf2: clk_hf2 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clocks = <&path_mux2>; + status = "disabled"; + }; + + /* clk_hf3 */ + clk_hf3: clk_hf3 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <2>; + clocks = <&path_mux1>; + status = "disabled"; + }; + + }; + +}; diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi new file mode 100644 index 00000000000000..d1fc0a7c026897 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi new file mode 100644 index 00000000000000..05ea3e26ed06f2 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.56-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi new file mode 100644 index 00000000000000..d1fc0a7c026897 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi new file mode 100644 index 00000000000000..d3ba211c22435a --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "../cyw20829/cyw20829.56-qfn.dtsi" + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi new file mode 100644 index 00000000000000..d1fc0a7c026897 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi b/dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi new file mode 100644 index 00000000000000..363ad188050f28 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.77-bga.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi new file mode 100644 index 00000000000000..d1fc0a7c026897 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt index e3d468cd764122..2d7641f59b641e 100644 --- a/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt @@ -5,9 +5,11 @@ set(hal_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-hal-cat1) set(hal_cat1a_dir ${hal_dir}/COMPONENT_CAT1A) +set(hal_cat1b_dir ${hal_dir}/COMPONENT_CAT1B) # PSoC 6 family defines zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A COMPONENT_CAT1A) +zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B COMPONENT_CAT1B) zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 COMPONENT_CAT1) zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 CY_USING_HAL) @@ -15,6 +17,7 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 CY_USING_HAL) zephyr_include_directories(${hal_dir}/include) zephyr_include_directories(${hal_dir}/include_pvt) zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${hal_cat1a_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${hal_cat1b_dir}/include) # Packages sources zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE @@ -54,6 +57,12 @@ zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_04_68_QFN zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_04_80_TQFP ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_04_80_tqfp.c) +zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_CYW20829_56_QFN + ${hal_cat1b_dir}/source/pin_packages/cyhal_cyw20829_56_qfn.c) + +zephyr_library_sources_ifdef(CONFIG_SOC_DIE_CYW20829 + ${hal_cat1b_dir}/source/triggers/cyhal_triggers_cyw20829.c) + zephyr_library_sources_ifdef(CONFIG_SOC_DIE_PSOC6_01 ${hal_cat1a_dir}/source/triggers/cyhal_triggers_psoc6_01.c) zephyr_library_sources_ifdef(CONFIG_SOC_DIE_PSOC6_02 diff --git a/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt index f7461673961f88..3d264fd5ee5bc4 100644 --- a/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt @@ -6,6 +6,7 @@ set(pdl_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1) set(pdl_drv_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/drivers) set(pdl_dev_cat1a_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/devices/COMPONENT_CAT1A) +set(pdl_dev_cat1b_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/devices/COMPONENT_CAT1B) # Generate PDL specific SOC defines @@ -17,10 +18,15 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_CYBLE_416045_02 CYBLE_416045_02_devi # Add mtb-pdl-cat1 zephyr_include_directories(${pdl_drv_dir}/include) -zephyr_include_directories(${pdl_dev_cat1a_dir}/include) -zephyr_include_directories(${pdl_dev_cat1a_dir}/include/ip) -zephyr_library_sources(${pdl_dev_cat1a_dir}/source/cy_device.c) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${pdl_dev_cat1a_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${pdl_dev_cat1a_dir}/include/ip) +zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${pdl_dev_cat1a_dir}/source/cy_device.c) + +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${pdl_dev_cat1b_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${pdl_dev_cat1b_dir}/include/ip) +zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${pdl_dev_cat1b_dir}/source/cy_device.c) + zephyr_library_sources(${pdl_drv_dir}/source/TOOLCHAIN_GCC_ARM/cy_syslib_ext.S) # Peripheral drivers @@ -61,6 +67,11 @@ zephyr_library_sources(${pdl_drv_dir}/source/cy_ipc_pipe.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_ipc_sema.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_prot.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_sysclk.c) +if(CONFIG_SOC_FAMILY_INFINEON_CAT1B) + zephyr_library_sources(${pdl_drv_dir}/source/cy_sysclk_v2.c) + zephyr_library_sources(${pdl_drv_dir}/source/cy_systick_v2.c) + zephyr_library_sources(${pdl_drv_dir}/source/cy_syspm_btss.c) +endif() zephyr_library_sources(${pdl_drv_dir}/source/cy_syslib.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_syspm.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_systick.c) diff --git a/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt index 896156527fa8b3..8e7df38166db86 100644 --- a/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt @@ -5,10 +5,22 @@ set(template_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-template-cat1) set(cat1a_dir ${template_dir}/files/templates/cat1a) +set(cat1b_dir ${template_dir}/files/templates/cat1b) -zephyr_include_directories(${cat1a_dir}/COMPONENT_MTB) +if(CONFIG_SOC_FAMILY_INFINEON_CAT1A) + zephyr_include_directories(${cat1a_dir}/COMPONENT_MTB) + zephyr_include_directories(${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM33/HEADER_FILES) -zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M4 - ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM4/system_psoc6_cm4.c) -zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M0PLUS - ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.c) + zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M4 + ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM4/system_psoc6_cm4.c) + zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M0PLUS + ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.c) +endif() + + +# Add support cyw20829 (cat1b) +if(CONFIG_SOC_FAMILY_INFINEON_CAT1B) + zephyr_include_directories(${cat1b_dir}/COMPONENT_MTB) + zephyr_include_directories(${cat1b_dir}/COMPONENT_MTB/COMPONENT_CM33/HEADER_FILES) + zephyr_library_sources(${cat1b_dir}/COMPONENT_MTB/COMPONENT_CM33/system_cyw20829.c) +endif() diff --git a/soc/infineon/cat1b/CMakeLists.txt b/soc/infineon/cat1b/CMakeLists.txt new file mode 100644 index 00000000000000..936ff2b9d6799d --- /dev/null +++ b/soc/infineon/cat1b/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(common) +add_subdirectory(${SOC_SERIES}) diff --git a/soc/infineon/cat1b/Kconfig b/soc/infineon/cat1b/Kconfig new file mode 100644 index 00000000000000..020436ead22cf5 --- /dev/null +++ b/soc/infineon/cat1b/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_INFINEON_CAT1B + +rsource "*/Kconfig" + +endif # SOC_FAMILY_INFINEON_CAT1B diff --git a/soc/infineon/cat1b/Kconfig.defconfig b/soc/infineon/cat1b/Kconfig.defconfig new file mode 100644 index 00000000000000..72ad49d573713e --- /dev/null +++ b/soc/infineon/cat1b/Kconfig.defconfig @@ -0,0 +1,10 @@ +# PSOC CAT1B Configuration + +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_INFINEON_CAT1B + +rsource "*/Kconfig.defconfig" + +endif # SOC_FAMILY_INFINEON_CAT1B diff --git a/soc/infineon/cat1b/Kconfig.soc b/soc/infineon/cat1b/Kconfig.soc new file mode 100644 index 00000000000000..602dfc1a00c399 --- /dev/null +++ b/soc/infineon/cat1b/Kconfig.soc @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Family definitions +config SOC_FAMILY_INFINEON_CAT1 + bool + +config SOC_FAMILY_INFINEON_CAT1B + bool + select SOC_FAMILY_INFINEON_CAT1 + +# MPNs definitions +rsource "*/Kconfig.soc" diff --git a/soc/infineon/cat1b/common/CMakeLists.txt b/soc/infineon/cat1b/common/CMakeLists.txt new file mode 100644 index 00000000000000..eff44801d0c36e --- /dev/null +++ b/soc/infineon/cat1b/common/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) diff --git a/soc/infineon/cat1b/common/pinctrl_soc.h b/soc/infineon/cat1b/common/pinctrl_soc.h new file mode 100644 index 00000000000000..7832c1b39de37c --- /dev/null +++ b/soc/infineon/cat1b/common/pinctrl_soc.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016-2017 Piotr Mienkowski + * Copyright (c) 2021 ATL Electronics + * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +/** + * @brief Infineon CAT1 SoC specific helpers for pinctrl driver. + */ + +#ifndef ZEPHYR_SOC_ARM_INFINEON_CAT1_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_INFINEON_CAT1_COMMON_PINCTRL_SOC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/** + * Bit definition in PINMUX field + */ +#define SOC_PINMUX_PORT_POS (0) +#define SOC_PINMUX_PORT_MASK (0xFFul << SOC_PINMUX_PORT_POS) +#define SOC_PINMUX_PIN_POS (8) +#define SOC_PINMUX_PIN_MASK (0xFFul << SOC_PINMUX_PIN_POS) +#define SOC_PINMUX_HSIOM_FUNC_POS (16) +#define SOC_PINMUX_HSIOM_MASK (0xFFul << SOC_PINMUX_HSIOM_FUNC_POS) +#define SOC_PINMUX_SIGNAL_POS (24) +#define SOC_PINMUX_SIGNAL_MASK (0xFFul << SOC_PINMUX_SIGNAL_POS) + +/* + * Pin flags/attributes + */ +#define SOC_GPIO_DEFAULT (0) +#define SOC_GPIO_FLAGS_POS (0) +#define SOC_GPIO_FLAGS_MASK (0x3F << SOC_GPIO_FLAGS_POS) +#define SOC_GPIO_PULLUP_POS (0) +#define SOC_GPIO_PULLUP (1 << SOC_GPIO_PULLUP_POS) +#define SOC_GPIO_PULLDOWN_POS (1) +#define SOC_GPIO_PULLDOWN (1 << SOC_GPIO_PULLDOWN_POS) +#define SOC_GPIO_OPENDRAIN_POS (2) +#define SOC_GPIO_OPENDRAIN (1 << SOC_GPIO_OPENDRAIN_POS) +#define SOC_GPIO_OPENSOURCE_POS (3) +#define SOC_GPIO_OPENSOURCE (1 << SOC_GPIO_OPENSOURCE_POS) + +/* Push-Pull means Strong, see dts/pinctrl/pincfg-node.yaml */ +#define SOC_GPIO_PUSHPULL_POS (4) +#define SOC_GPIO_PUSHPULL (1 << SOC_GPIO_PUSHPULL_POS) + +/* Input-Enable means Input-Buffer, see dts/pinctrl/pincfg-node.yaml */ +#define SOC_GPIO_INPUTENABLE_POS (5) +#define SOC_GPIO_INPUTENABLE (1 << SOC_GPIO_INPUTENABLE_POS) + +#define SOC_GPIO_HIGHZ_POS (6) +#define SOC_GPIO_HIGHZ (1 << SOC_GPIO_HIGHZ_POS) + +/** Type for CAT1 Soc pin. */ +typedef struct { + /** + * Pinmux settings (port, pin and function). + * [0..7] - Port nunder + * [8..15] - Pin number + * [16..23]- HSIOM function + */ + uint32_t pinmux; + + /** Pin configuration (bias, drive and slew rate). */ + uint32_t pincfg; +} pinctrl_soc_pin_t; + +#define CAT1_PINMUX_GET_PORT_NUM(pinmux) \ + (((pinmux) & SOC_PINMUX_PORT_MASK) >> SOC_PINMUX_PORT_POS) +#define CAT1_PINMUX_GET_PIN_NUM(pinmux) \ + (((pinmux) & SOC_PINMUX_PIN_MASK) >> SOC_PINMUX_PIN_POS) +#define CAT1_PINMUX_GET_HSIOM_FUNC(pinmux) \ + (((pinmux) & SOC_PINMUX_HSIOM_MASK) >> SOC_PINMUX_HSIOM_FUNC_POS) + +/** + * @brief Utility macro to initialize pinmux field in #pinctrl_pin_t. + * @param node_id Node identifier. + */ +#define Z_PINCTRL_CAT1_PINMUX_INIT(node_id) DT_PROP(node_id, pinmux) + +/** + * @brief Utility macro to initialize pincfg field in #pinctrl_pin_t. + * @param node_id Node identifier. + */ +#define Z_PINCTRL_CAT1_PINCFG_INIT(node_id) ( \ + (DT_PROP(node_id, bias_pull_up) << SOC_GPIO_PULLUP_POS) | \ + (DT_PROP(node_id, bias_pull_down) << SOC_GPIO_PULLDOWN_POS) | \ + (DT_PROP(node_id, drive_open_drain) << SOC_GPIO_OPENDRAIN_POS) | \ + (DT_PROP(node_id, drive_open_source) << SOC_GPIO_OPENSOURCE_POS) | \ + (DT_PROP(node_id, drive_push_pull) << SOC_GPIO_PUSHPULL_POS) | \ + (DT_PROP(node_id, input_enable) << SOC_GPIO_INPUTENABLE_POS) | \ + (DT_PROP(node_id, bias_high_impedance) << SOC_GPIO_HIGHZ_POS)) + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param state_prop State property name. + * @param idx State property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \ + { .pinmux = Z_PINCTRL_CAT1_PINMUX_INIT( \ + DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .pincfg = Z_PINCTRL_CAT1_PINCFG_INIT( \ + DT_PROP_BY_IDX(node_id, state_prop, idx)) }, + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) } + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_INFINEON_CAT1_COMMON_PINCTRL_SOC_H_ */ diff --git a/soc/infineon/cat1b/cyw20829/CMakeLists.txt b/soc/infineon/cat1b/cyw20829/CMakeLists.txt new file mode 100644 index 00000000000000..1605a4aaea4e3a --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(soc.c) +zephyr_sources(app_header.c) +zephyr_include_directories(.) + +zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 CY_USING_HAL) +zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B COMPONENT_CAT1B) +zephyr_compile_definitions(COMPONENT_CM33) + +# Use custom linker script +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/soc/infineon/cat1b/cyw20829/linker.ld CACHE INTERNAL "") diff --git a/soc/infineon/cat1b/cyw20829/Kconfig b/soc/infineon/cat1b/cyw20829/Kconfig new file mode 100644 index 00000000000000..f00be4ba1b811c --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon CAT1B devices + +# Series definitions +config SOC_SERIES_CYW20829 + select ARM + select CPU_HAS_ARM_MPU + select CPU_CORTEX_M33 + select CPU_HAS_FPU + select DYNAMIC_INTERRUPTS diff --git a/soc/infineon/cat1b/cyw20829/Kconfig.defconfig b/soc/infineon/cat1b/cyw20829/Kconfig.defconfig new file mode 100644 index 00000000000000..2096df8420f8ed --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/Kconfig.defconfig @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon CYW20829 based MCU default configuration + +if SOC_DIE_CYW20829 + +config NUM_IRQS + default 70 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 48000000 + +# add additional die specific params + +endif # SOC_DIE_CYW20829 diff --git a/soc/infineon/cat1b/cyw20829/Kconfig.soc b/soc/infineon/cat1b/cyw20829/Kconfig.soc new file mode 100644 index 00000000000000..7737a292321456 --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/Kconfig.soc @@ -0,0 +1,79 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Infineon CYW20829 series MCUs + +# SOC series +config SOC_SERIES_CYW20829 + bool + +config SOC_SERIES + default "cyw20829" if SOC_SERIES_CYW20829 + +# SOC die +config SOC_DIE_CYW20829 + bool + select SOC_FAMILY_INFINEON_CAT1B + +# SOC packages +config SOC_PACKAGE_CYW20829_56_QFN + bool + +config SOC_PACKAGE_CYW20829_40_QFN + bool + +config SOC_PACKAGE_CYW20829_77_BGA + bool + +# MPN +config SOC_CYW20829A0LKML + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_56_QFN + select SOC_SERIES_CYW20829 + +config SOC_CYW20829A0KML + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_40_QFN + select SOC_SERIES_CYW20829 + +config SOC_CYW89829A0KML + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_40_QFN + select SOC_SERIES_CYW20829 + +config SOC_CYW20829B0LKML + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_56_QFN + select SOC_SERIES_CYW20829 + +config SOC_CYW20829B0KML + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_40_QFN + select SOC_SERIES_CYW20829 + +config SOC_CYW89829B0KML + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_40_QFN + select SOC_SERIES_CYW20829 + +config SOC_CYW89829B01MKSBG + bool + select SOC_DIE_CYW20829 + select SOC_PACKAGE_CYW20829_77_BGA + select SOC_SERIES_CYW20829 + +config SOC + default "cyw20829a0lkml" if SOC_CYW20829A0LKML + default "cyw20829a0kml" if SOC_CYW20829A0KML + default "cyw89829a0kml" if SOC_CYW89829A0KML + default "cyw20829b0lkml" if SOC_CYW20829B0LKML + default "cyw20829b0kml" if SOC_CYW20829B0KML + default "cyw89829b0kml" if SOC_CYW89829B0KML + default "cyw89829b01mksbg" if SOC_CYW89829B01MKSBG diff --git a/soc/infineon/cat1b/cyw20829/app_header.c b/soc/infineon/cat1b/cyw20829/app_header.c new file mode 100644 index 00000000000000..9d64178b1e23f7 --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/app_header.c @@ -0,0 +1,45 @@ +/* Copyright 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +struct toc2_data { + uint32_t toc2_size; + uint32_t l1_app_descr_addr; + uint32_t service_app_descr_addr; + uint32_t debug_cert_addr; +} __packed; + +struct l1_desc { + uint32_t l1_app_descr_size; + uint32_t boot_strap_addr; + uint32_t boot_strap_dst_addr; + uint32_t boot_strap_size; + uint32_t reserved[3]; +} __packed; + +struct l1_usr_app_hdr { + uint8_t reserved[32]; +} __packed; + +struct app_header { + struct toc2_data toc2_data; + struct l1_desc l1_desc; + uint8_t padding[4]; + struct l1_usr_app_hdr l1_usr_app_hdr; +} __packed; + +const struct app_header app_header Z_GENERIC_SECTION(.app_header) = { + .toc2_data = {.toc2_size = sizeof(struct toc2_data), + .l1_app_descr_addr = offsetof(struct app_header, l1_desc)}, + .l1_desc = {.l1_app_descr_size = sizeof(struct l1_desc), + .boot_strap_addr = DT_REG_ADDR(DT_NODELABEL(bootstrap_region)) - + DT_REG_ADDR(DT_NODELABEL(flash0)), + .boot_strap_dst_addr = DT_REG_ADDR(DT_NODELABEL(sram_bootstrap)), + .boot_strap_size = DT_REG_SIZE(DT_NODELABEL(sram_bootstrap))}, +}; diff --git a/soc/infineon/cat1b/cyw20829/bootstrap.ld b/soc/infineon/cat1b/cyw20829/bootstrap.ld new file mode 100644 index 00000000000000..da007baa74912c --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/bootstrap.ld @@ -0,0 +1,114 @@ +/* Copyright 2024 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +SECTIONS +{ + .app_header : + { + KEEP(*(.app_header)) + } > APP_HEADER_FLASH + + /* Cortex-M33 bootstrap code area */ + .bootstrapText : + { + . = ALIGN(4); + __bootstrapText_begin = .; + + /* Located in generated directory. This file is populated by calling + * zephyr_linker_sources(ROM_START ...). This typically contains the vector + * table and debug information. + */ + #include + + /* startup code */ + *(.text._reset_section) + + *startup_cat1b_cm33.*(.text*) + *system_cyw20829.*(.text*) + + /* drivers */ + *cy_device.*(.text*) + *cy_btss.*(.text*) + *cy_sysclk_v2.*(.text*) + *cy_syspm_v2.*(.text*) + *cy_sysint_v2.*(.text*) + *cy_syslib*.*(.text*) + *ppu_v1.*(.text*) + *cy_mpc.*(.text*) + *cy_syspm_ppu.*(.text*) + + *memcpy*.* (.text*) /* add memcpy from the NewLib library here*/ + *memset*.* (.text*) /* add memcpy from the NewLib library here*/ + *memmove*.* (.text*) /* add memcpy from the NewLib library here*/ + *s_fabs.* (.text*) + + KEEP(*(.cy_l1func*)) + + . = ALIGN(4); + __bootstrapText_end = .; + } > BOOTSTRAP_RAM AT>BOOTSTRAP_FLASH + + .bootstrapzero.table : + { + . = ALIGN(4); + __bootstrapzero_table_start__ = .; + LONG (__bootstrap_bss_start__) + LONG ((__bootstrap_bss_end__ - __bootstrap_bss_start__)/4) + . = ALIGN(4); + __bootstrapzero_table_end__ = .; + } > BOOTSTRAP_RAM AT>BOOTSTRAP_FLASH + + .bootstrapData : + { + __bootstrapData_start__ = .; + . = ALIGN(4); + + /* startup code */ + *startup_cat1b_cm33.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *system_cyw20829.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + + /* drivers */ + *cy_device.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_btss.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_sysclk_v2.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_syspm_v2.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_sysint_v2.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_syslib.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *ppu_v1.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_mpc.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + *cy_pd_ppu.*(.data* .rodata .rodata.* .constdata .constdata.* .conststring .conststring.*) + + KEEP(*(.cy_l1data*)) + + . = ALIGN(4); + __bootstrapData_end__ = .; + } > BOOTSTRAP_RAM AT>BOOTSTRAP_FLASH + + .bootstrapBss (NOLOAD): + { + . = ALIGN(4); + __bootstrap_bss_start__ = .; + + /* startup code */ + *startup_cat1b_cm33.*(.bss* COMMON) + *system_cyw20829.*(.bss* COMMON) + + /* drivers */ + *cy_device.*(.bss* COMMON) + *cy_btss.*(.bss* COMMON) + *cy_sysclk_v2.*(.bss* COMMON) + *cy_syspm_v2.*(.bss* COMMON) + *cy_sysint_v2.*(.bss* COMMON) + *cy_syslib.*(.bss* COMMON) + *ppu_v1.*(.bss* COMMON) + *cy_mpc.*(.bss* COMMON) + *cy_pd_ppu.*(.bss* COMMON) + KEEP(*(.cy_l1bss*)) + + . = ALIGN(4); + __bootstrap_bss_end__ = .; + } > BOOTSTRAP_RAM +} diff --git a/soc/infineon/cat1b/cyw20829/linker.ld b/soc/infineon/cat1b/cyw20829/linker.ld new file mode 100644 index 00000000000000..11b36b51170541 --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/linker.ld @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the Cortex-M platforms. + */ + +#include +#include + +#include +#include +#include + +/* physical address of RAM */ +#ifdef CONFIG_XIP +#define ROMABLE_REGION FLASH +#else +#define ROMABLE_REGION RAM +#endif +#define RAMABLE_REGION RAM + +#if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) +#define ROM_ADDR RAM_ADDR +#else +#define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) +#endif + +#if defined(CONFIG_ROM_END_OFFSET) +#define ROM_END_OFFSET CONFIG_ROM_END_OFFSET +#else +#define ROM_END_OFFSET 0 +#endif + +#if CONFIG_FLASH_LOAD_SIZE > 0 +#define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET) +#else +#define ROM_SIZE (CONFIG_FLASH_SIZE * 1024 - CONFIG_FLASH_LOAD_OFFSET - ROM_END_OFFSET) +#endif + +#if defined(CONFIG_XIP) +#if defined(CONFIG_IS_BOOTLOADER) +#define RAM_SIZE (CONFIG_BOOTLOADER_SRAM_SIZE * 1K) +#define RAM_ADDR (CONFIG_SRAM_BASE_ADDRESS + \ + (CONFIG_SRAM_SIZE * 1K - RAM_SIZE)) +#else +#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS +#endif +#else +#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K - CONFIG_BOOTLOADER_SRAM_SIZE * 1K) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS +#endif + +#if defined(CONFIG_CUSTOM_SECTION_ALIGN) +_region_min_align = CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE; +#else +/* Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE + * to make linker section alignment comply with MPU granularity. + */ +#if defined(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE) +_region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE; +#else +/* If building without MPU support, use default 4-byte alignment. */ +_region_min_align = 4; +#endif +#endif + +#if !defined(CONFIG_CUSTOM_SECTION_ALIGN) && defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) +#define MPU_ALIGN(region_size) \ + . = ALIGN(_region_min_align); \ + . = ALIGN( 1 << LOG2CEIL(region_size)) +#else +#define MPU_ALIGN(region_size) \ + . = ALIGN(_region_min_align) +#endif + +#include + +MEMORY + { + FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE + RAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE +#if defined(CONFIG_LINKER_DEVNULL_MEMORY) + DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE +#endif + LINKER_DT_REGIONS() + /* Used by and documented in include/linker/intlist.ld */ + IDT_LIST (wx) : ORIGIN = 0xFFFF7FFF, LENGTH = 32K + } + +ENTRY(CONFIG_KERNEL_ENTRY) + +#include + +SECTIONS + { + +#include + + /* + * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', + * before text section. + */ + /DISCARD/ : + { + *(.plt) + } + + /DISCARD/ : + { + *(.iplt) + } + + GROUP_START(ROMABLE_REGION) + + __rom_region_start = ROM_ADDR; + + SECTION_PROLOGUE(rom_start,,) + { + + + } GROUP_LINK_IN(ROMABLE_REGION) + +#ifdef CONFIG_CODE_DATA_RELOCATION + +#include + +#endif /* CONFIG_CODE_DATA_RELOCATION */ + + SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) + { + __text_region_start = .; + +#include + + *(.text) + *(".text.*") + *(".TEXT.*") + *(.gnu.linkonce.t.*) + + /* + * These are here according to 'arm-zephyr-elf-ld --verbose', + * after .gnu.linkonce.t.* + */ + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + . = ALIGN(4); + + } GROUP_LINK_IN(ROMABLE_REGION) + + __text_region_end = .; + +#if defined (CONFIG_CPP) + SECTION_PROLOGUE(.ARM.extab,,) + { + /* + * .ARM.extab section containing exception unwinding information. + */ + *(.ARM.extab* .gnu.linkonce.armextab.*) + } GROUP_LINK_IN(ROMABLE_REGION) +#endif + + SECTION_PROLOGUE(.ARM.exidx,,) + { + /* + * This section, related to stack and exception unwinding, is placed + * explicitly to prevent it from being shared between multiple regions. + * It must be defined for gcc to support 64-bit math and avoid + * section overlap. + */ + __exidx_start = .; +#if defined (__GCC_LINKER_CMD__) + *(.ARM.exidx* gnu.linkonce.armexidx.*) +#endif + __exidx_end = .; + } GROUP_LINK_IN(ROMABLE_REGION) + + __rodata_region_start = .; + +#include +#include + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + *(.rodata) + *(".rodata.*") + *(.gnu.linkonce.r.*) + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#include + + /* + * For XIP images, in order to avoid the situation when __data_rom_start + * is 32-bit aligned, but the actual data is placed right after rodata + * section, which may not end exactly at 32-bit border, pad rodata + * section, so __data_rom_start points at data and it is 32-bit aligned. + * + * On non-XIP images this may enlarge image size up to 3 bytes. This + * generally is not an issue, since modern ROM and FLASH memory is + * usually 4k aligned. + */ + . = ALIGN(4); + } GROUP_LINK_IN(ROMABLE_REGION) + +#include + +#if defined(CONFIG_BUILD_ALIGN_LMA) + /* + * Include a padding section here to make sure that the LMA address + * of the sections in the RAMABLE_REGION are aligned with those + * section's VMA alignment requirements. + */ + SECTION_PROLOGUE(padding_section,,) + { + __rodata_region_end = .; + MPU_ALIGN(__rodata_region_end - ADDR(rom_start)); + } GROUP_LINK_IN(ROMABLE_REGION) +#else + __rodata_region_end = .; + MPU_ALIGN(__rodata_region_end - ADDR(rom_start)); +#endif + __rom_region_end = __rom_region_start + . - ADDR(rom_start); + + GROUP_END(ROMABLE_REGION) + + /* + * These are here according to 'arm-zephyr-elf-ld --verbose', + * before data section. + */ + /DISCARD/ : { + *(.got.plt) + *(.igot.plt) + *(.got) + *(.igot) + } + + GROUP_START(RAMABLE_REGION) + + . = RAM_ADDR; + /* Align the start of image RAM with the + * minimum granularity required by MPU. + */ + . = ALIGN(_region_min_align); + _image_ram_start = .; + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#if defined(CONFIG_USERSPACE) +#define APP_SHARED_ALIGN . = ALIGN(_region_min_align); +#define SMEM_PARTITION_ALIGN MPU_ALIGN + +#include + + _app_smem_size = _app_smem_end - _app_smem_start; + _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); + + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + /* + * For performance, BSS section is assumed to be 4 byte aligned and + * a multiple of 4 bytes + */ + . = ALIGN(4); + __bss_start = .; + __kernel_ram_start = .; + + *(.bss) + *(".bss.*") + *(COMMON) + *(".kernel_bss.*") + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + __bss_end = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + +#include + +#endif /* CONFIG_USERSPACE */ + + GROUP_START(DATA_REGION) + + SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) + { + __data_region_start = .; + __data_start = .; + *(.data) + *(".data.*") + *(".kernel.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + __data_end = .; + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + __data_size = __data_end - __data_start; + __data_load_start = LOADADDR(_DATA_SECTION_NAME); + + __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); + +#include +#include + +#include + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + + __data_region_end = .; + +#ifndef CONFIG_USERSPACE + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + /* + * For performance, BSS section is assumed to be 4 byte aligned and + * a multiple of 4 bytes + */ + . = ALIGN(4); + __bss_start = .; + __kernel_ram_start = .; + + *(.bss) + *(".bss.*") + *(COMMON) + *(".kernel_bss.*") + +#ifdef CONFIG_CODE_DATA_RELOCATION +#include +#endif + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + __bss_end = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + + SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) + { + /* + * This section is used for non-initialized objects that + * will not be cleared during the boot process. + */ + *(.noinit) + *(".noinit.*") + *(".kernel_noinit.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + + } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) +#endif /* CONFIG_USERSPACE */ + + /* Define linker symbols */ + + __kernel_ram_end = RAM_ADDR + RAM_SIZE; + __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +GROUP_START(ITCM) + + SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(4)) + { + __itcm_start = .; + *(.itcm) + *(".itcm.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. */ +#include + + __itcm_end = .; + } GROUP_LINK_IN(ITCM AT> ROMABLE_REGION) + + __itcm_size = __itcm_end - __itcm_start; + __itcm_load_start = LOADADDR(_ITCM_SECTION_NAME); + +GROUP_END(ITCM) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +GROUP_START(DTCM) + + SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(4)) + { + __dtcm_start = .; + __dtcm_bss_start = .; + *(.dtcm_bss) + *(".dtcm_bss.*") + __dtcm_bss_end = .; + } GROUP_LINK_IN(DTCM) + + SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(4)) + { + __dtcm_noinit_start = .; + *(.dtcm_noinit) + *(".dtcm_noinit.*") + __dtcm_noinit_end = .; + } GROUP_LINK_IN(DTCM) + + SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(4)) + { + __dtcm_data_start = .; + *(.dtcm_data) + *(".dtcm_data.*") + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. */ +#include + + __dtcm_data_end = .; + } GROUP_LINK_IN(DTCM AT> ROMABLE_REGION) + + __dtcm_end = .; + + __dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME); + +GROUP_END(DTCM) +#endif + +/* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ +#include + +#include + + GROUP_END(RAMABLE_REGION) + +#include + + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.ARM.attributes, 0,) + { + KEEP(*(.ARM.attributes)) + KEEP(*(.gnu.attributes)) + } + + /* Sections generated from 'zephyr,memory-region' nodes */ + LINKER_DT_SECTIONS() + +/* Must be last in romable region */ +SECTION_PROLOGUE(.last_section,,) +{ +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif +} GROUP_LINK_IN(ROMABLE_REGION) + +/* To provide the image size as a const expression, + * calculate this value here. */ +_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start; + + } diff --git a/soc/infineon/cat1b/cyw20829/soc.c b/soc/infineon/cat1b/cyw20829/soc.c new file mode 100644 index 00000000000000..3199a1ac8945b4 --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/soc.c @@ -0,0 +1,61 @@ +/* Copyright 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Infineon CYW920829 soc. + */ + +#include +#include +#include +#include +#include +#include "cy_pdl.h" + +cy_en_sysint_status_t Cy_SysInt_Init(const cy_stc_sysint_t *config, cy_israddress userIsr) +{ + CY_ASSERT_L3(CY_SYSINT_IS_PRIORITY_VALID(config->intrPriority)); + cy_en_sysint_status_t status = CY_SYSINT_SUCCESS; + + /* The interrupt vector will be relocated only if the vector table was + * moved to SRAM (CONFIG_DYNAMIC_INTERRUPTS and CONFIG_GEN_ISR_TABLES + * must be enabled). Otherwise it is ignored. + */ + +#if defined(CONFIG_DYNAMIC_INTERRUPTS) && defined(CONFIG_GEN_ISR_TABLES) + if (config != NULL) { + uint32_t priority; + + /* NOTE: + * PendSV IRQ (which is used in Cortex-M variants to implement thread + * context-switching) is assigned the lowest IRQ priority level. + * If priority is same as PendSV, we will catch assertion in + * z_arm_irq_priority_set function. To avoid this, change priority + * to IRQ_PRIO_LOWEST, if it > IRQ_PRIO_LOWEST. Macro IRQ_PRIO_LOWEST + * takes in to account PendSV specific. + */ + priority = (config->intrPriority > IRQ_PRIO_LOWEST) ? + IRQ_PRIO_LOWEST : config->intrPriority; + + /* Configure a dynamic interrupt */ + (void) irq_connect_dynamic(config->intrSrc, priority, + (void *) userIsr, NULL, 0); + } else { + status = CY_SYSINT_BAD_PARAM; + } +#endif /* defined(CONFIG_DYNAMIC_INTERRUPTS) && defined(CONFIG_GEN_ISR_TABLES) */ + + return(status); +} + +static int init_cycfg_platform_wrapper(void) +{ + /* Initializes the system */ + SystemInit(); + return 0; +} + +SYS_INIT(init_cycfg_platform_wrapper, PRE_KERNEL_1, 0); diff --git a/soc/infineon/cat1b/cyw20829/soc.h b/soc/infineon/cat1b/cyw20829/soc.h new file mode 100644 index 00000000000000..e13fc0739e62e1 --- /dev/null +++ b/soc/infineon/cat1b/cyw20829/soc.h @@ -0,0 +1,18 @@ +/* Copyright 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Infineon CYW20829 soc. + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +#ifndef _ASMLANGUAGE +#include +#endif /* !_ASMLANGUAGE */ + +#endif /* _SOC__H_ */ diff --git a/soc/infineon/cat1b/soc.yml b/soc/infineon/cat1b/soc.yml new file mode 100644 index 00000000000000..af1e937afee031 --- /dev/null +++ b/soc/infineon/cat1b/soc.yml @@ -0,0 +1,12 @@ +family: +- name: cat1b + series: + - name: cyw20829 + socs: + - name: cyw20829a0lkml + - name: cyw20829a0kml + - name: cyw89829a0kml + - name: cyw20829b0lkml + - name: cyw20829b0kml + - name: cyw89829b0kml + - name: cyw89829b01mksbg From 026202c30056c7c34994efae1a625a9e14b647e8 Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1368/1389] version.h.in: Do not use @template@ @template@s will be replaced by empty strings and the comment in generated files will be broken. Replace them with just simple words. Signed-off-by: Yasushi SHOJI --- version.h.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.h.in b/version.h.in index bfb2eb3edb75cc..9d10a8f55d5676 100644 --- a/version.h.in +++ b/version.h.in @@ -1,8 +1,8 @@ #ifndef _@VERSION_TYPE@_VERSION_H_ #define _@VERSION_TYPE@_VERSION_H_ -/* @templates@ values come from cmake/version.cmake - * BUILD_VERSION related @template@ values will be 'git describe', +/* The template values come from cmake/version.cmake + * BUILD_VERSION related template values will be 'git describe', * alternatively user defined BUILD_VERSION. */ From e7eeacdf2cee2b3c4fdc7aaf897cb0459d35fa91 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1369/1389] drivers: bluetooth: da1469x: Fix deferred buffer allocation If rx buffer allocation has to be deferred to rx_thread, we need to stop isr reading from mailbox as otherwise rx_thread won't be able to process other buffers. Since CMAC2SYS irq is cleared before data is read from mailbox, in case rx buffer allocation was deferred we also need to trigger irq manually to make sure all pending data is processed. Signed-off-by: Andrzej Kaczmarek --- drivers/bluetooth/hci/hci_da1469x.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/hci/hci_da1469x.c b/drivers/bluetooth/hci/hci_da1469x.c index 8935244472a954..c97b83f3b35cfd 100644 --- a/drivers/bluetooth/hci/hci_da1469x.c +++ b/drivers/bluetooth/hci/hci_da1469x.c @@ -42,6 +42,7 @@ static struct { bool have_hdr; bool discardable; + bool deferred; uint8_t hdr_len; @@ -187,6 +188,21 @@ static struct net_buf *get_rx(k_timeout_t timeout) return NULL; } +static void rx_isr_start(void) +{ + if (rx.deferred) { + rx.deferred = false; + NVIC_SetPendingIRQ(CMAC2SYS_IRQn); + } + + irq_enable(CMAC2SYS_IRQn); +} + +static void rx_isr_stop(void) +{ + irq_disable(CMAC2SYS_IRQn); +} + static void rx_thread(void *p1, void *p2, void *p3) { struct net_buf *buf; @@ -217,11 +233,11 @@ static void rx_thread(void *p1, void *p2, void *p3) } /* Let the ISR continue receiving new packets */ - irq_enable(CMAC2SYS_IRQn); + rx_isr_start(); buf = net_buf_get(&rx.fifo, K_FOREVER); do { - irq_enable(CMAC2SYS_IRQn); + rx_isr_start(); LOG_DBG("Calling bt_recv(%p)", buf); bt_recv(buf); @@ -232,7 +248,8 @@ static void rx_thread(void *p1, void *p2, void *p3) */ k_yield(); - irq_disable(CMAC2SYS_IRQn); + rx_isr_stop(); + buf = net_buf_get(&rx.fifo, K_NO_WAIT); } while (buf); } @@ -270,7 +287,7 @@ static inline void read_payload(void) } LOG_WRN("Failed to allocate, deferring to rx_thread"); - irq_disable(CMAC2SYS_IRQn); + rx.deferred = true; return; } @@ -372,7 +389,7 @@ static inline void process_rx(void) /* Called by HAL when data in CMAC mailbox is available to read */ void cmac_read_req(void) { - while (cmac_mbox_has_data()) { + while (!rx.deferred && cmac_mbox_has_data()) { process_rx(); } } From 7c25ef41dfaa536d46c29a58ffd5f070ba45f640 Mon Sep 17 00:00:00 2001 From: Yassine EL -AISSAOUI Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1370/1389] dts: binding: add yaml file for nxp HCI - used to define hci info Signed-off-by: Yassine EL -AISSAOUI --- dts/bindings/arm/nxp,hci-ble.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 dts/bindings/arm/nxp,hci-ble.yaml diff --git a/dts/bindings/arm/nxp,hci-ble.yaml b/dts/bindings/arm/nxp,hci-ble.yaml new file mode 100644 index 00000000000000..7620ec8eb6988b --- /dev/null +++ b/dts/bindings/arm/nxp,hci-ble.yaml @@ -0,0 +1,12 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP BLE HCI information + +compatible: "nxp,hci-ble" + +include: base.yaml + +properties: + interrupts: + required: true From 8c7d6564a444ed941b765351c715f055681c98fc Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1371/1389] drivers: hci: Add NXP HCI driver Add HCI driver generic to NXP platforms. Update west.yml to have ble support for rw61x Signed-off-by: Axel Le Bourhis Signed-off-by: Yassine El Aissaoui --- drivers/bluetooth/hci/CMakeLists.txt | 1 + drivers/bluetooth/hci/Kconfig | 16 +- drivers/bluetooth/hci/Kconfig.nxp | 24 ++ drivers/bluetooth/hci/hci_nxp.c | 417 +++++++++++++++++++++++++++ west.yml | 2 +- 5 files changed, 452 insertions(+), 8 deletions(-) create mode 100644 drivers/bluetooth/hci/Kconfig.nxp create mode 100644 drivers/bluetooth/hci/hci_nxp.c diff --git a/drivers/bluetooth/hci/CMakeLists.txt b/drivers/bluetooth/hci/CMakeLists.txt index ab1df047ce11dc..ca3f62f9e59bd1 100644 --- a/drivers/bluetooth/hci/CMakeLists.txt +++ b/drivers/bluetooth/hci/CMakeLists.txt @@ -34,3 +34,4 @@ zephyr_library_sources_ifdef(CONFIG_BT_PSOC6_BLESS hci_psoc6_bless.c) zephyr_library_sources_ifdef(CONFIG_SOC_NRF5340_CPUAPP nrf53_support.c) zephyr_library_sources_ifdef(CONFIG_BT_AMBIQ_HCI hci_ambiq.c apollox_blue.c) zephyr_library_sources_ifdef(CONFIG_BT_DA1469X hci_da1469x.c) +zephyr_library_sources_ifdef(CONFIG_BT_NXP hci_nxp.c) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index 1b4bc9fdb25d0c..7a2f79fd85a86d 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -115,6 +115,11 @@ config BT_DA1469X Bluetooth HCI driver for communication with CMAC core on DA1469x MCU. +config BT_NXP + bool "NXP HCI driver" + help + NXP HCI bluetooth interface + config BT_NO_DRIVER bool "No default HCI driver" select BT_HAS_HCI_VS @@ -149,16 +154,12 @@ config BT_BLUENRG_ACI endif # BT_SPI -if BT_AMBIQ_HCI - config BT_HCI_INIT_PRIORITY int "BT HCI init priority" - default 75 + default 75 if BT_AMBIQ_HCI + default KERNEL_INIT_PRIORITY_DEVICE help - The priority of BT HCI driver initialization needs to be lower than - the SPI, GPIO, clock controller drivers initialization priorities. - -endif # BT_AMBIQ_HCI + The priority of BT HCI driver initialization. config BT_STM32_IPM_RX_STACK_SIZE int "STM32 IPM stack size for RX thread" @@ -178,6 +179,7 @@ menuconfig BT_AIROC IEEE 802.11a/b/g/n/ac/ax Wi-Fi and Bluetooth® 5.2 in a single-chip solution to enable small-form-factor IoT designs. source "drivers/bluetooth/hci/Kconfig.infineon" +source "drivers/bluetooth/hci/Kconfig.nxp" config BT_DRIVER_QUIRK_NO_AUTO_DLE bool "Host auto-initiated Data Length Update quirk" diff --git a/drivers/bluetooth/hci/Kconfig.nxp b/drivers/bluetooth/hci/Kconfig.nxp new file mode 100644 index 00000000000000..a5eb8648c8ad5f --- /dev/null +++ b/drivers/bluetooth/hci/Kconfig.nxp @@ -0,0 +1,24 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +config HCI_NXP_ENABLE_AUTO_SLEEP + bool "BLE Controller auto sleep mode" + help + If enabled, the Controller auto sleep mode will be configured and enabled during HCI init. + Auto sleep mode means the Controller will handle its low power state automatically. + Enabling this feature will allow to save power at the cost of some latency when sending a HCI + message to the Controller as the Host will need to wake it up. + +config HCI_NXP_SET_CAL_DATA + bool "BLE Controller calibration data" + help + If enabled, the Host will send calibration data to the BLE Controller during HCI init. + +config HCI_NXP_SET_CAL_DATA_ANNEX100 + bool "BLE Controller calibration data annex 100" + help + If enabled, the Host will send calibration data annex 100 to the BLE Controller during HCI + init. diff --git a/drivers/bluetooth/hci/hci_nxp.c b/drivers/bluetooth/hci/hci_nxp.c new file mode 100644 index 00000000000000..78016a794b5fd8 --- /dev/null +++ b/drivers/bluetooth/hci/hci_nxp.c @@ -0,0 +1,417 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* -------------------------------------------------------------------------- */ +/* Includes */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* -------------------------------------------------------------------------- */ +/* Definitions */ +/* -------------------------------------------------------------------------- */ + +#define DT_DRV_COMPAT nxp_hci_ble + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +LOG_MODULE_REGISTER(bt_driver); + +#define HCI_IRQ_N DT_INST_IRQ_BY_NAME(0, hci_int, irq) +#define HCI_IRQ_P DT_INST_IRQ_BY_NAME(0, hci_int, priority) +#define HCI_WAKEUP_IRQ_N DT_INST_IRQ_BY_NAME(0, wakeup_int, irq) +#define HCI_WAKEUP_IRQ_P DT_INST_IRQ_BY_NAME(0, wakeup_int, priority) + +/* Vendor specific commands */ +#define HCI_CMD_STORE_BT_CAL_DATA_OCF 0x61U +#define HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH 32U +#define HCI_CMD_STORE_BT_CAL_DATA_ANNEX100_OCF 0xFFU +#define HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH 16U +#define HCI_CMD_SET_BT_SLEEP_MODE_OCF 0x23U +#define HCI_CMD_SET_BT_SLEEP_MODE_PARAM_LENGTH 3U +#define HCI_CMD_BT_HOST_SLEEP_CONFIG_OCF 0x59U +#define HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH 2U + +/* -------------------------------------------------------------------------- */ +/* Public prototypes */ +/* -------------------------------------------------------------------------- */ + +extern int32_t ble_hci_handler(void); +extern int32_t ble_wakeup_done_handler(void); + +/* -------------------------------------------------------------------------- */ +/* Private functions */ +/* -------------------------------------------------------------------------- */ + +#if CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP || CONFIG_HCI_NXP_SET_CAL_DATA +static int nxp_bt_send_vs_command(uint16_t opcode, const uint8_t *params, uint8_t params_len) +{ +#if CONFIG_BT_HCI_HOST + struct net_buf *buf; + + /* Allocate buffer for the hci command */ + buf = bt_hci_cmd_create(opcode, params_len); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return -ENOMEM; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, params, params_len); + + /* Send the command */ + return bt_hci_cmd_send_sync(opcode, buf, NULL); +#else + return 0; +#endif +} +#endif /* CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP || CONFIG_HCI_NXP_SET_CAL_DATA */ + +#if CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP +static int nxp_bt_enable_controller_autosleep(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_SET_BT_SLEEP_MODE_OCF); + const uint8_t params[HCI_CMD_SET_BT_SLEEP_MODE_PARAM_LENGTH] = { + 0x02U, /* Auto sleep enable */ + 0x00U, /* Idle timeout LSB */ + 0x00U /* Idle timeout MSB */ + }; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, params, HCI_CMD_SET_BT_SLEEP_MODE_PARAM_LENGTH); +} + +static int nxp_bt_set_host_sleep_config(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_BT_HOST_SLEEP_CONFIG_OCF); + const uint8_t params[HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH] = { + 0xFFU, /* BT_HIU_WAKEUP_INBAND */ + 0xFFU, /* BT_HIU_WAKE_GAP_WAIT_FOR_IRQ */ + }; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, params, HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH); +} +#endif /* CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP */ + +#if CONFIG_HCI_NXP_SET_CAL_DATA +static int bt_nxp_set_calibration_data(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_STORE_BT_CAL_DATA_OCF); + extern const uint8_t hci_cal_data_params[HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH]; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, hci_cal_data_params, + HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH); +} + +#if CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 +static int bt_nxp_set_calibration_data_annex100(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_STORE_BT_CAL_DATA_ANNEX100_OCF); + + extern const uint8_t + hci_cal_data_annex100_params[HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH]; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, hci_cal_data_annex100_params, + HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH); +} +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 */ + +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA */ + +static bool is_hci_event_discardable(const uint8_t *evt_data) +{ + bool ret = false; + uint8_t evt_type = evt_data[0]; + + switch (evt_type) { + case BT_HCI_EVT_LE_META_EVENT: { + uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)]; + + switch (subevt_type) { + case BT_HCI_EVT_LE_ADVERTISING_REPORT: + case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: + ret = true; + break; + default: + break; + } + } break; + + default: + break; + } + + return ret; +} + +static struct net_buf *bt_evt_recv(uint8_t *data, size_t len) +{ + struct net_buf *buf; + uint8_t payload_len; + uint8_t evt_hdr; + bool discardable_evt; + size_t space_in_buffer; + + payload_len = data[1]; + evt_hdr = data[0]; + discardable_evt = false; + + /* Data Check */ + if (len < BT_HCI_EVT_HDR_SIZE) { + LOG_ERR("Event header is missing"); + return NULL; + } + if ((len - BT_HCI_EVT_HDR_SIZE) != payload_len) { + LOG_ERR("Event payload length is incorrect"); + return NULL; + } + + discardable_evt = is_hci_event_discardable(data); + + /* Allocate a buffer for the HCI Event */ + buf = bt_buf_get_evt(evt_hdr, discardable_evt, (discardable_evt ? K_NO_WAIT : K_FOREVER)); + + if (buf) { + space_in_buffer = net_buf_tailroom(buf); + if (len > space_in_buffer) { + LOG_ERR("Buffer size error,INFO : evt_hdr=%d, data_len=%zu, buf_size=%zu", + evt_hdr, len, space_in_buffer); + net_buf_unref(buf); + return NULL; + } + /* Copy the data to the buffer */ + net_buf_add_mem(buf, data, len); + } else { + if (discardable_evt) { + LOG_DBG("Discardable buffer pool full, ignoring event"); + } else { + LOG_ERR("No available event buffers!"); + } + return NULL; + } + + return buf; +} + +static struct net_buf *bt_acl_recv(uint8_t *data, size_t len) +{ + struct net_buf *buf; + uint16_t payload_len; + + /* Data Check */ + if (len < BT_HCI_ACL_HDR_SIZE) { + LOG_ERR("ACL header is missing"); + return NULL; + } + memcpy((void *)&payload_len, (void *)&data[2], 2); + if ((len - BT_HCI_ACL_HDR_SIZE) != payload_len) { + LOG_ERR("ACL payload length is incorrect"); + return NULL; + } + /* Allocate a buffer for the received data */ + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); + + if (buf) { + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Buffer doesn't have enough space to store the data"); + net_buf_unref(buf); + return NULL; + } + /* Copy the data to the buffer */ + net_buf_add_mem(buf, data, len); + } else { + LOG_ERR("ACL buffer is empty"); + return NULL; + } + + return buf; +} + +static void hci_rx_cb(uint8_t packetType, uint8_t *data, uint16_t len) +{ + struct net_buf *buf; + + switch (packetType) { + case BT_HCI_H4_EVT: + /* create a buffer and fill it out with event data */ + buf = bt_evt_recv(data, len); + break; + case BT_HCI_H4_ACL: + /* create a buffer and fill it out with ACL data */ + buf = bt_acl_recv(data, len); + break; + default: + buf = NULL; + LOG_ERR("Unknown HCI type"); + } + + if (buf) { + /* Provide the buffer to the host */ + bt_recv(buf); + } +} + +static int bt_nxp_send(struct net_buf *buf) +{ + uint8_t packetType; + + switch (bt_buf_get_type(buf)) { + case BT_BUF_CMD: + packetType = BT_HCI_H4_CMD; + break; + case BT_BUF_ACL_OUT: + packetType = BT_HCI_H4_ACL; + break; + default: + LOG_ERR("Not supported type"); + return -1; + } + + net_buf_push_u8(buf, packetType); + PLATFORM_SendHciMessage(buf->data, buf->len); + + net_buf_unref(buf); + + return 0; +} + +static int bt_nxp_open(void) +{ + int ret = 0; + + do { + ret = PLATFORM_InitBle(); + if (ret < 0) { + LOG_ERR("Failed to initialize BLE controller"); + break; + } + + ret = PLATFORM_SetHciRxCallback(hci_rx_cb); + if (ret < 0) { + LOG_ERR("BLE HCI RX callback registration failed"); + break; + } + + ret = PLATFORM_StartHci(); + if (ret < 0) { + LOG_ERR("HCI open failed"); + break; + } + +#if CONFIG_HCI_NXP_SET_CAL_DATA + ret = bt_nxp_set_calibration_data(); + if (ret < 0) { + LOG_ERR("Failed to set calibration data"); + break; + } +#if CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 + /* After send annex55 to CPU2, CPU2 need reset, + * a delay of at least 20ms is required to continue sending annex100 + */ + k_sleep(Z_TIMEOUT_MS(20)); + + ret = bt_nxp_set_calibration_data_annex100(); + if (ret < 0) { + LOG_ERR("Failed to set calibration data"); + break; + } +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 */ +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA */ + +#if CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP + ret = nxp_bt_set_host_sleep_config(); + if (ret < 0) { + LOG_ERR("Failed to set host sleep config"); + break; + } + + ret = nxp_bt_enable_controller_autosleep(); + if (ret < 0) { + LOG_ERR("Failed to configure controller autosleep"); + break; + } +#endif + } while (false); + + return ret; +} + +static int bt_nxp_close(void) +{ + int ret = 0; + /* Reset the Controller */ +#if CONFIG_BT_HCI_HOST + ret = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); + if (ret) { + LOG_ERR("Failed to reset BLE controller"); + } + k_sleep(K_SECONDS(1)); + + ret = PLATFORM_TerminateBle(); + if (ret < 0) { + LOG_ERR("Failed to shutdown BLE controller"); + } +#endif + return ret; +} + +static const struct bt_hci_driver drv = { + .name = "BT NXP", + .open = bt_nxp_open, + .close = bt_nxp_close, + .send = bt_nxp_send, + .bus = BT_HCI_DRIVER_BUS_IPM, +}; + +static int bt_nxp_init(void) +{ + int status; + int ret = 0; + + /* HCI Interrupt */ + IRQ_CONNECT(HCI_IRQ_N, HCI_IRQ_P, ble_hci_handler, 0, 0); + irq_enable(HCI_IRQ_N); + + /* Wake up done interrupt */ + IRQ_CONNECT(HCI_WAKEUP_IRQ_N, HCI_WAKEUP_IRQ_P, ble_wakeup_done_handler, 0, 0); + irq_enable(HCI_WAKEUP_IRQ_N); + +#if (DT_INST_PROP(0, wakeup_source)) && CONFIG_PM + EnableDeepSleepIRQ(HCI_IRQ_N); +#endif + + do { + status = PLATFORM_InitBle(); + if (status < 0) { + LOG_ERR("BLE Controller initialization failed"); + ret = status; + break; + } + + status = bt_hci_driver_register(&drv); + if (status < 0) { + LOG_ERR("HCI driver registration failed"); + ret = status; + break; + } + } while (0); + + return ret; +} + +SYS_INIT(bt_nxp_init, POST_KERNEL, CONFIG_BT_HCI_INIT_PRIORITY); diff --git a/west.yml b/west.yml index c6ff13bd6bf9f2..177d1715856e88 100644 --- a/west.yml +++ b/west.yml @@ -193,7 +193,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 57d844b03ea545aa702ae99d9777481709ba8aa4 + revision: 5e84f1d2173e3c5057725d76f9dad6bfabad0b5f path: modules/hal/nxp groups: - hal From 47cba02004e665eb35a0ec391ce1abee0a8fd760 Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1372/1389] modules: Add Kconfig to Kconfig.mcux for BLE support Added NXP_FW_LOADER for NXP platforms. Added NXP_RF_IMU for NXP platforms. Added MONOLITHIC Flags for NXP platforms. Signed-off-by: Axel Le Bourhis --- modules/Kconfig.mcux | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 0700438661e67e..5d30250079fc60 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -369,4 +369,16 @@ config HAS_MCUX_XBARA help Set if the XBARA module is present on the SoC. +config NXP_FW_LOADER + bool "Include firmware loader component" + help + The firmware loader is used to load firmwares to embedded tranceivers. + It is needed to enable connectivity features. + +config NXP_RF_IMU + bool "Include RF_IMU adapter for intercore messaging" + select EVENTS + help + RF_IMU adapter is needed for intercore messaging. + endif # HAS_MCUX From 0da43814635702ca686989e1942c2d1f2043d520 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1373/1389] soc: rw61x: Add BLE support for rw61x - Add SMU regions - Add HCI definition - Add config when BT is enabled Signed-off-by: Yassine El Aissaoui --- dts/arm/nxp/nxp_rw6xx_common.dtsi | 41 +++++++++++++++++++++++++++++++ soc/nxp/rw/CMakeLists.txt | 2 ++ soc/nxp/rw/Kconfig.defconfig | 35 ++++++++++++++++++++++++++ soc/nxp/rw/sections.ld | 38 ++++++++++++++++++++++++++++ soc/nxp/rw/soc.h | 3 +++ 5 files changed, 119 insertions(+) create mode 100644 soc/nxp/rw/sections.ld diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index b02f5fe281405f..60c3dc9d2d5427 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { chosen { @@ -56,6 +57,15 @@ }; }; }; + + smu1: sram@41380000 { + ranges = <0x0 0x41380000 DT_SIZE_K(510)>; + }; + + smu2: sram@443C0000 { + ranges = <0x0 0x443C0000 DT_SIZE_K(140)>; + }; + }; &sram { @@ -73,6 +83,30 @@ }; }; +&smu1 { + #address-cells = <1>; + #size-cells = <1>; + + smu1_data: memory@0 { + compatible = "zephyr,memory-region","mmio-sram"; + reg = <0x0 DT_SIZE_K(510)>; + zephyr,memory-region = "SMU1"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; +}; + +&smu2 { + #address-cells = <1>; + #size-cells = <1>; + + smu2_data: memory@0 { + compatible = "zephyr,memory-region","mmio-sram"; + reg = <0x0 DT_SIZE_K(140)>; + zephyr,memory-region = "SMU2"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; +}; + &peripheral { #address-cells = <1>; #size-cells = <1>; @@ -443,6 +477,13 @@ interrupts = <41 0>; status = "disabled"; }; + + hci: hci_ble { + compatible = "nxp,hci-ble"; + /* first index is the hci interrupt, the second is the wake up done interrupt */ + interrupts = <90 2>, <82 2>; + interrupt-names = "hci_int", "wakeup_int"; + }; }; &flexspi { diff --git a/soc/nxp/rw/CMakeLists.txt b/soc/nxp/rw/CMakeLists.txt index 3790d07afd87a9..64b8bd4803ab05 100644 --- a/soc/nxp/rw/CMakeLists.txt +++ b/soc/nxp/rw/CMakeLists.txt @@ -17,3 +17,5 @@ zephyr_linker_sources_ifdef(CONFIG_NXP_RW6XX_BOOT_HEADER set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") zephyr_include_directories(.) + +zephyr_linker_sources(RAM_SECTIONS sections.ld) diff --git a/soc/nxp/rw/Kconfig.defconfig b/soc/nxp/rw/Kconfig.defconfig index aa62fea1460a90..7f1ee72b9cf319 100644 --- a/soc/nxp/rw/Kconfig.defconfig +++ b/soc/nxp/rw/Kconfig.defconfig @@ -80,4 +80,39 @@ choice USB_MCUX_CONTROLLER_TYPE default USB_DC_NXP_EHCI endchoice +if BT + +config FLASH + default y + +choice BT_HCI_BUS_TYPE + default BT_NXP +endchoice + +config BT_DIS_MANUF + default "NXP" + +config BT_BUF_EVT_DISCARDABLE_SIZE + default 84 + +config BT_HCI_ACL_FLOW_CONTROL + default n + +config HCI_NXP_ENABLE_AUTO_SLEEP + default y + +config HCI_NXP_SET_CAL_DATA + default y + +config HEAP_MEM_POOL_SIZE + default 256 + +endif # BT + +config NXP_FW_LOADER + default y if (BT || WIFI) + +config NXP_RF_IMU + default y if (BT || WIFI) + endif # SOC_SERIES_RW6XX diff --git a/soc/nxp/rw/sections.ld b/soc/nxp/rw/sections.ld new file mode 100644 index 00000000000000..2fe41f042bd7e1 --- /dev/null +++ b/soc/nxp/rw/sections.ld @@ -0,0 +1,38 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define TXQ23_SIZE 0x1080 +#define SMU1_SIZE DT_REG_SIZE(DT_NODELABEL(smu1_data)) +#define SMU2_SIZE DT_REG_SIZE(DT_NODELABEL(smu2_data)) + + +.SMU1 (NOLOAD) : +{ + . = ALIGN(4); + /* CPU3 <-> CPU1 mailbox */ + *(.smu_cpu13_mbox) + KEEP (*(.smu_cpu13_mbox)) + /* CPU3 -> CPU1 TXQ */ + *(.smu_cpu31_txq) + KEEP (*(.smu_cpu31_txq)) + /* Left space is reserved for CPU3/CPU1 operations */ + . += SMU1_SIZE - .; +} > SMU1 + +.SMU2 (NOLOAD) : +{ + . = ALIGN(4); + /* CPU3 <-> CPU2 mailbox */ + *(.smu_cpu23_mbox) + KEEP (*(.smu_cpu23_mbox)) + /* Reserve space for CPU1 -> CPU3 TXQ (allocated by the CPU2) */ + . += TXQ23_SIZE; + /* CPU3 -> CPU2 TXQ */ + *(.smu_cpu32_txq) + KEEP (*(.smu_cpu32_txq)) + /* Left space is reserved for CPU3/CPU2 operations */ + . += SMU2_SIZE - .; +} > SMU2 diff --git a/soc/nxp/rw/soc.h b/soc/nxp/rw/soc.h index 780bd9b66aad81..13f451493e91e6 100644 --- a/soc/nxp/rw/soc.h +++ b/soc/nxp/rw/soc.h @@ -16,6 +16,9 @@ #endif /* !_ASMLANGUAGE */ +#define ble_hci_handler BLE_MCI_WAKEUP0_DriverIRQHandler +#define ble_wakeup_done_handler BLE_MCI_WAKEUP_DONE0_DriverIRQHandler + /* Wrapper Function to deal with SDK differences in power API */ static inline void EnableDeepSleepIRQ(IRQn_Type irq) { From 74bae852f16ab560260e230ff314ab88474ddd93 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1374/1389] boards: rd_rw612_bga: Update board information - Add pinctrl for flexcomm0 in usart mode needed for BLE tester application - Reserve the firmware storage partition - Mark HCI as a wakeup source Signed-off-by: Yassine El Aissaoui --- boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi | 7 +++++++ boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi index db565403583f14..31a3303d5d6fe8 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi @@ -14,6 +14,13 @@ }; }; + pinmux_flexcomm0_usart: pinmux_flexcomm0_usart { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + }; + pinmux_flexcomm0_spi: pinmux_flexcomm0_spi { group0 { pinmux = , diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi index 3310e806608926..1fa058bfb13133 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi @@ -147,6 +147,16 @@ arduino_i2c: &flexcomm2 { label = "image-0"; reg = <0x00020000 0x3e0000>; }; + + /* This partition is reserved for connectivity firmwares storage + * and shouldn't be moved. + */ + fw_storage: partition@400000 { + label = "fw_storage"; + reg = <0x400000 0x280000>; + read-only; + }; + slot1_partition: partition@680000 { label = "image-1"; reg = <0x680000 0x3e0000>; @@ -264,3 +274,8 @@ zephyr_udc0: &usb_otg { &systick { status = "disabled"; }; + +&hci { + status = "okay"; + wakeup-source; +}; From 2160cc083e61ccc466038de7c8a71947b34408a1 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1375/1389] samples: tests: bluetooth: Add support for rd_rw612_bga Adding bt_tester support. Adding bt_tester app build with Twister for rd_rw612_bga board Fix failing tests/samples due to unsufficent MPU ressources by releasing unnecessary MPU regions. Disable twister build on samples that are not meant to be supported on this board, so exclude it from the test cases. Update peripheral/central ht sample.yaml files to test build for rd_rw612_bga. Signed-off-by: Axel Le Bourhis Signed-off-by: Yassine El Aissaoui --- samples/bluetooth/central_ht/sample.yaml | 2 ++ samples/bluetooth/peripheral_ht/sample.yaml | 2 ++ .../peripheral_ots/boards/rd_rw612_bga.conf | 1 + .../prod_consumer/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../shared_mem/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../bluetooth/tester/boards/rd_rw612_bga.conf | 6 ++++++ tests/bluetooth/tester/rd_rw612_bga.overlay | 19 +++++++++++++++++++ tests/bluetooth/tester/testcase.yaml | 1 + .../mbedtls/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../kernel/common/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../exception/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../mem_protect/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../stackprot/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../userspace/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../thread_stack/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../threads/tls/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ .../thread_safety/boards/rd_rw612_bga.overlay | 17 +++++++++++++++++ 17 files changed, 218 insertions(+) create mode 100644 samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf create mode 100644 samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay create mode 100644 samples/userspace/shared_mem/boards/rd_rw612_bga.overlay create mode 100644 tests/bluetooth/tester/boards/rd_rw612_bga.conf create mode 100644 tests/bluetooth/tester/rd_rw612_bga.overlay create mode 100644 tests/crypto/mbedtls/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/common/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/fatal/exception/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/mem_protect/mem_protect/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/mem_protect/stackprot/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/mem_protect/userspace/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/threads/thread_stack/boards/rd_rw612_bga.overlay create mode 100644 tests/kernel/threads/tls/boards/rd_rw612_bga.overlay create mode 100644 tests/lib/newlib/thread_safety/boards/rd_rw612_bga.overlay diff --git a/samples/bluetooth/central_ht/sample.yaml b/samples/bluetooth/central_ht/sample.yaml index f41b2289705765..f59d207a59fed3 100644 --- a/samples/bluetooth/central_ht/sample.yaml +++ b/samples/bluetooth/central_ht/sample.yaml @@ -8,6 +8,8 @@ tests: - qemu_x86 - nrf51dk/nrf51822 - nrf52dk/nrf52832 + - rd_rw612_bga tags: bluetooth integration_platforms: - qemu_cortex_m3 + - rd_rw612_bga diff --git a/samples/bluetooth/peripheral_ht/sample.yaml b/samples/bluetooth/peripheral_ht/sample.yaml index 4ff509843e0649..4243914b57178b 100644 --- a/samples/bluetooth/peripheral_ht/sample.yaml +++ b/samples/bluetooth/peripheral_ht/sample.yaml @@ -9,9 +9,11 @@ tests: - qemu_x86 - nrf51dk/nrf51822 - nrf52dk/nrf52832 + - rd_rw612_bga tags: bluetooth integration_platforms: - qemu_cortex_m3 + - rd_rw612_bga sample.bluetooth.peripheral_ht.frdm_kw41z_shield: harness: bluetooth platform_allow: diff --git a/samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf b/samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf new file mode 100644 index 00000000000000..b25149c8ec46ac --- /dev/null +++ b/samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_BT_RX_STACK_SIZE=1800 diff --git a/samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay b/samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/samples/userspace/shared_mem/boards/rd_rw612_bga.overlay b/samples/userspace/shared_mem/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/samples/userspace/shared_mem/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/bluetooth/tester/boards/rd_rw612_bga.conf b/tests/bluetooth/tester/boards/rd_rw612_bga.conf new file mode 100644 index 00000000000000..ba1ae16dc7c0bd --- /dev/null +++ b/tests/bluetooth/tester/boards/rd_rw612_bga.conf @@ -0,0 +1,6 @@ +CONFIG_BT_MAX_CONN=16 + +# debug options +# CONFIG_UART_CONSOLE=y +# CONFIG_LOG=y +# CONFIG_LOG_DEFAULT_LEVEL=4 diff --git a/tests/bluetooth/tester/rd_rw612_bga.overlay b/tests/bluetooth/tester/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..4d4b5710e424c5 --- /dev/null +++ b/tests/bluetooth/tester/rd_rw612_bga.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,uart-pipe = &flexcomm0; + }; +}; + +&flexcomm0 { + compatible = "nxp,lpc-usart"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_flexcomm0_usart>; + pinctrl-names = "default"; +}; diff --git a/tests/bluetooth/tester/testcase.yaml b/tests/bluetooth/tester/testcase.yaml index 7721cabf15318e..43fa984a2ced9d 100644 --- a/tests/bluetooth/tester/testcase.yaml +++ b/tests/bluetooth/tester/testcase.yaml @@ -6,6 +6,7 @@ tests: - native_posix - native_sim - nrf52840dk/nrf52840 + - rd_rw612_bga tags: bluetooth harness: bluetooth bluetooth.general.tester_le_audio: diff --git a/tests/crypto/mbedtls/boards/rd_rw612_bga.overlay b/tests/crypto/mbedtls/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/crypto/mbedtls/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/common/boards/rd_rw612_bga.overlay b/tests/kernel/common/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/common/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/fatal/exception/boards/rd_rw612_bga.overlay b/tests/kernel/fatal/exception/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/fatal/exception/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/mem_protect/mem_protect/boards/rd_rw612_bga.overlay b/tests/kernel/mem_protect/mem_protect/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/mem_protect/mem_protect/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/mem_protect/stackprot/boards/rd_rw612_bga.overlay b/tests/kernel/mem_protect/stackprot/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/mem_protect/stackprot/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/mem_protect/userspace/boards/rd_rw612_bga.overlay b/tests/kernel/mem_protect/userspace/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/mem_protect/userspace/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/threads/thread_stack/boards/rd_rw612_bga.overlay b/tests/kernel/threads/thread_stack/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/threads/thread_stack/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/kernel/threads/tls/boards/rd_rw612_bga.overlay b/tests/kernel/threads/tls/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/kernel/threads/tls/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/tests/lib/newlib/thread_safety/boards/rd_rw612_bga.overlay b/tests/lib/newlib/thread_safety/boards/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..b78c0344f1eb05 --- /dev/null +++ b/tests/lib/newlib/thread_safety/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; From 37cade5f2d2e5429f4eb2e70544d24cba098a8d2 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1376/1389] drivers: intc: VPR CLIC should make sure GEN_IRQ_VECTOR_TABLE is enabled VPR cores CLIC supports vectored mode only. Select `GEN_IRQ_VECTOR_TABLE` such that it can't be disabled. Signed-off-by: Yong Cong Sin --- drivers/interrupt_controller/Kconfig.clic | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/interrupt_controller/Kconfig.clic b/drivers/interrupt_controller/Kconfig.clic index fff8d1dffadeb2..db7fe0b6b0d56b 100644 --- a/drivers/interrupt_controller/Kconfig.clic +++ b/drivers/interrupt_controller/Kconfig.clic @@ -14,6 +14,7 @@ config NRFX_CLIC bool "VPR Core Local Interrpt Controller (CLIC)" default y depends on DT_HAS_NORDIC_NRF_CLIC_ENABLED + select GEN_IRQ_VECTOR_TABLE help Interrupt controller for Nordic VPR cores. From 337e3f6ffc7c4e66d9d651497fc8f912d23b9786 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1377/1389] test: gen_isr_table: exclude NRFX_CLIC from riscv_no_direct VPR cores CLIC supports vectored mode only and can't be disabled. Filter out `CONFIG_NRFX_CLIC` to prevent build error. Signed-off-by: Yong Cong Sin --- tests/kernel/gen_isr_table/testcase.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kernel/gen_isr_table/testcase.yaml b/tests/kernel/gen_isr_table/testcase.yaml index 1b06037c780719..bb8c8a1dde7720 100644 --- a/tests/kernel/gen_isr_table/testcase.yaml +++ b/tests/kernel/gen_isr_table/testcase.yaml @@ -78,7 +78,7 @@ tests: arch.interrupt.gen_isr_table.riscv_no_direct: platform_exclude: m2gl025_miv arch_allow: riscv - filter: CONFIG_RISCV_PRIVILEGED + filter: CONFIG_RISCV_PRIVILEGED and not CONFIG_NRFX_CLIC extra_configs: - CONFIG_GEN_IRQ_VECTOR_TABLE=n arch.interrupt.gen_isr_table.bit_shift_2nd_level: From 9adf8fc8a6833202aa80c42700bdb7e6785d054d Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1378/1389] arch: sw_isr: revamp multi-level interrupt architecture Previously the multi-level irq lookup table is generated by looping through the devicetree nodes using macros & Kconfig, which is hard to read and flimsy. This PR shifts the heavy lifting to devicetree & DT macros such that an interrupt controller driver, which has its info in the devicetree, can register itself directly with the multi-level interrupt architecture, which is more straightforward. The previous auto-generated look up table with macros is now moved in a file of its own. A new compatibility Kconfig: `CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION` is added and enabled by default to compile the legacy look up table for interrupt controller drivers that aren't updated to support the new architecture yet. Signed-off-by: Yong Cong Sin --- arch/common/CMakeLists.txt | 2 + arch/common/Kconfig | 10 ++ arch/common/multilevel_irq.c | 163 ++++-------------- arch/common/multilevel_irq_legacy.c | 72 ++++++++ cmake/linker_script/common/common-rom.cmake | 4 + drivers/interrupt_controller/intc_plic.c | 5 + .../zephyr/devicetree/interrupt_controller.h | 60 +++++++ include/zephyr/irq_multilevel.h | 17 ++ include/zephyr/linker/common-rom.ld | 2 + .../common-rom-interrupt-controllers.ld | 9 + include/zephyr/sw_isr_table.h | 75 ++++++++ tests/kernel/gen_isr_table/src/main.c | 15 +- 12 files changed, 306 insertions(+), 128 deletions(-) create mode 100644 arch/common/multilevel_irq_legacy.c create mode 100644 include/zephyr/devicetree/interrupt_controller.h create mode 100644 include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld diff --git a/arch/common/CMakeLists.txt b/arch/common/CMakeLists.txt index 78fc6396ed63ac..407d028cffa77c 100644 --- a/arch/common/CMakeLists.txt +++ b/arch/common/CMakeLists.txt @@ -22,6 +22,8 @@ zephyr_library_sources_ifdef( multilevel_irq.c ) +zephyr_library_sources_ifdef(CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION multilevel_irq_legacy.c) + zephyr_library_sources_ifdef(CONFIG_SHARED_INTERRUPTS shared_irq.c) if(NOT CONFIG_ARCH_HAS_TIMING_FUNCTIONS AND diff --git a/arch/common/Kconfig b/arch/common/Kconfig index aabc599a4d58a9..d53eb393b27578 100644 --- a/arch/common/Kconfig +++ b/arch/common/Kconfig @@ -15,3 +15,13 @@ config SEMIHOST https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc This option is compatible with hardware and with QEMU, through the (automatic) use of the -semihosting-config switch when invoking it. + +config LEGACY_MULTI_LEVEL_TABLE_GENERATION + bool "Auto generates the multi-level interrupt LUT (deprecated)" + default y + select DEPRECATED + depends on MULTI_LEVEL_INTERRUPTS + depends on !PLIC + help + A make-shift Kconfig to continue generating the multi-level interrupt LUT + with the legacy way using DT macros. diff --git a/arch/common/multilevel_irq.c b/arch/common/multilevel_irq.c index 53f8e03a4d8493..25972d41da1641 100644 --- a/arch/common/multilevel_irq.c +++ b/arch/common/multilevel_irq.c @@ -15,162 +15,71 @@ BUILD_ASSERT((CONFIG_NUM_2ND_LEVEL_AGGREGATORS * CONFIG_MAX_IRQ_PER_AGGREGATOR) BIT(CONFIG_2ND_LEVEL_INTERRUPT_BITS), "L2 bits not enough to cover the number of L2 IRQs"); -/* - * Insert code if the node_id is an interrupt controller - */ -#define Z_IF_DT_IS_INTC(node_id, code) \ - IF_ENABLED(DT_NODE_HAS_PROP(node_id, interrupt_controller), (code)) - -/* - * Expands to node_id if its IRQN is equal to `_irq`, nothing otherwise - * This only works for `_irq` between 0 & 4095, see `IS_EQ` - */ -#define Z_IF_DT_INTC_IRQN_EQ(node_id, _irq) IF_ENABLED(IS_EQ(DT_IRQ(node_id, irq), _irq), (node_id)) - -/* - * Expands to node_id if it's an interrupt controller & its IRQN is `irq`, or nothing otherwise - */ -#define Z_DT_INTC_GET_IRQN(node_id, _irq) \ - Z_IF_DT_IS_INTC(node_id, Z_IF_DT_INTC_IRQN_EQ(node_id, _irq)) - /** - * Loop through child of "/soc" and get root interrupt controllers with `_irq` as IRQN, - * this assumes only one device has the IRQN - * @param _irq irq number - * @return node_id(s) that has the `_irq` number, or empty if none of them has the `_irq` + * @brief Get the aggregator that's responsible for the given irq + * + * @param irq IRQ number to query + * + * @return Aggregator entry, NULL if irq is level 1 or not found. */ -#define INTC_DT_IRQN_GET(_irq) \ - DT_FOREACH_CHILD_STATUS_OKAY_VARGS(DT_PATH(soc), Z_DT_INTC_GET_IRQN, _irq) - -/* If can't find any matching interrupt controller, fills with `NULL` */ -#define INTC_DEVICE_INIT(node_id) .dev = DEVICE_DT_GET_OR_NULL(node_id), - -#define INIT_IRQ_PARENT_OFFSET(d, i, o) { \ - INTC_DEVICE_INIT(d) \ - .irq = i, \ - .offset = o, \ -} - -#define IRQ_INDEX_TO_OFFSET(i, base) (base + i * CONFIG_MAX_IRQ_PER_AGGREGATOR) - -#define CAT_2ND_LVL_LIST(i, base) \ - INIT_IRQ_PARENT_OFFSET(INTC_DT_IRQN_GET(CONFIG_2ND_LVL_INTR_0##i##_OFFSET), \ - CONFIG_2ND_LVL_INTR_0##i##_OFFSET, IRQ_INDEX_TO_OFFSET(i, base)) -const struct _irq_parent_entry _lvl2_irq_list[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] - = { LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, CAT_2ND_LVL_LIST, (,), - CONFIG_2ND_LVL_ISR_TBL_OFFSET) }; - -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - -BUILD_ASSERT((CONFIG_NUM_3RD_LEVEL_AGGREGATORS * CONFIG_MAX_IRQ_PER_AGGREGATOR) <= - BIT(CONFIG_3RD_LEVEL_INTERRUPT_BITS), - "L3 bits not enough to cover the number of L3 IRQs"); - -#define CAT_3RD_LVL_LIST(i, base) \ - INIT_IRQ_PARENT_OFFSET(INTC_DT_IRQN_GET(CONFIG_3RD_LVL_INTR_0##i##_OFFSET), \ - CONFIG_3RD_LVL_INTR_0##i##_OFFSET, IRQ_INDEX_TO_OFFSET(i, base)) +static const struct _irq_parent_entry *get_intc_entry_for_irq(unsigned int irq) +{ + const unsigned int level = irq_get_level(irq); -const struct _irq_parent_entry _lvl3_irq_list[CONFIG_NUM_3RD_LEVEL_AGGREGATORS] - = { LISTIFY(CONFIG_NUM_3RD_LEVEL_AGGREGATORS, CAT_3RD_LVL_LIST, (,), - CONFIG_3RD_LVL_ISR_TBL_OFFSET) }; + /* 1st level aggregator is not registered */ + if (level == 1) { + return NULL; + } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + const unsigned int intc_irq = irq_get_intc_irq(irq); -static const struct _irq_parent_entry *get_parent_entry(unsigned int parent_irq, - const struct _irq_parent_entry list[], - unsigned int length) -{ - unsigned int i; - const struct _irq_parent_entry *entry = NULL; - - for (i = 0U; i < length; ++i) { - if (list[i].irq == parent_irq) { - entry = &list[i]; - break; + /* Find an aggregator entry that matches the level & intc_irq */ + STRUCT_SECTION_FOREACH_ALTERNATE(intc_table, _irq_parent_entry, intc) { + if ((intc->level == level) && (intc->irq == intc_irq)) { + return intc; } } - __ASSERT(i != length, "Invalid argument: %i", parent_irq); - - return entry; + return NULL; } const struct device *z_get_sw_isr_device_from_irq(unsigned int irq) { - const struct device *dev = NULL; - unsigned int level, parent_irq; - const struct _irq_parent_entry *entry = NULL; + const struct _irq_parent_entry *intc = get_intc_entry_for_irq(irq); - level = irq_get_level(irq); + __ASSERT(intc != NULL, "can't find an aggregator to handle irq(%X)", irq); - if (level == 2U) { - parent_irq = irq_parent_level_2(irq); - entry = get_parent_entry(parent_irq, - _lvl2_irq_list, - CONFIG_NUM_2ND_LEVEL_AGGREGATORS); - } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - else if (level == 3U) { - parent_irq = irq_parent_level_3(irq); - entry = get_parent_entry(parent_irq, - _lvl3_irq_list, - CONFIG_NUM_3RD_LEVEL_AGGREGATORS); - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - dev = entry != NULL ? entry->dev : NULL; - - return dev; + return intc != NULL ? intc->dev : NULL; } unsigned int z_get_sw_isr_irq_from_device(const struct device *dev) { - for (size_t i = 0U; i < CONFIG_NUM_2ND_LEVEL_AGGREGATORS; ++i) { - if (_lvl2_irq_list[i].dev == dev) { - return _lvl2_irq_list[i].irq; + /* Get the IRQN for the aggregator */ + STRUCT_SECTION_FOREACH_ALTERNATE(intc_table, _irq_parent_entry, intc) { + if (intc->dev == dev) { + return intc->irq; } } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - for (size_t i = 0U; i < CONFIG_NUM_3RD_LEVEL_AGGREGATORS; ++i) { - if (_lvl3_irq_list[i].dev == dev) { - return _lvl3_irq_list[i].irq; - } - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + __ASSERT(false, "dev(%p) not found", dev); return 0; } unsigned int z_get_sw_isr_table_idx(unsigned int irq) { - unsigned int table_idx, level, parent_irq, local_irq, parent_offset; - const struct _irq_parent_entry *entry = NULL; - - level = irq_get_level(irq); + unsigned int table_idx, local_irq; + const struct _irq_parent_entry *intc = get_intc_entry_for_irq(irq); + const unsigned int level = irq_get_level(irq); - if (level == 2U) { - local_irq = irq_from_level_2(irq); + if (intc != NULL) { + local_irq = level == 2 ? irq_from_level_2(irq) : irq_from_level_3(irq); __ASSERT_NO_MSG(local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR); - parent_irq = irq_parent_level_2(irq); - entry = get_parent_entry(parent_irq, - _lvl2_irq_list, - CONFIG_NUM_2ND_LEVEL_AGGREGATORS); - parent_offset = entry != NULL ? entry->offset : 0U; - table_idx = parent_offset + local_irq; - } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - else if (level == 3U) { - local_irq = irq_from_level_3(irq); - __ASSERT_NO_MSG(local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR); - parent_irq = irq_parent_level_3(irq); - entry = get_parent_entry(parent_irq, - _lvl3_irq_list, - CONFIG_NUM_3RD_LEVEL_AGGREGATORS); - parent_offset = entry != NULL ? entry->offset : 0U; - table_idx = parent_offset + local_irq; - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - else { + + table_idx = intc->offset + local_irq; + } else { + /* irq level must be 1 if no intc entry */ + __ASSERT(level == 1, "can't find an aggregator to handle irq(%X)", irq); table_idx = irq; } diff --git a/arch/common/multilevel_irq_legacy.c b/arch/common/multilevel_irq_legacy.c new file mode 100644 index 00000000000000..dd4fe68b5ac455 --- /dev/null +++ b/arch/common/multilevel_irq_legacy.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Intel Corporation. + * Copyright (c) 2024 Meta. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** + * @file + * @brief This file houses the deprecated legacy macros-generated multi-level interrupt lookup + * table code, compiled when `CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION` is enabled. + */ + +/* + * Insert code if the node_id is an interrupt controller + */ +#define Z_IF_DT_IS_INTC(node_id, code) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, interrupt_controller), (code)) + +/* + * Expands to node_id if its IRQN is equal to `_irq`, nothing otherwise + * This only works for `_irq` between 0 & 4095, see `IS_EQ` + */ +#define Z_IF_DT_INTC_IRQN_EQ(node_id, _irq) IF_ENABLED(IS_EQ(DT_IRQ(node_id, irq), _irq), (node_id)) + +/* + * Expands to node_id if it's an interrupt controller & its IRQN is `irq`, or nothing otherwise + */ +#define Z_DT_INTC_GET_IRQN(node_id, _irq) \ + Z_IF_DT_IS_INTC(node_id, Z_IF_DT_INTC_IRQN_EQ(node_id, _irq)) + +/** + * Loop through child of "/soc" and get root interrupt controllers with `_irq` as IRQN, + * this assumes only one device has the IRQN + * @param _irq irq number + * @return node_id(s) that has the `_irq` number, or empty if none of them has the `_irq` + */ +#define INTC_DT_IRQN_GET(_irq) \ + DT_FOREACH_CHILD_STATUS_OKAY_VARGS(DT_PATH(soc), Z_DT_INTC_GET_IRQN, _irq) + +#define INIT_IRQ_PARENT_OFFSET_2ND(n, d, i, o) \ + IRQ_PARENT_ENTRY_DEFINE(intc_l2_##n, DEVICE_DT_GET_OR_NULL(d), i, o, 2) + +#define IRQ_INDEX_TO_OFFSET(i, base) (base + i * CONFIG_MAX_IRQ_PER_AGGREGATOR) + +#define CAT_2ND_LVL_LIST(i, base) \ + INIT_IRQ_PARENT_OFFSET_2ND(i, INTC_DT_IRQN_GET(CONFIG_2ND_LVL_INTR_0##i##_OFFSET), \ + CONFIG_2ND_LVL_INTR_0##i##_OFFSET, \ + IRQ_INDEX_TO_OFFSET(i, base)) + +LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, CAT_2ND_LVL_LIST, (;), CONFIG_2ND_LVL_ISR_TBL_OFFSET); + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + +BUILD_ASSERT((CONFIG_NUM_3RD_LEVEL_AGGREGATORS * CONFIG_MAX_IRQ_PER_AGGREGATOR) <= + BIT(CONFIG_3RD_LEVEL_INTERRUPT_BITS), + "L3 bits not enough to cover the number of L3 IRQs"); + +#define INIT_IRQ_PARENT_OFFSET_3RD(n, d, i, o) \ + IRQ_PARENT_ENTRY_DEFINE(intc_l3_##n, DEVICE_DT_GET_OR_NULL(d), i, o, 3) + +#define CAT_3RD_LVL_LIST(i, base) \ + INIT_IRQ_PARENT_OFFSET_3RD(i, INTC_DT_IRQN_GET(CONFIG_3RD_LVL_INTR_0##i##_OFFSET), \ + CONFIG_3RD_LVL_INTR_0##i##_OFFSET, \ + IRQ_INDEX_TO_OFFSET(i, base)) + +LISTIFY(CONFIG_NUM_3RD_LEVEL_AGGREGATORS, CAT_3RD_LVL_LIST, (;), CONFIG_3RD_LVL_ISR_TBL_OFFSET); + +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index 125d438b58b298..a902a24f3c0e01 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -205,6 +205,10 @@ if (CONFIG_LOG) zephyr_iterable_section(NAME log_backend KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() +if (CONFIG_MULTI_LEVEL_INTERRUPTS) + zephyr_iterable_section(NAME intc_table KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() + if (CONFIG_HTTP_SERVER) zephyr_iterable_section(NAME http_service_desc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index f5f762e4aba9d6..6f959b25cd4bfd 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -576,6 +577,10 @@ SHELL_CMD_ARG_REGISTER(plic, &plic_cmds, "PLIC shell commands", PLIC_INTC_IRQ_FUNC_DEFINE(n) #define PLIC_INTC_DEVICE_INIT(n) \ + IRQ_PARENT_ENTRY_DEFINE( \ + plic##n, DEVICE_DT_INST_GET(n), DT_INST_IRQN(n), \ + INTC_INST_ISR_TBL_OFFSET(n), \ + DT_INST_INTC_GET_AGGREGATOR_LEVEL(n)); \ PLIC_INTC_CONFIG_INIT(n) \ PLIC_INTC_DATA_INIT(n) \ DEVICE_DT_INST_DEFINE(n, &plic_init, NULL, \ diff --git a/include/zephyr/devicetree/interrupt_controller.h b/include/zephyr/devicetree/interrupt_controller.h new file mode 100644 index 00000000000000..a9c4e864ae1984 --- /dev/null +++ b/include/zephyr/devicetree/interrupt_controller.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Interrupt controller devicetree macro public API header file. + */ + +#ifndef ZEPHYR_INCLUDE_DEVICETREE_INTERRUPT_CONTROLLER_H_ +#define ZEPHYR_INCLUDE_DEVICETREE_INTERRUPT_CONTROLLER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @defgroup devicetree-interrupt_controller Devicetree Interrupt Controller API + * @ingroup devicetree + * @{ + */ + +/** + * @brief Get the aggregator level of an interrupt controller + * + * @note Aggregator level is equivalent to IRQ_LEVEL + 1 (a 2nd level aggregator has Zephyr level 1 + * IRQ encoding) + * + * @param node_id node identifier of an interrupt controller + * + * @return Level of the interrupt controller + */ +#define DT_INTC_GET_AGGREGATOR_LEVEL(node_id) UTIL_INC(DT_IRQ_LEVEL(node_id)) + +/** + * @brief Get the aggregator level of a `DT_DRV_COMPAT` interrupt controller + * + * @note Aggregator level is equivalent to IRQ_LEVEL + 1 (a 2nd level aggregator has Zephyr level 1 + * IRQ encoding) + * + * @param inst instance of an interrupt controller + * + * @return Level of the interrupt controller + */ +#define DT_INST_INTC_GET_AGGREGATOR_LEVEL(inst) DT_INTC_GET_AGGREGATOR_LEVEL(DT_DRV_INST(inst)) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEVICETREE_INTERRUPT_CONTROLLER_H_ */ diff --git a/include/zephyr/irq_multilevel.h b/include/zephyr/irq_multilevel.h index 25daa0302495c0..dda2ff2b46b0b0 100644 --- a/include/zephyr/irq_multilevel.h +++ b/include/zephyr/irq_multilevel.h @@ -166,6 +166,23 @@ static inline unsigned int irq_parent_level_3(unsigned int irq) BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); } +/** + * @brief Returns the parent interrupt controller IRQ of the given IRQ number + * + * @param irq IRQ number in its zephyr format + * + * @return IRQ of the interrupt controller + */ +static inline unsigned int irq_get_intc_irq(unsigned int irq) +{ + const unsigned int level = irq_get_level(irq); + + __ASSERT_NO_MSG(level > 1 && level <= 3); + + return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS + + (level == 3 ? CONFIG_2ND_LEVEL_INTERRUPT_BITS : 0)); +} + #endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ #ifdef __cplusplus } diff --git a/include/zephyr/linker/common-rom.ld b/include/zephyr/linker/common-rom.ld index 8f9c89ebdd0c68..7653c1843d1f53 100644 --- a/include/zephyr/linker/common-rom.ld +++ b/include/zephyr/linker/common-rom.ld @@ -14,4 +14,6 @@ #include +#include + #include diff --git a/include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld b/include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld new file mode 100644 index 00000000000000..9ee9dace341886 --- /dev/null +++ b/include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + ITERABLE_SECTION_ROM(intc_table, 4) diff --git a/include/zephyr/sw_isr_table.h b/include/zephyr/sw_isr_table.h index 7b1bfddb2cbda0..ea708cba4f7d3a 100644 --- a/include/zephyr/sw_isr_table.h +++ b/include/zephyr/sw_isr_table.h @@ -16,6 +16,7 @@ #if !defined(_ASMLANGUAGE) #include +#include #include #include #include @@ -47,10 +48,84 @@ extern struct _isr_table_entry _sw_isr_table[]; struct _irq_parent_entry { const struct device *dev; + unsigned int level; unsigned int irq; unsigned int offset; }; +/** + * @cond INTERNAL_HIDDEN + */ + +/* Mapping between aggregator level to order */ +#define Z_STR_L2 2ND +#define Z_STR_L3 3RD +/** + * @brief Get the Software ISR table offset Kconfig for the given aggregator level + * + * @param l Aggregator level, must be 2 or 3 + * + * @return `CONFIG_2ND_LVL_ISR_TBL_OFFSET` if second level aggregator, + * `CONFIG_3RD_LVL_ISR_TBL_OFFSET` if third level aggregator + */ +#define Z_SW_ISR_TBL_KCONFIG_BY_ALVL(l) CONCAT(CONFIG_, CONCAT(Z_STR_L, l), _LVL_ISR_TBL_OFFSET) + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @brief Get an interrupt controller node's level base ISR table offset. + * + * @param node_id node identifier of the interrupt controller + * + * @return `CONFIG_2ND_LVL_ISR_TBL_OFFSET` if node_id is a second level aggregator, + * `CONFIG_3RD_LVL_ISR_TBL_OFFSET` if it is a third level aggregator + */ +#define INTC_BASE_ISR_TBL_OFFSET(node_id) \ + Z_SW_ISR_TBL_KCONFIG_BY_ALVL(DT_INTC_GET_AGGREGATOR_LEVEL(node_id)) + +/** + * @brief Get the SW ISR table offset for an instance of interrupt controller + * + * @param inst DT_DRV_COMPAT interrupt controller driver instance number + * + * @return Software ISR table offset of the interrupt controller + */ +#define INTC_INST_ISR_TBL_OFFSET(inst) \ + (INTC_BASE_ISR_TBL_OFFSET(DT_DRV_INST(inst)) + (inst * CONFIG_MAX_IRQ_PER_AGGREGATOR)) + +/** + * @brief Get the SW ISR table offset for a child interrupt controller + * + * @details This macro is a alternative form of the `INTC_INST_ISR_TBL_OFFSET`. This is used by + * pseudo interrupt controller devices that are child of a main interrupt controller device. + * + * @param node_id node identifier of the child interrupt controller + * + * @return Software ISR table offset of the child + */ +#define INTC_CHILD_ISR_TBL_OFFSET(node_id) \ + (INTC_BASE_ISR_TBL_OFFSET(node_id) + \ + (DT_NODE_CHILD_IDX(node_id) * CONFIG_MAX_IRQ_PER_AGGREGATOR)) + +/** + * @brief Register an interrupt controller with the software ISR table + * + * @param _name Name of the interrupt controller (must be unique) + * @param _dev Pointer to the interrupt controller device instance + * @param _irq Interrupt controller IRQ number + * @param _offset Software ISR table offset of the interrupt controller + * @param _level Interrupt controller aggregator level + */ +#define IRQ_PARENT_ENTRY_DEFINE(_name, _dev, _irq, _offset, _level) \ + static const STRUCT_SECTION_ITERABLE_ALTERNATE(intc_table, _irq_parent_entry, _name) = { \ + .dev = _dev, \ + .level = _level, \ + .irq = _irq, \ + .offset = _offset, \ + } + /* * Data structure created in a special binary .intlist section for each * configured interrupt. gen_irq_tables.py pulls this out of the binary and diff --git a/tests/kernel/gen_isr_table/src/main.c b/tests/kernel/gen_isr_table/src/main.c index 2f6476a1f344a5..95a8940d25cdd3 100644 --- a/tests/kernel/gen_isr_table/src/main.c +++ b/tests/kernel/gen_isr_table/src/main.c @@ -407,7 +407,9 @@ static void test_multi_level_bit_masks_fn(uint32_t irq1, uint32_t irq2, uint32_t const bool has_l3 = irq3 > 0; const bool has_l2 = irq2 > 0; const uint32_t level = has_l3 ? 3 : has_l2 ? 2 : 1; - const uint32_t irqn = (irq3 << l3_shift) | (irq2 << l2_shift) | irq1; + const uint32_t irqn_l1 = irq1; + const uint32_t irqn_l2 = (irq2 << l2_shift) | irqn_l1; + const uint32_t irqn = (irq3 << l3_shift) | irqn_l2; zassert_equal(level, irq_get_level(irqn)); @@ -422,6 +424,17 @@ static void test_multi_level_bit_masks_fn(uint32_t irq1, uint32_t irq2, uint32_t zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level_3(hwirq3)); zassert_equal(hwirq2 + 1, irq_parent_level_3(irqn)); } + + if (has_l3) { + zassert_equal(irqn_l2, irq_get_intc_irq(irqn)); + } else if (has_l2) { + zassert_equal(irqn_l1, irq_get_intc_irq(irqn)); + } else { + /* degenerate cases */ + if (false) { + zassert_equal(irqn, irq_get_intc_irq(irqn)); + } + } } ZTEST(gen_isr_table, test_multi_level_bit_masks_l1) From 1355f5b5807162db8bb02976b5263ab7b21a98db Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:41 +0200 Subject: [PATCH 1379/1389] doc: migration-guide: 3.7: add note on multilevel interrupt arch changes Add a note on the revamp of the multilevel interrupt architecture, the changes to be made, and new macros to help with the update. Signed-off-by: Yong Cong Sin --- doc/releases/migration-guide-3.7.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 5dc2312a57d9ad..27834decc3fb10 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -301,6 +301,20 @@ Input Interrupt Controller ==================== +* The static auto-generation of the multilevel interrupt controller lookup table has been + deprecated, and will be compiled only when the new compatibility Kconfig: + :kconfig:option:`CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION` is enabled, which will eventually + be removed in the coming releases. + + Multi-level interrupt controller drivers should be updated to use the newly created + ``IRQ_PARENT_ENTRY_DEFINE`` macro to register itself with the new multi-level interrupt + architecture. To make the macro easier to use, ``INTC_INST_ISR_TBL_OFFSET`` macro is made to + deduce the software ISR table offset for a given driver instance, for pseudo interrupt controller + child, use the ``INTC_CHILD_ISR_TBL_OFFSET`` macro instead. New devicetree macros + (``DT_INTC_GET_AGGREGATOR_LEVEL`` & ``DT_INST_INTC_GET_AGGREGATOR_LEVEL``) have been added + for an interrupt controller driver instance to pass its aggregator level into the + ``IRQ_PARENT_ENTRY_DEFINE`` macro. + LED Strip ========= From 31c48a5dd0a9d11c15fba813bb644623f5b66724 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1380/1389] drivers: intc: plic: simplify isr handling Save the reference of the start index of the `_sw_isr_table` to the config struct, so that the `local_irq` can be used as offset directly. Signed-off-by: Yong Cong Sin --- drivers/interrupt_controller/intc_plic.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index 6f959b25cd4bfd..144e448a04d4a7 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -76,6 +76,7 @@ struct plic_config { uint32_t max_prio; uint32_t num_irqs; riscv_plic_irq_config_func_t irq_config_func; + struct _isr_table_entry *isr_table; }; struct plic_stats { @@ -367,15 +368,8 @@ static void plic_irq_handler(const struct device *dev) } #endif - const uint32_t parent_irq = COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), - (z_get_sw_isr_irq_from_device(dev)), (0U)); - const uint32_t irq = irq_to_level_2(local_irq) | parent_irq; - const unsigned int isr_offset = - COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), (z_get_sw_isr_table_idx(irq)), - (irq_from_level_2(irq) + CONFIG_2ND_LVL_ISR_TBL_OFFSET)); - /* Call the corresponding IRQ handler in _sw_isr_table */ - ite = (struct _isr_table_entry *)&_sw_isr_table[isr_offset]; + ite = &config->isr_table[local_irq]; ite->isr(ite->arg); /* @@ -573,6 +567,7 @@ SHELL_CMD_ARG_REGISTER(plic, &plic_cmds, "PLIC shell commands", .max_prio = DT_INST_PROP(n, riscv_max_priority), \ .num_irqs = DT_INST_PROP(n, riscv_ndev), \ .irq_config_func = plic_irq_config_func_##n, \ + .isr_table = &_sw_isr_table[INTC_INST_ISR_TBL_OFFSET(n)], \ }; \ PLIC_INTC_IRQ_FUNC_DEFINE(n) From b97d8d9d7bc28590150377e9496186109c12b9ca Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1381/1389] irq: multilevel: add APIs with `level` as argument Add APIs that accept an additional `level` argument, and use that to call the respective functions. In some cases this can reduce code complexity, especially when the level isn't known at build time. Signed-off-by: Yong Cong Sin --- include/zephyr/irq_multilevel.h | 71 +++++++++++++++++++++++++++ tests/kernel/gen_isr_table/src/main.c | 6 +++ 2 files changed, 77 insertions(+) diff --git a/include/zephyr/irq_multilevel.h b/include/zephyr/irq_multilevel.h index dda2ff2b46b0b0..b500559f1c7220 100644 --- a/include/zephyr/irq_multilevel.h +++ b/include/zephyr/irq_multilevel.h @@ -12,6 +12,7 @@ #define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ #ifndef _ASMLANGUAGE +#include #include #include @@ -166,6 +167,76 @@ static inline unsigned int irq_parent_level_3(unsigned int irq) BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); } +/** + * @brief Return the interrupt number for a given level + * + * @param irq IRQ number in its zephyr format + * @param level IRQ level + * + * @return IRQ number in the level + */ +static inline unsigned int irq_from_level(unsigned int irq, unsigned int level) +{ + if (level == 1) { + return irq; + } else if (level == 2) { + return irq_from_level_2(irq); + } else if (level == 3) { + return irq_from_level_3(irq); + } + + /* level is higher than 3 */ + __ASSERT_NO_MSG(false); + return irq; +} + +/** + * @brief Converts irq from level 1 to to a given level + * + * @param irq IRQ number in its zephyr format + * @param level IRQ level + * + * @return Converted IRQ number in the level + */ +static inline unsigned int irq_to_level(unsigned int irq, unsigned int level) +{ + if (level == 1) { + return irq; + } else if (level == 2) { + return irq_to_level_2(irq); + } else if (level == 3) { + return irq_to_level_3(irq); + } + + /* level is higher than 3 */ + __ASSERT_NO_MSG(false); + return irq; +} + +/** + * @brief Returns the parent IRQ of the given level raw IRQ number + * + * @param irq IRQ number in its zephyr format + * @param level IRQ level + * + * @return IRQ parent of the given level + */ +static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level) +{ + if (level == 1) { + /* doesn't really make sense, but return anyway */ + return irq; + } else if (level == 2) { + return irq_parent_level_2(irq); + } else if (level == 3) { + return irq_parent_level_3(irq); + } + + /* level is higher than 3 */ + __ASSERT_NO_MSG(false); + return irq; +} + /** * @brief Returns the parent interrupt controller IRQ of the given IRQ number * diff --git a/tests/kernel/gen_isr_table/src/main.c b/tests/kernel/gen_isr_table/src/main.c index 95a8940d25cdd3..b71b47dafbca00 100644 --- a/tests/kernel/gen_isr_table/src/main.c +++ b/tests/kernel/gen_isr_table/src/main.c @@ -415,14 +415,20 @@ static void test_multi_level_bit_masks_fn(uint32_t irq1, uint32_t irq2, uint32_t if (has_l2) { zassert_equal(hwirq2, irq_from_level_2(irqn)); + zassert_equal(hwirq2, irq_from_level(irqn, 2)); zassert_equal((hwirq2 + 1) << l2_shift, irq_to_level_2(hwirq2)); + zassert_equal((hwirq2 + 1) << l2_shift, irq_to_level(hwirq2, 2)); zassert_equal(hwirq1, irq_parent_level_2(irqn)); + zassert_equal(hwirq1, irq_parent_level(irqn, 2)); } if (has_l3) { zassert_equal(hwirq3, irq_from_level_3(irqn)); + zassert_equal(hwirq3, irq_from_level(irqn, 3)); zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level_3(hwirq3)); + zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level(hwirq3, 3)); zassert_equal(hwirq2 + 1, irq_parent_level_3(irqn)); + zassert_equal(hwirq2 + 1, irq_parent_level(irqn, 3)); } if (has_l3) { From 07c42a04ec8084673a4c26d3fbd8271edb12541f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1382/1389] arch: common: multilevel_irq: simplification with new multilevel IRQ APIs Use the multi-level interrupt APIs that accepts `level` as an argument for the code where the level of the interrupt is not known at build time. Signed-off-by: Yong Cong Sin --- arch/common/multilevel_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/common/multilevel_irq.c b/arch/common/multilevel_irq.c index 25972d41da1641..be2e8892e1f274 100644 --- a/arch/common/multilevel_irq.c +++ b/arch/common/multilevel_irq.c @@ -73,7 +73,7 @@ unsigned int z_get_sw_isr_table_idx(unsigned int irq) const unsigned int level = irq_get_level(irq); if (intc != NULL) { - local_irq = level == 2 ? irq_from_level_2(irq) : irq_from_level_3(irq); + local_irq = irq_from_level(irq, level); __ASSERT_NO_MSG(local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR); table_idx = intc->offset + local_irq; From 8b3b884c119f6cc95dfcf3a7cb25fa9bbe025428 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1383/1389] drivers: interrupt_controller: irq_steer: use new multilevel irq impl Update the NXP's irq_steer driver to use the new multi-level interrupt implementation. Signed-off-by: Yong Cong Sin --- arch/common/Kconfig | 1 + drivers/interrupt_controller/intc_nxp_irqsteer.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/arch/common/Kconfig b/arch/common/Kconfig index d53eb393b27578..2df4d3a8e8b19d 100644 --- a/arch/common/Kconfig +++ b/arch/common/Kconfig @@ -22,6 +22,7 @@ config LEGACY_MULTI_LEVEL_TABLE_GENERATION select DEPRECATED depends on MULTI_LEVEL_INTERRUPTS depends on !PLIC + depends on !NXP_IRQSTEER help A make-shift Kconfig to continue generating the multi-level interrupt LUT with the legacy way using DT macros. diff --git a/drivers/interrupt_controller/intc_nxp_irqsteer.c b/drivers/interrupt_controller/intc_nxp_irqsteer.c index cd06b23854acff..41157f08cde04d 100644 --- a/drivers/interrupt_controller/intc_nxp_irqsteer.c +++ b/drivers/interrupt_controller/intc_nxp_irqsteer.c @@ -223,9 +223,11 @@ */ #include +#include #include #include #include +#include #include "sw_isr_common.h" @@ -478,3 +480,10 @@ DEVICE_DT_INST_DEFINE(0, NULL, &irqsteer_config, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); + +#define NXP_IRQSTEER_MASTER_IRQ_ENTRY_DEF(node_id) \ + IRQ_PARENT_ENTRY_DEFINE(CONCAT(nxp_irqsteer_master_, DT_NODE_CHILD_IDX(node_id)), NULL, \ + DT_IRQN(node_id), INTC_CHILD_ISR_TBL_OFFSET(node_id), \ + DT_INTC_GET_AGGREGATOR_LEVEL(node_id)); + +DT_INST_FOREACH_CHILD_STATUS_OKAY(0, NXP_IRQSTEER_MASTER_IRQ_ENTRY_DEF); From 026665edb9e94fb03a42831f2133d99ee836f3da Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1384/1389] drivers: intc_dw_ace: convert to use instance-based macros Define the DRV_COMPAT and use instance-based device DT macros. Signed-off-by: Yong Cong Sin --- drivers/interrupt_controller/intc_dw_ace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/interrupt_controller/intc_dw_ace.c b/drivers/interrupt_controller/intc_dw_ace.c index 9bda4bddcfa4b5..300ee3a10be656 100644 --- a/drivers/interrupt_controller/intc_dw_ace.c +++ b/drivers/interrupt_controller/intc_dw_ace.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT intel_ace_intc + #include #include #include @@ -68,7 +70,7 @@ * ACE_INTC[core_id].irq_inten_l |= interrupt_bit; */ -#define ACE_INTC ((volatile struct dw_ictl_registers *)DT_REG_ADDR(DT_NODELABEL(ace_intc))) +#define ACE_INTC ((volatile struct dw_ictl_registers *)DT_INST_REG_ADDR(0)) static inline bool is_dw_irq(uint32_t irq) { @@ -175,6 +177,6 @@ static const struct dw_ace_v1_ictl_driver_api dw_ictl_ace_v1x_apis = { #endif }; -DEVICE_DT_DEFINE(DT_NODELABEL(ace_intc), dw_ace_init, NULL, NULL, NULL, +DEVICE_DT_INST_DEFINE(0, dw_ace_init, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, &dw_ictl_ace_v1x_apis); From 58ea2aa28ccdb4bd9d4312e796638b5555bc61e0 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1385/1389] drivers: intc: update to use multi-level API Update these multi-level interrupt drivers to use the new API. Signed-off-by: Yong Cong Sin --- arch/common/Kconfig | 4 ++++ drivers/interrupt_controller/intc_cavs.c | 8 +++++++- drivers/interrupt_controller/intc_dw.c | 5 +++++ drivers/interrupt_controller/intc_dw_ace.c | 7 +++++-- drivers/interrupt_controller/intc_rv32m1_intmux.c | 8 ++++++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/arch/common/Kconfig b/arch/common/Kconfig index 2df4d3a8e8b19d..ba74cf6dda75ac 100644 --- a/arch/common/Kconfig +++ b/arch/common/Kconfig @@ -23,6 +23,10 @@ config LEGACY_MULTI_LEVEL_TABLE_GENERATION depends on MULTI_LEVEL_INTERRUPTS depends on !PLIC depends on !NXP_IRQSTEER + depends on !RV32M1_INTMUX + depends on !CAVS_ICTL + depends on !DW_ICTL_ACE + depends on !DW_ICTL help A make-shift Kconfig to continue generating the multi-level interrupt LUT with the legacy way using DT macros. diff --git a/drivers/interrupt_controller/intc_cavs.c b/drivers/interrupt_controller/intc_cavs.c index 47e4940e139777..38e22c233e8172 100644 --- a/drivers/interrupt_controller/intc_cavs.c +++ b/drivers/interrupt_controller/intc_cavs.c @@ -8,9 +8,11 @@ #include #include +#include #include #include #include +#include #include "intc_cavs.h" #if defined(CONFIG_SMP) && (CONFIG_MP_MAX_NUM_CPUS > 1) @@ -150,6 +152,10 @@ static const struct irq_next_level_api cavs_apis = { IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ cavs_ictl_isr, DEVICE_DT_INST_GET(n), \ DT_INST_IRQ(n, sense)); \ - } + } \ + IRQ_PARENT_ENTRY_DEFINE( \ + intc_cavs_##n, DEVICE_DT_INST_GET(n), DT_INST_IRQN(n), \ + INTC_INST_ISR_TBL_OFFSET(n), \ + DT_INST_INTC_GET_AGGREGATOR_LEVEL(n)); DT_INST_FOREACH_STATUS_OKAY(CAVS_ICTL_INIT) diff --git a/drivers/interrupt_controller/intc_dw.c b/drivers/interrupt_controller/intc_dw.c index 3d221b50370caf..1abee2e514eafe 100644 --- a/drivers/interrupt_controller/intc_dw.c +++ b/drivers/interrupt_controller/intc_dw.c @@ -14,7 +14,9 @@ */ #include +#include #include +#include #include "intc_dw.h" #include #include @@ -156,3 +158,6 @@ static void dw_ictl_config_irq(const struct device *port) DEVICE_DT_INST_GET(0), DT_INST_IRQ(0, sense)); } + +IRQ_PARENT_ENTRY_DEFINE(intc_dw, DEVICE_DT_INST_GET(0), DT_INST_IRQN(0), + INTC_INST_ISR_TBL_OFFSET(0), DT_INST_INTC_GET_AGGREGATOR_LEVEL(0)); diff --git a/drivers/interrupt_controller/intc_dw_ace.c b/drivers/interrupt_controller/intc_dw_ace.c index 300ee3a10be656..40f61a69e4e6af 100644 --- a/drivers/interrupt_controller/intc_dw_ace.c +++ b/drivers/interrupt_controller/intc_dw_ace.c @@ -8,11 +8,10 @@ #include #include +#include #include #include -#ifdef CONFIG_DYNAMIC_INTERRUPTS #include -#endif #include #include #include @@ -180,3 +179,7 @@ static const struct dw_ace_v1_ictl_driver_api dw_ictl_ace_v1x_apis = { DEVICE_DT_INST_DEFINE(0, dw_ace_init, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, &dw_ictl_ace_v1x_apis); + +IRQ_PARENT_ENTRY_DEFINE(ace_intc, DEVICE_DT_INST_GET(0), DT_INST_IRQN(0), + INTC_BASE_ISR_TBL_OFFSET(DT_DRV_INST(0)), + DT_INST_INTC_GET_AGGREGATOR_LEVEL(0)); diff --git a/drivers/interrupt_controller/intc_rv32m1_intmux.c b/drivers/interrupt_controller/intc_rv32m1_intmux.c index b9b10c042112ee..f5af9f70e7ebce 100644 --- a/drivers/interrupt_controller/intc_rv32m1_intmux.c +++ b/drivers/interrupt_controller/intc_rv32m1_intmux.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -218,3 +219,10 @@ static int rv32m1_intmux_init(const struct device *dev) DEVICE_DT_INST_DEFINE(0, &rv32m1_intmux_init, NULL, NULL, &rv32m1_intmux_cfg, PRE_KERNEL_1, CONFIG_RV32M1_INTMUX_INIT_PRIORITY, &rv32m1_intmux_apis); + +#define INTC_CHILD_IRQ_ENTRY_DEF(node_id) \ + IRQ_PARENT_ENTRY_DEFINE(CONCAT(DT_DRV_COMPAT, _child_, DT_NODE_CHILD_IDX(node_id)), NULL, \ + DT_IRQN(node_id), INTC_CHILD_ISR_TBL_OFFSET(node_id), \ + DT_INTC_GET_AGGREGATOR_LEVEL(node_id)); + +DT_INST_FOREACH_CHILD_STATUS_OKAY(0, INTC_CHILD_IRQ_ENTRY_DEF); From 7efcd71ac8d01db2c41578b75327531676c52793 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1386/1389] tests: drivers: build_all: intc: add a common build-only test Add a generic build-only test for: - intc_nxp_irqsteer - intc_cavs - intc_rv32m1_intmux - intc_dw_ace - intc_dw Signed-off-by: Yong Cong Sin --- .../common/CMakeLists.txt | 8 ++++ .../boards/imx8mp_evk_mimx8ml8_adsp.conf | 14 ++++++ .../boards/imx8mp_evk_mimx8ml8_adsp.overlay | 46 +++++++++++++++++++ .../boards/intel_adsp_ace20_lnl.overlay | 21 +++++++++ .../interrupt_controller/common/prj.conf | 3 ++ .../interrupt_controller/common/src/main.c | 10 ++++ .../interrupt_controller/common/testcase.yaml | 21 +++++++++ 7 files changed, 123 insertions(+) create mode 100644 tests/drivers/build_all/interrupt_controller/common/CMakeLists.txt create mode 100644 tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.conf create mode 100644 tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.overlay create mode 100644 tests/drivers/build_all/interrupt_controller/common/boards/intel_adsp_ace20_lnl.overlay create mode 100644 tests/drivers/build_all/interrupt_controller/common/prj.conf create mode 100644 tests/drivers/build_all/interrupt_controller/common/src/main.c create mode 100644 tests/drivers/build_all/interrupt_controller/common/testcase.yaml diff --git a/tests/drivers/build_all/interrupt_controller/common/CMakeLists.txt b/tests/drivers/build_all/interrupt_controller/common/CMakeLists.txt new file mode 100644 index 00000000000000..213deed619daf3 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(common) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.conf b/tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.conf new file mode 100644 index 00000000000000..d8e1b2f7fe1485 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.conf @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +# Made-up config to build intc_nxp_irqsteer.c, refer to: +# https://github.com/zephyrproject-rtos/zephyr/pull/62776#issuecomment-1727846332 + +CONFIG_MULTI_LEVEL_INTERRUPTS=y +CONFIG_2ND_LEVEL_INTERRUPTS=y +CONFIG_2ND_LVL_ISR_TBL_OFFSET=32 +CONFIG_MAX_IRQ_PER_AGGREGATOR=64 +CONFIG_NUM_2ND_LEVEL_AGGREGATORS=3 +CONFIG_2ND_LVL_INTR_00_OFFSET=19 +CONFIG_2ND_LVL_INTR_01_OFFSET=20 +CONFIG_2ND_LVL_INTR_02_OFFSET=21 diff --git a/tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.overlay b/tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.overlay new file mode 100644 index 00000000000000..9da8bafefc1a76 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/boards/imx8mp_evk_mimx8ml8_adsp.overlay @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Made-up devicetree to build intc_nxp_irqsteer.c, refer to: + * https://github.com/zephyrproject-rtos/zephyr/pull/62776#issuecomment-1727846332 + */ + + /{ + soc { + irqsteer: interrupt-controller@30a80000 { + compatible = "nxp,irqsteer-intc"; + reg = <0x30a80000 DT_SIZE_K(64)>; + + #size-cells = <0>; + #address-cells = <1>; + + master0: interrupt-controller@0 { + compatible = "nxp,irqsteer-master"; + reg = <0>; + interrupt-controller; + #interrupt-cells = <1>; + interrupts-extended = <&clic 19 0 0>; + }; + + master1: interrupt-controller@1 { + compatible = "nxp,irqsteer-master"; + reg = <1>; + interrupt-controller; + #interrupt-cells = <1>; + interrupts-extended = <&clic 20 0 0>; + }; + + master2: interrupt-controller@2 { + compatible = "nxp,irqsteer-master"; + reg = <2>; + interrupt-controller; + #interrupt-cells = <1>; + interrupts-extended = <&clic 21 0 0>; + }; + }; + }; +}; diff --git a/tests/drivers/build_all/interrupt_controller/common/boards/intel_adsp_ace20_lnl.overlay b/tests/drivers/build_all/interrupt_controller/common/boards/intel_adsp_ace20_lnl.overlay new file mode 100644 index 00000000000000..e0594ff091ac28 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/boards/intel_adsp_ace20_lnl.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Made-up devicetree to build intc_dw.c */ + + /{ + soc { + dw_intc: dw_intc@7a000 { + compatible = "snps,designware-intc"; + reg = <0x7a000 0xc00>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <6 0 0>; + num-irqs = <28>; + interrupt-parent = <&core_intc>; + }; + }; +}; diff --git a/tests/drivers/build_all/interrupt_controller/common/prj.conf b/tests/drivers/build_all/interrupt_controller/common/prj.conf new file mode 100644 index 00000000000000..4fac64b8a333a4 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/prj.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST=y diff --git a/tests/drivers/build_all/interrupt_controller/common/src/main.c b/tests/drivers/build_all/interrupt_controller/common/src/main.c new file mode 100644 index 00000000000000..689c8bf6b53f00 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/src/main.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/interrupt_controller/common/testcase.yaml b/tests/drivers/build_all/interrupt_controller/common/testcase.yaml new file mode 100644 index 00000000000000..98b9d2ac1d8404 --- /dev/null +++ b/tests/drivers/build_all/interrupt_controller/common/testcase.yaml @@ -0,0 +1,21 @@ +common: + build_only: true + tags: + - drivers + - interrupt +tests: + drivers.interrupt_controller.common.intc_nxp_irqsteer.build: + platform_allow: + - imx8mp_evk/mimx8ml8/adsp + drivers.interrupt_controller.common.intc_cavs.build: + platform_allow: + - intel_adsp/cavs25 + drivers.interrupt_controller.common.intc_rv32m1_intmux.build: + platform_allow: + - rv32m1_vega/openisa_rv32m1/zero_riscy + drivers.interrupt_controller.common.intc_dw_ace.build: + platform_allow: + - intel_adsp/ace15_mtpm + drivers.interrupt_controller.common.intc_dw.build: + platform_allow: + - intel_adsp/ace20_lnl From 9cb26729911ec1f68ae07f6f195fce212aa4d586 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1387/1389] tests: drivers: intc: verify registration of controllers Test the registration of interrupt controller with the intc_table and verify that thru the sw_isr_table APIs. Verified registration with all 3 interrupt levels. Signed-off-by: Yong Cong Sin --- .../multi_level_backend/CMakeLists.txt | 12 ++ .../multi_level_backend/Kconfig | 18 ++ .../multi_level_backend/prj.conf | 12 ++ .../multi_level_backend/src/main.c | 178 ++++++++++++++++++ .../multi_level_backend/testcase.yaml | 16 ++ 5 files changed, 236 insertions(+) create mode 100644 tests/drivers/interrupt_controller/multi_level_backend/CMakeLists.txt create mode 100644 tests/drivers/interrupt_controller/multi_level_backend/Kconfig create mode 100644 tests/drivers/interrupt_controller/multi_level_backend/prj.conf create mode 100644 tests/drivers/interrupt_controller/multi_level_backend/src/main.c create mode 100644 tests/drivers/interrupt_controller/multi_level_backend/testcase.yaml diff --git a/tests/drivers/interrupt_controller/multi_level_backend/CMakeLists.txt b/tests/drivers/interrupt_controller/multi_level_backend/CMakeLists.txt new file mode 100644 index 00000000000000..9333affd479607 --- /dev/null +++ b/tests/drivers/interrupt_controller/multi_level_backend/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(intc_multi_level_backend) + +# required for "sw_isr_common.h" +zephyr_library_include_directories(${ZEPHYR_BASE}/arch/common/include) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/interrupt_controller/multi_level_backend/Kconfig b/tests/drivers/interrupt_controller/multi_level_backend/Kconfig new file mode 100644 index 00000000000000..31c67ccc7d47be --- /dev/null +++ b/tests/drivers/interrupt_controller/multi_level_backend/Kconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +if RISCV + +config NUM_IRQS + int + # let's pretend that the level 1 supports 64 lines + # (MAX_IRQ_PER_AGGREGATOR x (NUM_2ND_LEVEL_AGGREGATORS + NUM_3RD_LEVEL_AGGREGATORS)) + 64 + # (64 x 4) + 64 = 320 + default 320 + +endif # RISCV + +config DUMP_INTC_TABLE + bool "Enable to dump the content of intc table" + +source "Kconfig.zephyr" diff --git a/tests/drivers/interrupt_controller/multi_level_backend/prj.conf b/tests/drivers/interrupt_controller/multi_level_backend/prj.conf new file mode 100644 index 00000000000000..407b7b66121105 --- /dev/null +++ b/tests/drivers/interrupt_controller/multi_level_backend/prj.conf @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +CONFIG_MAX_IRQ_PER_AGGREGATOR=64 +CONFIG_2ND_LEVEL_INTERRUPT_BITS=9 +CONFIG_NUM_2ND_LEVEL_AGGREGATORS=2 +CONFIG_3RD_LEVEL_INTERRUPTS=y +CONFIG_NUM_3RD_LEVEL_AGGREGATORS=2 + +# Uncomment the following to dump the contents of intc_table +# CONFIG_DUMP_INTC_TABLE=y diff --git a/tests/drivers/interrupt_controller/multi_level_backend/src/main.c b/tests/drivers/interrupt_controller/multi_level_backend/src/main.c new file mode 100644 index 00000000000000..7aba6aebef4198 --- /dev/null +++ b/tests/drivers/interrupt_controller/multi_level_backend/src/main.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sw_isr_common.h" + +#include + +#include +#include +#include + +#ifdef CONFIG_DUMP_INTC_TABLE +#define DEBUG_PRINT(...) PRINT(__VA_ARGS__) +#else +#define DEBUG_PRINT(...) +#endif + +/** + * Fake device pointers + */ +/* Device pointer to level 2 intc 1 */ +#define INTC_1_DEV UINT_TO_POINTER(21) +/* Device pointer to level 2 intc 2 */ +#define INTC_2_DEV UINT_TO_POINTER(22) +/* Device pointer to level 3 intc 3*/ +#define INTC_3_DEV UINT_TO_POINTER(31) +/* Device pointer to level 3 intc 4 */ +#define INTC_4_DEV UINT_TO_POINTER(32) + +/** + * Interrupt controller's local IRQ + */ +/* Local IRQ of level 2 intc 1 */ +#define INTC_1_IRQ 4 +/* Local IRQ of level 2 intc 2 */ +#define INTC_2_IRQ 5 +/* Local IRQ of level 3 intc 3 */ +#define INTC_3_IRQ 9 +/* Local IRQ of level 3 intc 4 */ +#define INTC_4_IRQ 10 + +/** + * Interrupt controller's IRQ in Zephyr format + */ +/* Zephyr IRQ of level 2 intc 1 */ +#define INTC_1_IRQN INTC_1_IRQ +/* Zephyr IRQ of level 2 intc 2 */ +#define INTC_2_IRQN INTC_2_IRQ +/* Zephyr IRQ of level 3 intc 3*/ +#define INTC_3_IRQN (IRQ_TO_L2(INTC_3_IRQ) | INTC_1_IRQN) +/* Zephyr IRQ of level 3 intc 4 */ +#define INTC_4_IRQN (IRQ_TO_L2(INTC_4_IRQ) | INTC_2_IRQN) + +/** + * Register all interrupt controller with the intc table + */ +/* Helper to calculate the stride for each intc in the ISR table */ +#define INTC_COUNT(n) (n * CONFIG_MAX_IRQ_PER_AGGREGATOR) +#define INTC_1_OFFSET INTC_COUNT(1) +#define INTC_2_OFFSET INTC_COUNT(2) +#define INTC_3_OFFSET INTC_COUNT(3) +#define INTC_4_OFFSET INTC_COUNT(4) +IRQ_PARENT_ENTRY_DEFINE(intc_l2_1, INTC_1_DEV, INTC_1_IRQN, INTC_1_OFFSET, 2); +IRQ_PARENT_ENTRY_DEFINE(intc_l2_2, INTC_2_DEV, INTC_2_IRQN, INTC_2_OFFSET, 2); +IRQ_PARENT_ENTRY_DEFINE(intc_l3_3, INTC_3_DEV, INTC_3_IRQN, INTC_3_OFFSET, 3); +IRQ_PARENT_ENTRY_DEFINE(intc_l3_4, INTC_4_DEV, INTC_4_IRQN, INTC_4_OFFSET, 3); + +/** + * Test IRQs in local format + */ +#define TEST_IRQ_1 2 +#define TEST_IRQ_2 3 +#define TEST_IRQ_3 4 +#define TEST_IRQ_4 5 + +/** + * Test IRQs in Zephyr format + */ +/* TEST_IRQ_1 handled by intc_l2_1 */ +#define TEST_IRQN_1 (IRQ_TO_L2(TEST_IRQ_1) | INTC_1_IRQN) +/* TEST_IRQ_2 handled by intc_l2_2 */ +#define TEST_IRQN_2 (IRQ_TO_L2(TEST_IRQ_2) | INTC_2_IRQN) +/* TEST_IRQ_3 handled by intc_l3_1 */ +#define TEST_IRQN_3 (IRQ_TO_L3(TEST_IRQ_3) | INTC_3_IRQN) +/* TEST_IRQ_4 handled by intc_l3_2 */ +#define TEST_IRQN_4 (IRQ_TO_L3(TEST_IRQ_4) | INTC_4_IRQN) + +ZTEST(intc_multi_level_backend, test_irq_from_device) +{ + /* degenerate cases */ + if (!IS_ENABLED(CONFIG_ASSERT)) { + /* Return 0 if dev not found in the LUT */ + zassert_equal(z_get_sw_isr_irq_from_device(UINT_TO_POINTER(42)), 0); + } + + zassert_equal(z_get_sw_isr_irq_from_device(INTC_1_DEV), INTC_1_IRQN); + zassert_equal(z_get_sw_isr_irq_from_device(INTC_2_DEV), INTC_2_IRQN); + zassert_equal(z_get_sw_isr_irq_from_device(INTC_3_DEV), INTC_3_IRQN); + zassert_equal(z_get_sw_isr_irq_from_device(INTC_4_DEV), INTC_4_IRQN); +} + +ZTEST(intc_multi_level_backend, test_device_from_irq) +{ + /* degenerate cases */ + if (!IS_ENABLED(CONFIG_ASSERT)) { + /* Return NULL if can't find anything to handle the IRQ */ + zassert_equal_ptr(z_get_sw_isr_device_from_irq(IRQ_TO_L2(9) | 8), NULL); + } + + zassert_equal_ptr(z_get_sw_isr_device_from_irq(TEST_IRQN_1), INTC_1_DEV); + zassert_equal_ptr(z_get_sw_isr_device_from_irq(TEST_IRQN_2), INTC_2_DEV); + zassert_equal_ptr(z_get_sw_isr_device_from_irq(TEST_IRQN_3), INTC_3_DEV); + zassert_equal_ptr(z_get_sw_isr_device_from_irq(TEST_IRQN_4), INTC_4_DEV); +} + +ZTEST(intc_multi_level_backend, test_table_idx_from_irq) +{ + /* degenerate cases */ + if (!IS_ENABLED(CONFIG_ASSERT)) { + /* 2nd level aggregator that doesn't exist */ + const unsigned int first_level_agg = 8; + const unsigned int unhandled_irqn = IRQ_TO_L2(TEST_IRQ_1) | first_level_agg; + + zassert_equal(z_get_sw_isr_table_idx(unhandled_irqn), + unhandled_irqn - CONFIG_GEN_IRQ_START_VECTOR); + + /* local_irq exceeded CONFIG_MAX_IRQ_PER_AGGREGATOR */ + const unsigned int local_irq = CONFIG_MAX_IRQ_PER_AGGREGATOR + 1; + const unsigned int overflown_irqn = IRQ_TO_L2(local_irq) | INTC_1_IRQN; + + zassert_equal(z_get_sw_isr_table_idx(overflown_irqn), + local_irq + INTC_1_OFFSET - CONFIG_GEN_IRQ_START_VECTOR); + + /* Overflow SW ISR table */ + const unsigned int local_irq2 = (CONFIG_MAX_IRQ_PER_AGGREGATOR - 1); + const unsigned int overflown_irqn2 = IRQ_TO_L3(local_irq2) | INTC_4_IRQN; + + zassert_equal(z_get_sw_isr_table_idx(overflown_irqn2), + local_irq2 + INTC_4_OFFSET - CONFIG_GEN_IRQ_START_VECTOR); + } + + /* Level 1 */ + zassert_equal(z_get_sw_isr_table_idx(INTC_1_IRQN), + INTC_1_IRQN - CONFIG_GEN_IRQ_START_VECTOR); + zassert_equal(z_get_sw_isr_table_idx(1), 1 - CONFIG_GEN_IRQ_START_VECTOR); + + /* Level 2 */ + zassert_equal(z_get_sw_isr_table_idx(TEST_IRQN_1), + TEST_IRQ_1 + INTC_1_OFFSET - CONFIG_GEN_IRQ_START_VECTOR); + zassert_equal(z_get_sw_isr_table_idx(TEST_IRQN_2), + TEST_IRQ_2 + INTC_2_OFFSET - CONFIG_GEN_IRQ_START_VECTOR); + + /* Level 3 */ + zassert_equal(z_get_sw_isr_table_idx(TEST_IRQN_3), + TEST_IRQ_3 + INTC_3_OFFSET - CONFIG_GEN_IRQ_START_VECTOR); + zassert_equal(z_get_sw_isr_table_idx(TEST_IRQN_4), + TEST_IRQ_4 + INTC_4_OFFSET - CONFIG_GEN_IRQ_START_VECTOR); +} + +static void *setup(void) +{ + DEBUG_PRINT("=============== intc table ===============\n"); + DEBUG_PRINT(" dev | level | irq | offset\n"); + DEBUG_PRINT("==========================================\n"); + STRUCT_SECTION_FOREACH_ALTERNATE(intc_table, _irq_parent_entry, intc) + { + DEBUG_PRINT("%12p | %6u | %6X | %7u\n", intc->dev, intc->level, intc->irq, + intc->offset); + } + DEBUG_PRINT("==========================================\n"); + + return NULL; +} + +ZTEST_SUITE(intc_multi_level_backend, NULL, setup, NULL, NULL, NULL); diff --git a/tests/drivers/interrupt_controller/multi_level_backend/testcase.yaml b/tests/drivers/interrupt_controller/multi_level_backend/testcase.yaml new file mode 100644 index 00000000000000..5f41f8ff071fac --- /dev/null +++ b/tests/drivers/interrupt_controller/multi_level_backend/testcase.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +common: + tags: + - drivers + - interrupt + filter: CONFIG_MULTI_LEVEL_INTERRUPTS and not CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION + arch_allow: + - riscv + - xtensa +tests: + interrupt_controller.intc_multi_level_backend.default: {} + interrupt_controller.intc_multi_level_backend.no_assert: + extra_configs: + - CONFIG_ASSERT=n From 5f88ec4c4ec792285788cdbc3f93148a9e5f3020 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1388/1389] samples: Bluetooth: hci_vs_scan_req: Build for BT_LL_SW_SPLIT only Build the vendor specific sample hci_vs_scan_req for BT_LL_SW_SPLIT variant of the Controller only. Signed-off-by: Vinayak Kariappa Chettimada --- samples/bluetooth/hci_vs_scan_req/sample.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/bluetooth/hci_vs_scan_req/sample.yaml b/samples/bluetooth/hci_vs_scan_req/sample.yaml index 9f2aad6f3637ac..245a83aa0d96af 100644 --- a/samples/bluetooth/hci_vs_scan_req/sample.yaml +++ b/samples/bluetooth/hci_vs_scan_req/sample.yaml @@ -5,8 +5,8 @@ tests: harness: bluetooth platform_allow: - nrf52dk/nrf52832 - - qemu_cortex_m3 - - qemu_x86 - tags: bluetooth integration_platforms: - - qemu_cortex_m3 + - nrf52dk/nrf52832 + extra_configs: + - CONFIG_BT_LL_SW_SPLIT=y + tags: bluetooth From 749052cead8bff0bdefdf9221b4c5e2a8a566f73 Mon Sep 17 00:00:00 2001 From: Mario Paja Date: Sun, 26 May 2024 22:39:42 +0200 Subject: [PATCH 1389/1389] drivers: ethernet: add support for lan9250 This PR adds support for LAN9250 spi ethernet controller. This driver is tested on the Mikroe ETH Click 3 https://www.mikroe.com/eth-3-click Signed-off-by: Mario Paja --- drivers/ethernet/CMakeLists.txt | 1 + drivers/ethernet/Kconfig | 1 + drivers/ethernet/Kconfig.lan9250 | 40 + drivers/ethernet/eth_lan9250.c | 743 +++++++++++++++++++ drivers/ethernet/eth_lan9250_priv.h | 324 ++++++++ dts/bindings/ethernet/microchip,lan9250.yaml | 18 + 6 files changed, 1127 insertions(+) create mode 100644 drivers/ethernet/Kconfig.lan9250 create mode 100644 drivers/ethernet/eth_lan9250.c create mode 100644 drivers/ethernet/eth_lan9250_priv.h create mode 100644 dts/bindings/ethernet/microchip,lan9250.yaml diff --git a/drivers/ethernet/CMakeLists.txt b/drivers/ethernet/CMakeLists.txt index 02b8f96bc9b181..ac51b22511fd9b 100644 --- a/drivers/ethernet/CMakeLists.txt +++ b/drivers/ethernet/CMakeLists.txt @@ -40,6 +40,7 @@ zephyr_library_sources_ifdef(CONFIG_ETH_IVSHMEM eth_ivshmem.c eth_ivshmem_queue zephyr_library_sources_ifdef(CONFIG_ETH_ADIN2111 eth_adin2111.c) zephyr_library_sources_ifdef(CONFIG_ETH_LAN865X eth_lan865x.c oa_tc6.c) zephyr_library_sources_ifdef(CONFIG_ETH_XMC4XXX eth_xmc4xxx.c) +zephyr_library_sources_ifdef(CONFIG_ETH_LAN9250 eth_lan9250.c) if(CONFIG_ETH_NXP_S32_NETC) zephyr_library_sources(eth_nxp_s32_netc.c) diff --git a/drivers/ethernet/Kconfig b/drivers/ethernet/Kconfig index f54d659b7c038f..e98200ef7ebd4d 100644 --- a/drivers/ethernet/Kconfig +++ b/drivers/ethernet/Kconfig @@ -73,6 +73,7 @@ source "drivers/ethernet/Kconfig.adin2111" source "drivers/ethernet/Kconfig.numaker" source "drivers/ethernet/Kconfig.lan865x" source "drivers/ethernet/Kconfig.xmc4xxx" +source "drivers/ethernet/Kconfig.lan9250" source "drivers/ethernet/eth_nxp_enet_qos/Kconfig" diff --git a/drivers/ethernet/Kconfig.lan9250 b/drivers/ethernet/Kconfig.lan9250 new file mode 100644 index 00000000000000..f881fef7c3519d --- /dev/null +++ b/drivers/ethernet/Kconfig.lan9250 @@ -0,0 +1,40 @@ +# LAN9250 Stand-alone Ethernet Controller configuration options + +# Copyright (c) 2024 Mario Paja +# SPDX-License-Identifier: Apache-2.0 + + +menuconfig ETH_LAN9250 + bool "LAN9250 Ethernet Controller" + default y + depends on DT_HAS_MICROCHIP_LAN9250_ENABLED + select SPI + help + LAN9250 Stand-Alone Ethernet Controller + with SPI Interface + +if ETH_LAN9250 + +config ETH_LAN9250_RX_THREAD_STACK_SIZE + int "Stack size for internal incoming packet handler" + default 1024 + help + Size of the stack used for internal thread which is ran for + incoming packet processing. + +config ETH_LAN9250_RX_THREAD_PRIO + int "Priority for internal incoming packet handler" + default 2 + help + Priority level for internal thread which is ran for incoming + packet processing. + +config ETH_LAN9250_TIMEOUT + int "IP buffer timeout" + default 100 + help + Given timeout in milliseconds. Maximum amount of time + that the driver will wait from the IP stack to get + a memory buffer before the Ethernet frame is dropped. + +endif diff --git a/drivers/ethernet/eth_lan9250.c b/drivers/ethernet/eth_lan9250.c new file mode 100644 index 00000000000000..265b130bcfb5b2 --- /dev/null +++ b/drivers/ethernet/eth_lan9250.c @@ -0,0 +1,743 @@ +/* LAN9250 Stand-alone Ethernet Controller with SPI + * + * Copyright (c) 2024 Mario Paja + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT microchip_lan9250 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "eth_lan9250_priv.h" + +LOG_MODULE_REGISTER(eth_lan9250, CONFIG_ETHERNET_LOG_LEVEL); + +static int lan9250_write_sys_reg(const struct device *dev, uint16_t address, uint32_t data) +{ + const struct lan9250_config *config = dev->config; + uint8_t cmd[1 + 2 + 4] = { + LAN9250_SPI_INSTR_WRITE, (address >> 8) & 0xFF, (address & 0xFF), (data & 0xFF), + (data >> 8 & 0xFF), (data >> 16 & 0xFF), (data >> 24 & 0xFF)}; + struct spi_buf tx_buf = { + .buf = &cmd, + .len = ARRAY_SIZE(cmd), + }; + struct spi_buf_set tx_bufs = {.buffers = &tx_buf, .count = 1}; + + return spi_write_dt(&config->spi, &tx_bufs); +} + +static int lan9250_read_sys_reg(const struct device *dev, uint16_t address, uint32_t *value) +{ + const struct lan9250_config *config = dev->config; + uint32_t data; + uint8_t cmd[3] = {LAN9250_SPI_INSTR_READ, (address >> 8) & 0xFF, (address & 0xFF)}; + uint8_t tmp[7]; + + int ret = 0; + + struct spi_buf tx_buf = { + .buf = &cmd, + .len = ARRAY_SIZE(cmd), + }; + struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; + + const struct spi_buf rx_buf = { + .buf = tmp, + .len = ARRAY_SIZE(tmp), + }; + const struct spi_buf_set rx = { + .buffers = &rx_buf, + .count = 1, + }; + + ret |= spi_transceive_dt(&config->spi, &tx, &rx); + + data = tmp[3]; + data |= tmp[4] << 8; + data |= tmp[5] << 16; + data |= tmp[6] << 24; + + *value = data; + + return ret; +} + +static int lan9250_wait_ready(const struct device *dev, uint16_t address, uint32_t mask, + uint32_t expected, uint32_t m_second) +{ + uint32_t tmp; + int wait_time = 0; + + while (true) { + lan9250_read_sys_reg(dev, address, &tmp); + wait_time++; + k_msleep(1); + if ((tmp & mask) == expected) { + return 0; + } else if (wait_time == m_second) { + LOG_ERR("NOT READY"); + return -EIO; + } + } +} + +static int lan9250_read_mac_reg(const struct device *dev, uint8_t address, uint32_t *value) +{ + uint32_t tmp; + + /* Wait for MAC to be ready and send writing register command and data */ + lan9250_wait_ready(dev, LAN9250_MAC_CSR_CMD, LAN9250_MAC_CSR_CMD_BUSY, 0, + LAN9250_MAC_TIMEOUT); + + lan9250_write_sys_reg(dev, LAN9250_MAC_CSR_CMD, + address | LAN9250_MAC_CSR_CMD_BUSY | LAN9250_MAC_CSR_CMD_READ); + + /* Wait for MAC to be ready and send writing register command and data */ + lan9250_wait_ready(dev, LAN9250_MAC_CSR_CMD, LAN9250_MAC_CSR_CMD_BUSY, 0, + LAN9250_MAC_TIMEOUT); + + lan9250_read_sys_reg(dev, LAN9250_MAC_CSR_DATA, &tmp); + + *value = tmp; + return 0; +} + +static int lan9250_write_mac_reg(const struct device *dev, uint8_t address, uint32_t data) +{ + int ret = 0; + + /* Wait for MAC to be ready and send writing register command and data */ + lan9250_wait_ready(dev, LAN9250_MAC_CSR_CMD, LAN9250_MAC_CSR_CMD_BUSY, 0, + LAN9250_MAC_TIMEOUT); + + lan9250_write_sys_reg(dev, LAN9250_MAC_CSR_DATA, data); + + lan9250_write_sys_reg(dev, LAN9250_MAC_CSR_CMD, address | LAN9250_MAC_CSR_CMD_BUSY); + + /* Wait until writing MAC is done */ + lan9250_wait_ready(dev, LAN9250_MAC_CSR_CMD, LAN9250_MAC_CSR_CMD_BUSY, 0, + LAN9250_MAC_TIMEOUT); + + return ret; +} + +static int lan9250_wait_mac_ready(const struct device *dev, uint8_t address, uint32_t mask, + uint32_t expected, uint32_t m_second) +{ + uint32_t tmp; + int wait_time = 0; + + while (true) { + lan9250_read_mac_reg(dev, address, &tmp); + wait_time++; + k_msleep(1); + if ((tmp & mask) == expected) { + return 0; + } else if (wait_time == m_second) { + return -EIO; + } + } +} + +static int lan9250_read_phy_reg(const struct device *dev, uint8_t address, uint16_t *value) +{ + uint32_t tmp; + + /* Wait PHY to be ready and send reading register command */ + lan9250_wait_mac_ready(dev, LAN9250_HMAC_MII_ACC, LAN9250_HMAC_MII_ACC_MIIBZY, 0, + LAN9250_PHY_TIMEOUT); + + lan9250_write_mac_reg(dev, LAN9250_HMAC_MII_ACC, + LAN9250_HMAC_MII_ACC_PHY_ADDR_DEFAULT | + (address << HMACMIIAR_MIIRX_S)); + + /* Wait PHY to be ready and send reading register command */ + lan9250_wait_mac_ready(dev, LAN9250_HMAC_MII_ACC, LAN9250_HMAC_MII_ACC_MIIBZY, 0, + LAN9250_PHY_TIMEOUT); + + lan9250_read_mac_reg(dev, LAN9250_HMAC_MII_DATA, &tmp); + + *value = tmp; + + return 0; +} + +static int lan9250_write_phy_reg(const struct device *dev, uint8_t address, uint16_t data) +{ + /* Wait PHY to be ready and send reading register command */ + lan9250_wait_mac_ready(dev, LAN9250_HMAC_MII_ACC, LAN9250_HMAC_MII_ACC_MIIBZY, 0, + LAN9250_PHY_TIMEOUT); + + lan9250_write_mac_reg(dev, LAN9250_HMAC_MII_DATA, data); + lan9250_write_mac_reg(dev, LAN9250_HMAC_MII_ACC, + (1 << 11) | (address << HMACMIIAR_MIIRX_S) | + LAN9250_HMAC_MII_ACC_MIIW_R); + + /* Wait PHY to be ready and send reading register command */ + lan9250_wait_mac_ready(dev, LAN9250_HMAC_MII_ACC, LAN9250_HMAC_MII_ACC_MIIBZY, 0, + LAN9250_PHY_TIMEOUT); + + return 0; +} + +static int lan9250_set_macaddr(const struct device *dev) +{ + struct lan9250_runtime *ctx = dev->data; + int ret = 0; + + ret |= lan9250_write_mac_reg(dev, LAN9250_HMAC_ADDRL, + ctx->mac_address[0] | (ctx->mac_address[1] << 8) | + (ctx->mac_address[2] << 16) | + (ctx->mac_address[3] << 24)); + + ret |= lan9250_write_mac_reg(dev, LAN9250_HMAC_ADDRH, + ctx->mac_address[4] | (ctx->mac_address[5] << 8)); + + return ret; +} + +static int lan9250_spi_check(const struct device *dev) +{ + uint32_t tmp; + int ret = 0; + uint8_t retries = LAN9250_DEFAULT_NUMOF_RETRIES; + + do { + ret |= lan9250_read_sys_reg(dev, LAN9250_BYTE_TEST, &tmp); + k_busy_wait(USEC_PER_MSEC * 1U); + } while (tmp != LAN9250_BYTE_TEST_DEFAULT && retries--); + + if (tmp != LAN9250_BYTE_TEST_DEFAULT) { + LOG_ERR("Timeout, failed to establish SPI connection"); + return -EIO; + } + + LOG_DBG("SPI OK"); + + return ret; +} + +static int lan9250_hw_cfg_check(const struct device *dev) +{ + uint32_t tmp; + int ret = 0; + + do { + ret |= lan9250_read_sys_reg(dev, LAN9250_HW_CFG, &tmp); + k_busy_wait(USEC_PER_MSEC * 1U); + } while ((tmp & LAN9250_HW_CFG_DEVICE_READY) == 0); + + LOG_DBG("LAN9250_HW_CFG OK"); + + return ret; +} + +static int lan9250_sw_reset(const struct device *dev) +{ + /* Wait until LAN9250 SPI bus is ready */ + + lan9250_wait_ready(dev, LAN9250_BYTE_TEST, BOTR_MASK, LAN9250_BYTE_TEST_DEFAULT, + LAN9250_RESET_TIMEOUT); + + lan9250_write_sys_reg(dev, LAN9250_RESET_CTL, + LAN9250_RESET_CTL_HMAC_RST | LAN9250_RESET_CTL_PHY_RST | + LAN9250_RESET_CTL_DIGITAL_RST); + + lan9250_wait_ready(dev, LAN9250_BYTE_TEST, BOTR_MASK, LAN9250_BYTE_TEST_DEFAULT, + LAN9250_RESET_TIMEOUT); + + return 0; +} + +static int lan9250_reset(const struct device *dev) +{ + lan9250_hw_cfg_check(dev); + lan9250_sw_reset(dev); + + /* Configure TX FIFO size mode to be 8: + * + * - TX data FIFO size: 7680 + * - RX data FIFO size: 7680 + * - TX status FIFO size: 512 + * - RX status FIFO size: 512 + */ + lan9250_write_sys_reg(dev, LAN9250_HW_CFG, + LAN9250_HW_CFG_MBO | LAN9250_HW_CFG_TX_FIF_SZ_8KB); + + /* Configure MAC automatic flow control: + * + * - Automatic flow control high level: 110 + * - Automatic flow control low level: 55 + * - Backpressure duration: 4 + * - Flow control on any frame + */ + + lan9250_write_sys_reg(dev, LAN9250_AFC_CFG, + (110 << HMAFCCFGR_AFCHL_S) | (55 << LAN9250_AFC_CFG_FCMULT) | + (4 << LAN9250_AFC_CFG_FCBRD) | LAN9250_AFC_CFG_FCANY); + + /* Configure host MAC flow control: + * + * - Pause time: 15 + * - Flow control + */ + + lan9250_write_mac_reg(dev, LAN9250_HMAC_FLOW, + (0xf << HMACFCR_PT_S) | LAN9250_HMAC_FLOW_FCEN); + + /* Configure interrupt: + * + * - Interrupt De-assertion interval: 10 + * - Interrupt output to pin + * - Interrupt pin active output low + * - Interrupt pin push-pull driver + */ + + lan9250_write_sys_reg(dev, LAN9250_IRQ_CFG, + LAN9250_IRQ_CFG_INT_DEAS_100US | LAN9250_IRQ_CFG_IRQ_EN | + LAN9250_IRQ_CFG_IRQ_TYPE_PP); + + /* Configure interrupt trigger source, please refer to macro + * LAN9250_INT_SOURCE. + */ + lan9250_write_sys_reg(dev, LAN9250_INT_EN, + LAN9250_INT_EN_PHY_INT_EN | LAN9250_INT_EN_TDFA_EN | + LAN9250_INT_EN_RSFL_EN); + + /* Disable TX data FIFO available interrupt */ + lan9250_write_sys_reg(dev, LAN9250_FIFO_INT, + LAN9250_FIFO_INT_TX_DATA_AVAILABLE_LEVEL | + LAN9250_FIFO_INT_TX_STATUS_LEVEL); + + /* Configure RX: + * + * - RX DMA counter: Ethernet maximum packet size + * - RX data offset: 4, so that need read dummy before reading data + */ + lan9250_write_sys_reg(dev, LAN9250_RX_CFG, (NET_ETH_MAX_FRAME_SIZE << 16) | (4 << 8)); + + /* Configure remote power management: + * + * - Auto wakeup + * - Disable 1588 clock + * - Disable 1588 timestamp unit clock + * - Energy-detect + * - Wake on + * - PME pin push-pull driver + * - Clear wakeon + * - PME active high + * - PME pin + */ + lan9250_write_sys_reg(dev, LAN9250_PMT_CTRL, + LAN9250_PMT_CTRL_PM_WAKE | LAN9250_PMT_CTRL_1588_DIS | + LAN9250_PMT_CTRL_1588_TSU_DIS | LAN9250_PMT_CTRL_ED_EN | + LAN9250_PMT_CTRL_WOL_EN | LAN9250_PMT_CTRL_PME_TYPE | + LAN9250_PMT_CTRL_WOL_STS | LAN9250_PMT_CTRL_PME_POL | + LAN9250_PMT_CTRL_PME_EN); + + /* Configure PHY basic control: + * + * - Auto-Negotiation for 10/100 Mbits and Half/Full Duplex + */ + + lan9250_write_phy_reg(dev, LAN9250_PHY_BASIC_CONTROL, LAN9250_PHY_BASIC_CONTROL_PHY_AN); + + /* Configure PHY auto-negotiation advertisement capability: + * + * - Asymmetric pause + * - Symmetric pause + * - 100Base-X half duplex or full duplex + * - 10Base-X half duplex or full duplex + * - Select IEEE802.3 + */ + lan9250_write_phy_reg( + dev, LAN9250_PHY_AN_ADV, + LAN9250_PHY_AN_ADV_ASYM_PAUSE | LAN9250_PHY_AN_ADV_SYM_PAUSE | + /*LAN9250_PHY_AN_ADV_100BTX_HD |*/ LAN9250_PHY_AN_ADV_100BTX_FD | + /*LAN9250_PHY_AN_ADV_10BT_HD |*/ LAN9250_PHY_AN_ADV_10BT_FD | + LAN9250_PHY_AN_ADV_SELECTOR_DEFAULT); + + /* Configure PHY special mode: + * + * - PHY mode = 111b, enable all capable and auto-nagotiation + * - PHY address = 1, default value is fixed to 1 by manufacturer + */ + + lan9250_write_phy_reg(dev, LAN9250_PHY_SPECIAL_MODES, LAN9250_PHY_SPECIAL_MODES_MODE | 1); + + /* Configure PHY special control or status indication: + * + * - Port auto-MDIX determined by bits 14 and 13 + * - Auto-MDIX + * - Disable SQE tests + */ + + lan9250_write_phy_reg(dev, LAN9250_PHY_SPECIAL_CONTROL_STAT_IND, + LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_AMDIXCTRL | + LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_AMDIXEN | + LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_SQEOFF); + + /* Configure PHY interrupt source: + * + * - Link up + * - Link down + */ + lan9250_write_phy_reg(dev, LAN9250_PHY_INTERRUPT_MASK, + LAN9250_PHY_INTERRUPT_SOURCE_LINK_UP | + LAN9250_PHY_INTERRUPT_SOURCE_LINK_DOWN); + + /* Configure special control or status: + * + * - Fixed to write 0000010b to reserved filed + */ + + lan9250_write_phy_reg(dev, LAN9250_PHY_SPECIAL_CONTROL_STATUS, + LAN9250_PHY_MODE_CONTROL_STATUS_ALTINT); + + /* Clear interrupt status */ + lan9250_write_sys_reg(dev, LAN9250_INT_STS, 0xFFFFFFFF); + + /* Configure HMAC control: + * + * - Automatically strip the pad field on incoming packets + * - TX enable + * - RX enable + * - Full duplex + */ + lan9250_write_mac_reg(dev, LAN9250_HMAC_CR, + LAN9250_HMAC_CR_PADSTR | LAN9250_HMAC_CR_TXEN | LAN9250_HMAC_CR_RXEN | + LAN9250_HMAC_CR_FDPX); + + /** Configure TX: + * + * - TX enable + */ + lan9250_write_sys_reg(dev, LAN9250_TX_CFG, LAN9250_TX_CFG_TX_ON); + + return 0; +} + +static int lan9250_write_buf(const struct device *dev, uint8_t *data_buffer, uint16_t buf_len) +{ + const struct lan9250_config *config = dev->config; + int ret = 0; + uint8_t cmd[3] = {LAN9250_SPI_INSTR_WRITE, (LAN9250_TX_DATA_FIFO >> 8) & 0xFF, + (LAN9250_TX_DATA_FIFO & 0xFF)}; + + struct spi_buf tx_buf[2]; + + tx_buf[0].buf = &cmd; + tx_buf[0].len = ARRAY_SIZE(cmd); + + tx_buf[1].buf = data_buffer; + tx_buf[1].len = buf_len; + + struct spi_buf_set tx = {.buffers = tx_buf, .count = 2}; + + ret |= spi_transceive_dt(&config->spi, &tx, NULL); + + return ret; +} + +static int lan9250_read_buf(const struct device *dev, uint8_t *data_buffer, uint16_t buf_len) +{ + const struct lan9250_config *config = dev->config; + uint8_t cmd[3] = {LAN9250_SPI_INSTR_READ, (LAN9250_RX_DATA_FIFO >> 8) & 0xFF, + (LAN9250_RX_DATA_FIFO & 0xFF)}; + + int ret = 0; + + struct spi_buf tx_buf = { + .buf = &cmd, + .len = ARRAY_SIZE(cmd), + }; + struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; + + struct spi_buf rx_buf[2]; + + rx_buf[0].buf = NULL; + rx_buf[0].len = 3; + + rx_buf[1].buf = data_buffer; + rx_buf[1].len = buf_len; + + const struct spi_buf_set rx = {.buffers = rx_buf, .count = 2}; + + ret |= spi_transceive_dt(&config->spi, &tx, &rx); + + return ret; +} + +static int lan9250_rx(const struct device *dev) +{ + const struct lan9250_config *config = dev->config; + struct lan9250_runtime *ctx = dev->data; + uint8_t pktcnt; + uint32_t tmp; + uint16_t pkt_len; + uint16_t lengthfr; + + /* Check valid packet count in RX FIFO */ + lan9250_read_sys_reg(dev, LAN9250_RX_FIFO_INF, &tmp); + pktcnt = (tmp & LAN9250_RX_FIFO_INF_RXSUSED) >> 16; + + if (!pktcnt) { + return 0; + } + + k_sem_take(&ctx->tx_rx_sem, K_FOREVER); + + while (pktcnt--) { + + /* Get the length of the packet */ + lan9250_read_sys_reg(dev, LAN9250_RX_STATUS_FIFO, &tmp); + + pkt_len = (tmp & LAN9250_RX_STS_PACKET_LEN) >> 16; + pkt_len -= 4; + lengthfr = pkt_len; + + struct net_buf *pkt_buf; + struct net_pkt *pkt; + + /* Get the frame from the buffer */ + pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, pkt_len, AF_UNSPEC, 0, + K_MSEC(config->timeout)); + if (!pkt) { + LOG_ERR("%s: Could not allocate rx buffer", dev->name); + eth_stats_update_errors_rx(ctx->iface); + return 0; + } + + pkt_buf = pkt->buffer; + + lan9250_read_sys_reg(dev, LAN9250_RX_DATA_FIFO, &tmp); + + do { + + size_t frag_len; + uint8_t *data_ptr; + size_t spi_frame_len; + + data_ptr = pkt_buf->data; + + /* Review the space available for the new frag */ + frag_len = net_buf_tailroom(pkt_buf); + + if (pkt_len > frag_len) { + spi_frame_len = frag_len; + } else { + spi_frame_len = pkt_len; + } + + /* Review the space available for the new frag */ + lan9250_read_buf(dev, data_ptr, spi_frame_len); + net_buf_add(pkt_buf, pkt_len); + + pkt_len -= spi_frame_len; + pkt_buf = pkt_buf->frags; + + } while (pkt_len > 0); + + uint8_t dummy[4]; + + lan9250_read_buf(dev, dummy, 4); + + net_pkt_set_iface(pkt, ctx->iface); + + /* Feed buffer frame to IP stack */ + if (net_recv_data(net_pkt_iface(pkt), pkt) < 0) { + net_pkt_unref(pkt); + } + } + + k_sem_give(&ctx->tx_rx_sem); + + return 0; +} + +static int lan9250_tx(const struct device *dev, struct net_pkt *pkt) +{ + struct lan9250_runtime *ctx = dev->data; + size_t len = net_pkt_get_len(pkt); + + LOG_DBG("%s: pkt %p (len %u)", dev->name, pkt, len); + + uint32_t regval; + uint16_t free_size; + uint8_t status_size; + + lan9250_read_sys_reg(dev, LAN9250_TX_FIFO_INF, ®val); + + status_size = (regval & LAN9250_TX_FIFO_INF_TXSUSED) >> 16; + free_size = regval & LAN9250_TX_FIFO_INF_TXFREE; + + LOG_DBG("status_size:%d, free_size:%d", status_size, free_size); + + /* Clear TX status FIFO if it is no empty by reading data */ + + uint32_t tmp; + + for (int i = 0; i < status_size; i++) { + lan9250_read_sys_reg(dev, LAN9250_TX_STATUS_FIFO, &tmp); + } + + k_sem_take(&ctx->tx_rx_sem, K_FOREVER); + + /* TX command 'A' */ + lan9250_write_sys_reg(dev, LAN9250_TX_DATA_FIFO, + LAN9250_TX_CMD_A_INT_ON_COMP | LAN9250_TX_CMD_A_BUFFER_ALIGN_4B | + LAN9250_TX_CMD_A_START_OFFSET_0B | + LAN9250_TX_CMD_A_FIRST_SEG | LAN9250_TX_CMD_A_LAST_SEG | len); + + /* TX command 'B' */ + lan9250_write_sys_reg(dev, LAN9250_TX_DATA_FIFO, LAN9250_TX_CMD_B_PACKET_TAG | len); + + if (net_pkt_read(pkt, ctx->buf, len)) { + return -EIO; + } + + lan9250_write_buf(dev, ctx->buf, LAN9250_ALIGN(len)); + + k_sem_give(&ctx->tx_rx_sem); + + return 0; +} + +static void lan9250_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) +{ + struct lan9250_runtime *context = CONTAINER_OF(cb, struct lan9250_runtime, gpio_cb); + + k_sem_give(&context->int_sem); +} + +static void lan9250_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct lan9250_runtime *context = p1; + uint32_t isr; + uint16_t tmp; + + while (true) { + k_sem_take(&context->int_sem, K_FOREVER); + lan9250_read_sys_reg(context->dev, LAN9250_INT_STS, &isr); + + if ((isr & LAN9250_INT_STS_PHY_INT) != 0) { + /* Read PHY interrupt source register */ + lan9250_read_phy_reg(context->dev, LAN9250_PHY_INTERRUPT_SOURCE, &tmp); + + if (tmp & LAN9250_PHY_INTERRUPT_SOURCE_LINK_UP) { + LOG_DBG("LINK UP"); + net_eth_carrier_on(context->iface); + } else if (tmp & LAN9250_PHY_INTERRUPT_SOURCE_LINK_DOWN) { + LOG_DBG("LINK DOWN"); + net_eth_carrier_off(context->iface); + } + } + + if ((isr & LAN9250_INT_STS_RSFL) != 0) { + + lan9250_rx(context->dev); + } + + lan9250_write_sys_reg(context->dev, LAN9250_INT_STS, isr); + } +} + +static enum ethernet_hw_caps lan9250_get_capabilities(const struct device *dev) +{ + ARG_UNUSED(dev); + + return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T; +} + +static void lan9250_iface_init(struct net_if *iface) +{ + const struct device *dev = net_if_get_device(iface); + struct lan9250_runtime *context = dev->data; + + net_if_set_link_addr(iface, context->mac_address, sizeof(context->mac_address), + NET_LINK_ETHERNET); + context->iface = iface; + ethernet_init(iface); + + net_if_carrier_off(iface); +} + +static const struct ethernet_api api_funcs = { + .iface_api.init = lan9250_iface_init, + .get_capabilities = lan9250_get_capabilities, + .send = lan9250_tx, +}; + +static int lan9250_init(const struct device *dev) +{ + const struct lan9250_config *config = dev->config; + struct lan9250_runtime *context = dev->data; + + context->dev = dev; + + /* SPI config */ + if (!spi_is_ready_dt(&config->spi)) { + LOG_ERR("SPI master port %s not ready", config->spi.bus->name); + return -EINVAL; + } + + /* Initialize GPIO */ + if (!gpio_is_ready_dt(&config->interrupt)) { + LOG_ERR("GPIO port %s not ready", config->interrupt.port->name); + return -EINVAL; + } + + if (gpio_pin_configure_dt(&config->interrupt, GPIO_INPUT)) { + LOG_ERR("Unable to configure GPIO pin %u", config->interrupt.pin); + return -EINVAL; + } + + gpio_init_callback(&(context->gpio_cb), lan9250_gpio_callback, BIT(config->interrupt.pin)); + + if (gpio_add_callback(config->interrupt.port, &(context->gpio_cb))) { + return -EINVAL; + } + + gpio_pin_interrupt_configure_dt(&config->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + + lan9250_spi_check(dev); + lan9250_reset(dev); + + lan9250_set_macaddr(dev); + + k_thread_create(&context->thread, context->thread_stack, + CONFIG_ETH_LAN9250_RX_THREAD_STACK_SIZE, lan9250_thread, context, NULL, + NULL, K_PRIO_COOP(CONFIG_ETH_LAN9250_RX_THREAD_PRIO), 0, K_NO_WAIT); + + LOG_INF("LAN9250 Initialized"); + + return 0; +} + +static struct lan9250_runtime lan9250_0_runtime = { + .mac_address = DT_INST_PROP(0, local_mac_address), + .tx_rx_sem = Z_SEM_INITIALIZER(lan9250_0_runtime.tx_rx_sem, 1, UINT_MAX), + .int_sem = Z_SEM_INITIALIZER(lan9250_0_runtime.int_sem, 0, UINT_MAX), +}; + +static const struct lan9250_config lan9250_0_config = { + .spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8), 0), + .interrupt = GPIO_DT_SPEC_INST_GET(0, int_gpios), + .timeout = CONFIG_ETH_LAN9250_TIMEOUT, +}; + +ETH_NET_DEVICE_DT_INST_DEFINE(0, lan9250_init, NULL, &lan9250_0_runtime, &lan9250_0_config, + CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU); diff --git a/drivers/ethernet/eth_lan9250_priv.h b/drivers/ethernet/eth_lan9250_priv.h new file mode 100644 index 00000000000000..b0d10a1c465df7 --- /dev/null +++ b/drivers/ethernet/eth_lan9250_priv.h @@ -0,0 +1,324 @@ +/* LAN9250 Stand-alone Ethernet Controller with SPI + * + * Copyright (c) 2024 Mario Paja + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#ifndef _LAN9250_ +#define _LAN9250_ + +#define LAN9250_DEFAULT_NUMOF_RETRIES 3U +#define LAN9250_PHY_TIMEOUT 2000 +#define LAN9250_MAC_TIMEOUT 2000 +#define LAN9250_RESET_TIMEOUT 5000 + +#define LAN9250_ALIGN(v) (((v) + 3) & (~3)) + + /* SPI instructions */ +#define LAN9250_SPI_INSTR_WRITE 0x02 +#define LAN9250_SPI_INSTR_READ 0x03 + +/* TX command 'A' format */ +#define LAN9250_TX_CMD_A_INT_ON_COMP 0x80000000 +#define LAN9250_TX_CMD_A_BUFFER_ALIGN_4B 0x00000000 +#define LAN9250_TX_CMD_A_START_OFFSET_0B 0x00000000 +#define LAN9250_TX_CMD_A_FIRST_SEG 0x00002000 +#define LAN9250_TX_CMD_A_LAST_SEG 0x00001000 + +/* TX command 'B' format */ +#define LAN9250_TX_CMD_B_PACKET_TAG 0xFFFF0000 + +/* RX status format */ +#define LAN9250_RX_STS_PACKET_LEN 0x3FFF0000 + +/* LAN9250 System registers */ +#define LAN9250_RX_DATA_FIFO 0x0000 +#define LAN9250_TX_DATA_FIFO 0x0020 +#define LAN9250_RX_STATUS_FIFO 0x0040 +#define LAN9250_TX_STATUS_FIFO 0x0048 +#define LAN9250_IRQ_CFG 0x0054 +#define LAN9250_INT_STS 0x0058 +#define LAN9250_INT_EN 0x005C +#define LAN9250_BYTE_TEST 0x0064 +#define LAN9250_FIFO_INT 0x0068 +#define LAN9250_RX_CFG 0x006C +#define LAN9250_TX_CFG 0x0070 +#define LAN9250_HW_CFG 0x0074 +#define LAN9250_RX_FIFO_INF 0x007C +#define LAN9250_TX_FIFO_INF 0x0080 +#define LAN9250_PMT_CTRL 0x0084 +#define LAN9250_MAC_CSR_CMD 0x00A4 +#define LAN9250_MAC_CSR_DATA 0x00A8 +#define LAN9250_AFC_CFG 0x00AC +#define LAN9250_RESET_CTL 0x01F8 + +/* LAN9250 Host MAC registers */ +#define LAN9250_HMAC_CR 0x01 +#define LAN9250_HMAC_ADDRH 0x02 +#define LAN9250_HMAC_ADDRL 0x03 +#define LAN9250_HMAC_MII_ACC 0x06 +#define LAN9250_HMAC_MII_DATA 0x07 +#define LAN9250_HMAC_FLOW 0x08 + +/* LAN9250 PHY registers */ +#define LAN9250_PHY_BASIC_CONTROL 0x00 +#define LAN9250_PHY_AN_ADV 0x04 +#define LAN9250_PHY_SPECIAL_MODES 0x12 +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND 0x1B +#define LAN9250_PHY_INTERRUPT_SOURCE 0x1D +#define LAN9250_PHY_INTERRUPT_MASK 0x1E +#define LAN9250_PHY_SPECIAL_CONTROL_STATUS 0x1F + +/* Interrupt Configuration register */ +#define LAN9250_IRQ_CFG_INT_DEAS_100US 0x0A000000 +#define LAN9250_IRQ_CFG_IRQ_EN 0x00000100 +#define LAN9250_IRQ_CFG_IRQ_TYPE_PP 0x00000001 + +/* Interrupt Status register */ +#define LAN9250_INT_STS_PHY_INT 0x04000000 +#define LAN9250_INT_STS_RSFL 0x00000008 + +/* Interrupt Enable register */ +#define LAN9250_INT_EN_PHY_INT_EN 0x04000000 +#define LAN9250_INT_EN_TDFA_EN 0x00000200 +#define LAN9250_INT_EN_RSFL_EN 0x00000008 + +/* Byte Order Test register */ +#define LAN9250_BYTE_TEST_DEFAULT 0x87654321 +#define BOTR_MASK 0xffffffff + +/* FIFO Level Interrupt register */ +#define LAN9250_FIFO_INT_TX_DATA_AVAILABLE_LEVEL 0xFF000000 +#define LAN9250_FIFO_INT_TX_STATUS_LEVEL 0x00FF0000 +#define LAN9250_FIFO_INT_RX_STATUS_LEVEL 0x000000FF + +/* Transmit Configuration register*/ +#define LAN9250_TX_CFG_TXS_DUMP 0x00008000 +#define LAN9250_TX_CFG_TXD_DUMP 0x00004000 +#define LAN9250_TX_CFG_TXSAO 0x00000004 +#define LAN9250_TX_CFG_TX_ON 0x00000002 +#define LAN9250_TX_CFG_STOP_TX 0x00000001 + +/* Hardware Configuration register */ +#define LAN9250_HW_CFG_DEVICE_READY 0x08000000 +#define LAN9250_HW_CFG_AMDIX_EN_STRAP_STATE 0x02000000 +#define LAN9250_HW_CFG_MBO 0x00100000 +#define LAN9250_HW_CFG_TX_FIF_SZ 0x000F0000 +#define LAN9250_HW_CFG_TX_FIF_SZ_2KB 0x00020000 +#define LAN9250_HW_CFG_TX_FIF_SZ_3KB 0x00030000 +#define LAN9250_HW_CFG_TX_FIF_SZ_4KB 0x00040000 +#define LAN9250_HW_CFG_TX_FIF_SZ_5KB 0x00050000 +#define LAN9250_HW_CFG_TX_FIF_SZ_6KB 0x00060000 +#define LAN9250_HW_CFG_TX_FIF_SZ_7KB 0x00070000 +#define LAN9250_HW_CFG_TX_FIF_SZ_8KB 0x00080000 +#define LAN9250_HW_CFG_TX_FIF_SZ_9KB 0x00090000 +#define LAN9250_HW_CFG_TX_FIF_SZ_10KB 0x000A0000 +#define LAN9250_HW_CFG_TX_FIF_SZ_11KB 0x000B0000 +#define LAN9250_HW_CFG_TX_FIF_SZ_12KB 0x000C0000 +#define LAN9250_HW_CFG_TX_FIF_SZ_13KB 0x000D0000 +#define LAN9250_HW_CFG_TX_FIF_SZ_14KB 0x000E0000 + +/* RX FIFO Information register */ +#define LAN9250_RX_FIFO_INF_RXSUSED 0x00FF0000 +#define LAN9250_RX_FIFO_INF_RXDUSED 0x0000FFFF + +/* TX FIFO Information register */ +#define LAN9250_TX_FIFO_INF_TXSUSED 0x00FF0000 +#define LAN9250_TX_FIFO_INF_TXFREE 0x0000FFFF + +/* Power Management Control register */ +#define LAN9250_PMT_CTRL_PM_MODE 0xE0000000 +#define LAN9250_PMT_CTRL_PM_SLEEP_EN 0x10000000 +#define LAN9250_PMT_CTRL_PM_WAKE 0x08000000 +#define LAN9250_PMT_CTRL_LED_DIS 0x04000000 +#define LAN9250_PMT_CTRL_1588_DIS 0x02000000 +#define LAN9250_PMT_CTRL_1588_TSU_DIS 0x00400000 +#define LAN9250_PMT_CTRL_HMAC_DIS 0x00080000 +#define LAN9250_PMT_CTRL_HMAC_SYS_ONLY_DIS 0x00040000 +#define LAN9250_PMT_CTRL_ED_STS 0x00010000 +#define LAN9250_PMT_CTRL_ED_EN 0x00004000 +#define LAN9250_PMT_CTRL_WOL_EN 0x00000200 +#define LAN9250_PMT_CTRL_PME_TYPE 0x00000040 +#define LAN9250_PMT_CTRL_WOL_STS 0x00000020 +#define LAN9250_PMT_CTRL_PME_IND 0x00000008 +#define LAN9250_PMT_CTRL_PME_POL 0x00000004 +#define LAN9250_PMT_CTRL_PME_EN 0x00000002 +#define LAN9250_PMT_CTRL_READY 0x00000001 + +/* General Purpose Timer Configuration register */ +#define LAN9250_GPT_CFG_TIMER_EN 0x20000000 +#define LAN9250_GPT_CFG_GPT_LOAD 0x0000FFFF + +/* General Purpose Timer Count register */ +#define LAN9250_GPT_CNT_GPT_CNT 0x0000FFFF + +/* Free Running 25MHz Counter register */ +#define LAN9250_FREE_RUN_FR_CNT 0xFFFFFFFF + +/* Host MAC RX Dropped Frames Counter register */ +#define LAN9250_RX_DROP_RX_DFC 0xFFFFFFFF + +/* Host MAC CSR Interface Command register */ +#define LAN9250_MAC_CSR_CMD_BUSY 0x80000000 +#define LAN9250_MAC_CSR_CMD_WRITE 0x00000000 +#define LAN9250_MAC_CSR_CMD_READ 0x40000000 +#define LAN9250_MAC_CSR_CMD_ADDR 0x000000FF + +/* Host MAC Automatic Flow Control Configuration register */ +#define LAN9250_AFC_CFG_AFC_HI 0x00FF0000 +#define HMAFCCFGR_AFCHL_S 16 +#define LAN9250_AFC_CFG_AFC_LO 0x0000FF00 +#define LAN9250_AFC_CFG_BACK_DUR 0x000000F0 +#define LAN9250_AFC_CFG_FCMULT 0x00000008 +#define LAN9250_AFC_CFG_FCBRD 0x00000004 +#define LAN9250_AFC_CFG_FCADD 0x00000002 +#define LAN9250_AFC_CFG_FCANY 0x00000001 + +/* Reset Control register */ +#define LAN9250_RESET_CTL_HMAC_RST 0x00000020 +#define LAN9250_RESET_CTL_PHY_RST 0x00000002 +#define LAN9250_RESET_CTL_DIGITAL_RST 0x00000001 + +/* Host MAC Control register */ +#define LAN9250_HMAC_CR_RXALL 0x80000000 +#define LAN9250_HMAC_CR_HMAC_EEE_ENABLE 0x02000000 +#define LAN9250_HMAC_CR_RCVOWN 0x00800000 +#define LAN9250_HMAC_CR_LOOPBK 0x00200000 +#define LAN9250_HMAC_CR_FDPX 0x00100000 +#define LAN9250_HMAC_CR_MCPAS 0x00080000 +#define LAN9250_HMAC_CR_PRMS 0x00040000 +#define LAN9250_HMAC_CR_INVFILT 0x00020000 +#define LAN9250_HMAC_CR_PASSBAD 0x00010000 +#define LAN9250_HMAC_CR_HO 0x00008000 +#define LAN9250_HMAC_CR_HPFILT 0x00002000 +#define LAN9250_HMAC_CR_BCAST 0x00000800 +#define LAN9250_HMAC_CR_DISRTY 0x00000400 +#define LAN9250_HMAC_CR_PADSTR 0x00000100 +#define LAN9250_HMAC_CR_BOLMT 0x000000C0 +#define LAN9250_HMAC_CR_BOLMT_10_BITS 0x00000000 +#define LAN9250_HMAC_CR_BOLMT_8_BITS 0x00000040 +#define LAN9250_HMAC_CR_BOLMT_4_BITS 0x00000080 +#define LAN9250_HMAC_CR_BOLMT_1_BIT 0x000000C0 +#define LAN9250_HMAC_CR_DFCHK 0x00000020 +#define LAN9250_HMAC_CR_TXEN 0x00000008 +#define LAN9250_HMAC_CR_RXEN 0x00000004 + +/* Host MAC Address High register */ +#define LAN9250_HMAC_ADDRH_PHY_ADR_47_32 0x0000FFFF + +/* Host MAC Address Low register */ +#define LAN9250_HMAC_ADDRL_PHY_ADR_31_0 0xFFFFFFFF + +/* Host MAC MII Access register */ +#define LAN9250_HMAC_MII_ACC_PHY_ADDR 0x0000F800 +#define LAN9250_HMAC_MII_ACC_PHY_ADDR_DEFAULT 0x00000800 +#define LAN9250_HMAC_MII_ACC_MIIRINDA 0x000007C0 +#define HMACMIIAR_MIIRX_S 6 +#define LAN9250_HMAC_MII_ACC_MIIW_R 0x00000002 +#define LAN9250_HMAC_MII_ACC_MIIBZY 0x00000001 + +/* Host MAC MII Data register */ +#define LAN9250_HMAC_MII_DATA_MII_DATA 0x0000FFFF + +/* Host MAC Flow Control register */ +#define LAN9250_HMAC_FLOW_FCPT 0xFFFF0000 +#define HMACFCR_PT_S 16 +#define LAN9250_HMAC_FLOW_FCPASS 0x00000004 +#define LAN9250_HMAC_FLOW_FCEN 0x00000002 +#define LAN9250_HMAC_FLOW_FCBSY 0x00000001 + +/* PHY Basic Control register */ +#define LAN9250_PHY_BASIC_CONTROL_PHY_SRST 0x8000 +#define LAN9250_PHY_BASIC_CONTROL_PHY_LOOPBACK 0x4000 +#define LAN9250_PHY_BASIC_CONTROL_PHY_SPEED_SEL_LSB 0x2000 +#define LAN9250_PHY_BASIC_CONTROL_PHY_AN 0x1000 +#define LAN9250_PHY_BASIC_CONTROL_PHY_PWR_DWN 0x0800 +#define LAN9250_PHY_BASIC_CONTROL_PHY_RST_AN 0x0200 +#define LAN9250_PHY_BASIC_CONTROL_PHY_DUPLEX 0x0100 +#define LAN9250_PHY_BASIC_CONTROL_PHY_COL_TEST 0x0080 + + +/* PHY Auto-Negotiation Advertisement register */ +#define LAN9250_PHY_AN_ADV_NEXT_PAGE 0x8000 +#define LAN9250_PHY_AN_ADV_REMOTE_FAULT 0x2000 +#define LAN9250_PHY_AN_ADV_EXTENDED_NEXT_PAGE 0x1000 +#define LAN9250_PHY_AN_ADV_ASYM_PAUSE 0x0800 +#define LAN9250_PHY_AN_ADV_SYM_PAUSE 0x0400 +#define LAN9250_PHY_AN_ADV_100BTX_FD 0x0100 +#define LAN9250_PHY_AN_ADV_100BTX_HD 0x0080 +#define LAN9250_PHY_AN_ADV_10BT_FD 0x0040 +#define LAN9250_PHY_AN_ADV_10BT_HD 0x0020 +#define LAN9250_PHY_AN_ADV_SELECTOR 0x001F +#define LAN9250_PHY_AN_ADV_SELECTOR_DEFAULT 0x0001 + +/* PHY Mode Control/Status register */ +#define LAN9250_PHY_MODE_CONTROL_STATUS_ALTINT 0x0040 + + +/* PHY Special Modes register */ +#define LAN9250_PHY_SPECIAL_MODES_FX_MODE 0x0400 +#define LAN9250_PHY_SPECIAL_MODES_MODE 0x00E0 +#define LAN9250_PHY_SPECIAL_MODES_MODE_10BT_HD 0x0000 +#define LAN9250_PHY_SPECIAL_MODES_MODE_10BT_FD 0x0020 +#define LAN9250_PHY_SPECIAL_MODES_MODE_100BTX_HD 0x0040 +#define LAN9250_PHY_SPECIAL_MODES_MODE_100BTX_FD 0x0060 +#define LAN9250_PHY_SPECIAL_MODES_MODE_POWER_DOWN 0x00C0 +#define LAN9250_PHY_SPECIAL_MODES_MODE_AN 0x00E0 +#define LAN9250_PHY_SPECIAL_MODES_PHYADD 0x001F + + +/* PHY Special Control/Status Indication register */ +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_AMDIXCTRL 0x8000 +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_AMDIXEN 0x4000 +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_AMDIXSTATE 0x2000 +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_SQEOFF 0x0800 +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_FEFI_EN 0x0020 +#define LAN9250_PHY_SPECIAL_CONTROL_STAT_IND_XPOL 0x0010 + +/* PHY Interrupt Source Flags register */ +#define LAN9250_PHY_INTERRUPT_SOURCE_LINK_UP 0x0200 +#define LAN9250_PHY_INTERRUPT_SOURCE_ENERGYON 0x0080 +#define LAN9250_PHY_INTERRUPT_SOURCE_AN_COMPLETE 0x0040 +#define LAN9250_PHY_INTERRUPT_SOURCE_REMOTE_FAULT 0x0020 +#define LAN9250_PHY_INTERRUPT_SOURCE_LINK_DOWN 0x0010 +#define LAN9250_PHY_INTERRUPT_SOURCE_AN_LP_ACK 0x0008 +#define LAN9250_PHY_INTERRUPT_SOURCE_PARALLEL_DETECT_FAULT 0x0004 +#define LAN9250_PHY_INTERRUPT_SOURCE_AN_PAGE_RECEIVED 0x0002 + +/* PHY Interrupt Mask register */ +#define LAN9250_PHY_INTERRUPT_MASK_LINK_UP 0x0200 +#define LAN9250_PHY_INTERRUPT_MASK_ENERGYON 0x0080 +#define LAN9250_PHY_INTERRUPT_MASK_AN_COMPLETE 0x0040 +#define LAN9250_PHY_INTERRUPT_MASK_REMOTE_FAULT 0x0020 +#define LAN9250_PHY_INTERRUPT_MASK_LINK_DOWN 0x0010 +#define LAN9250_PHY_INTERRUPT_MASK_AN_LP_ACK 0x0008 +#define LAN9250_PHY_INTERRUPT_MASK_PARALLEL_DETECT_FAULT 0x0004 +#define LAN9250_PHY_INTERRUPT_MASK_AN_PAGE_RECEIVED 0x0002 + +struct lan9250_config { + struct spi_dt_spec spi; + struct gpio_dt_spec interrupt; + uint8_t full_duplex; + int32_t timeout; +}; + +struct lan9250_runtime { + struct net_if *iface; + const struct device *dev; + + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ETH_LAN9250_RX_THREAD_STACK_SIZE); + + struct k_thread thread; + uint8_t mac_address[6]; + struct gpio_callback gpio_cb; + struct k_sem tx_rx_sem; + struct k_sem int_sem; + uint8_t buf[NET_ETH_MAX_FRAME_SIZE]; +}; + +#endif /*_LAN9250_*/ diff --git a/dts/bindings/ethernet/microchip,lan9250.yaml b/dts/bindings/ethernet/microchip,lan9250.yaml new file mode 100644 index 00000000000000..5f64875994474e --- /dev/null +++ b/dts/bindings/ethernet/microchip,lan9250.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024, Mario Paja +# SPDX-License-Identifier: Apache-2.0 + +description: | + LAN9250 standalone 10/100BASE-T Ethernet controller with SPI interface + +compatible: "microchip,lan9250" + +include: [spi-device.yaml, ethernet-controller.yaml] + +properties: + int-gpios: + type: phandle-array + required: true + description: | + The interrupt pin of LAN9250 is active low. + If connected directly the MCU pin should be configured + as active low.